Advertisement
wallyweek

Interface I programming in assembly

Oct 2nd, 2017
474
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 375.42 KB | None | 0 0
  1. CONTENTS
  2.  
  3.  
  4. INTRODUCTION
  5.  
  6. USE OF HOOK CODES
  7.  
  8. EXTENSIONS TO BASIC
  9. Basic loader program
  10. Assembler Listings
  11. Main program
  12. A simple ‘double POKE’ routine: POKE * x,y
  13. Pokeing strings into memory: POKE n,”s”
  14. Memory dump: *L n
  15. Modified EDIT function: *E n
  16. An improved sound command: BEEP *a,b,c,d
  17. A faster and more complete catalogue: * CAT n
  18. Pseudo—random file handling: READ #S,N
  19. Adding data to a file: RESTORE #S
  20. Extending the RS—232 channel
  21. Extending Spectrum BASIC
  22.  
  23. THE SHADOW ROM DISASSEMBLY
  24.  
  25. The restart routines
  26. The control routine
  27. The syntax checking routines
  28. The RS—232 link routines
  29. The Network routines
  30. The Microdrive routines
  31. The ‘Hook code’ routines
  32. The Microdrive command routines
  33. The ‘not used’ routines
  34.  
  35. APPENDIX
  36.  
  37. Labels sorted by address value
  38. Labels sorted alphabetically
  39. ‘Shadow’ system variables
  40. Channels
  41. Bibliography
  42. Index to routines
  43. Shadow ROM issue 2
  44. How to tell which edition Interface 1 you have
  45. Basic loader program for edition 2 Shadow ROM
  46. Extended BASIC commands from assembler
  47. for edition 2 Shadow ROM
  48. What to do if you have an unknown ROM
  49. INTRODUCTION
  50.  
  51. The Sinclair ZX Interface I adds enormously to the power of the ZX Spectrum, allowing it to send and receive data over \
  52. an RS—232 link, to use the Local Area Network, and to store information on the Microdrives. Equally impressive is its \
  53. ability to expand the BASIC provided with the computer, adding new and powerful commands. Much of this power is due to \
  54. the 8K monitor program which is housed in an 8K Read Only Memory in the Interface 1.
  55.  
  56. This ROM, which is kept between memory adresses 0000H and 1FFFH is "paged" back and forth with the main ROM so that \
  57. both ROMs appear to occupy the same section of memory.
  58.  
  59. This book provides a complete listing of this program, fully commented and explained, permitting you to use these \
  60. routines in your programs. In addition, many examples are given of how to expand the Spectrum's BASIC by using the \
  61. Interface 1 to define new commands.
  62.  
  63. I feel that this book should be of interest to all users of the Interface 1. Those without experience in machine code \
  64. programming can use the new BASIC commands provided, whether or not they own an assembler. More ambitious programmers \
  65. will find numerous hints for the creation of the their own routines, and the algorithms controlling the Microdrive, \
  66. the RS—232 link, and the Local Area Network will be of interest to even the most expert programmer.
  67.  
  68. I should like, finally, to thank Massimiliano, Carlo, Giovanna, Sylvia, and Mr. Alfred Milgrom (of Melbourne House \
  69. Ltd.). A special thanks must go to the entire staff of Sinclair Research Ltd.
  70.  
  71. Gianluca Carri
  72. Florence, Italy,
  73. January 1985.
  74.  
  75.  
  76. USE OF HOOK CODES
  77.  
  78. While the disassembly of the ROM given here will be a valuable aid to machine code programmers wishing to use the \
  79. Interface I, there is one problem: Sinclair Research have not used the same ROM in every Interface 1. There are two \
  80. different editions of the ROM. Each, of course, does the same job of running the Microdrives, the RS—232 interface, \
  81. and the Local Area Network, but there are a number of minor differences in the actual code contained in the ROMs. The \
  82. differences between the two editions are described in appendix 7.
  83. Does this mean that we can never rely on being able to write programs that can run on all machines? Far from it. \
  84. Sinclair Research have provided a way to access a number of the ROM routines in a way which can be guaranteed to work \
  85. on all machines. To do this, we use what are called hook codes. These consist of a RST 8 instruction followed by a \
  86. byte whose value depends on which hook code you are using. Their effect is to page the ROM in, call a routine in the \
  87. Interface 1's 'shadow ROM', then page the main ROM back in and return control to the users program. This provides \
  88. 'transparant' access to the Interface 1 — the user doesn't need to know anything about the ROM, only about the various \
  89. hook codes.
  90. The following example shows the use of hook code 20H (which tests to see if a key has been pressed) from machine code:
  91.  
  92. ORG 7D00H ;32000 dec
  93. EXAMPLE RST 0008H ;hook code restart
  94. DEFB 20H ;check keypress
  95. RET
  96. END
  97.  
  98. To do the same thing from BASIC:
  99.  
  100. POKE 32000,207: POKE 32001,32: POKE 32002,201: RANDONISE USR 32000
  101.  
  102. The hook codes available for your use are numbered from 1BH to 32H (27 to 50 decimal). The hook codes are all fully \
  103. described in the disassembly, from 1981H to 1B6DH. If you use the hook codes within your programs, instead of calling
  104. the shadow ROM subroutines, there will be no need to change your program if Sinclair make further changes to the ROM. \
  105. Otherwise you will need to update all the absolute references to the shadow ROM.
  106. In using hook codes, only the contents of the A register may be passed to the subroutines being called. The \
  107. subroutines do not preserve any registers, so be sure to save all of the main set of registers before you use any hook \
  108. codes. Some of the more complex routines corrupt HL', the return address to BASIC, so you may wish to preserve this.
  109. Although the individual hook codes are dealt with in detail in the disassembly, here is a brief summary of their \
  110. actions:
  111. 1BH - Accepts a character from the keyboard.
  112. 1CH - A character is output to stream 2, which is normally the upper part of the screen.
  113. 1DH - Accepts a byte of data from the RS—232 link.
  114. 1EH - Sends a byte of data to the RS—232 link.
  115. 1FH - A character is output to stream 3, which is normally the ZX printer.
  116. 20H - Tests for keypress.
  117.  
  118. The next twelve hook codes refer to the Microdrives.
  119. 21H - Select drive. Can be used to turn any drive on, or all drives off.
  120. 22H - Open channel. Allows the user to create a microdrive channel.
  121. 23H - Close channel. The Microdrive channel is reclaimed.
  122. 24H - Delete file. Used to erase a named file from a Microdrive channel.
  123. 25H - Read sequential. Allows the user to fetch the 'next' record of a named file.
  124. 26H - Write record. Writes a new record onto the next free sector of a microdrive cartridge.
  125. 27H - Read random. Similar to 'read sequential', except that the record read need not be the next one in the file.
  126. 28H - Reads a record from a specified sector of tape.
  127. 29H - Reads the record from the next sector of tape that passes under the read head of the Microdrive.
  128. 2AH - Writes a record to a specified sector of tape.
  129. 2BH - Due to a programming error, this has the same effect as 'create channel' in the first issue ROM. This should be \
  130. corrected in later issues.
  131. 2CH - Reclaims the memory used by a Microdrive channel.
  132.  
  133. The following four hook codes refer to the local area network.
  134. 2DH - Opens a network channel.
  135. 2EH - Closes a network channel.
  136. 2FH - Fetches a 'packet' of information from a network channel.
  137. 30H - Sends a packet over a network channel.
  138. 31H - Creates the new system variables used by the Interface 1. This happens when the system is powered up, and when \
  139. NEW is typed, but it also can be done manually.
  140. 32H - This routine is different from the other hook codes in that it can be used to call any routine in the shadow \
  141. ROM. The shadow ROM is paged in, the routine whose address is held in the system variable HD-11 (held at address \
  142. 5CEDH) is called, and the main ROM is paged back in.
  143. 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 \
  144. main ROM normally is, and to be directly accessible to your program, use the following program fragment to page
  145. the Shadow ROM in:
  146.  
  147. LD HL,LABEL
  148. LD (23789),HL
  149. RST 8
  150. DEFB 32H
  151. LABEL POP HL
  152. POP HL
  153.  
  154. To page the main ROM back in, simply do CALL 0700H
  155.  
  156. For more information about the hook codes and the ZX Interface 1, see the 'Spectrum Microdrive Book' by Dr. Ian Logan. \
  157. also published by Melbourne House.
  158. EXTENSIONS TO BASIC
  159.  
  160. This section of the book shows how to add a number of new commands to the Spectrums BASIC. Those with no knowledge of \
  161. machine code, or simply no interest in it can simply type the routines that follow into their Spectrums, save them
  162. onto tape or Microdrive, and instantly have a more powerful BASIC. Machine code programmers will find the programs \
  163. valuable examples of how to use the Interface 1 ROM routines, and should be interested by the way in which new \
  164. commands are added to BASIC. A later section will explain how this is done.
  165. The extensions to BASIC consist of a number of machine code routines, each of which makes up a new BASIC command, \
  166. along with a main program which will prepare the computer to run the new commands.
  167. The new BASIC includes improvements to the POKE, CAT, and BEEP commands, a better version of EDIT, more versatile \
  168. file handling for the Microdrives, an extension to the RS—232 channel, and a useful memory dump command which will \
  169. list the contents of an area of memory, in both hexadecimal and ASCII form.
  170. Sinclair Research have released two different versions of the Interface 1. Each of the versions contains a slightly \
  171. different program in its ROM. The newer version of the ROM has corrected a number of errors contained in the previous \
  172. edition, as well as adding some new routines. Because new code has been added to
  173. the Shadow ROM at various points, many of the routines in the ROM are no longer located at the same address as before. \
  174. As the extensions to BASIC given in this book make use of many routines from the Shadow ROM, you will have to do \
  175. slightly
  176. different things to implement the BASIC extensions, depending on which edition of the Interface 1 you own.
  177. First of all you'll have to figure out which edition of the Interface you own. Instructions on how to do this are \
  178. given in Appendix 8 on page 155.
  179. If you find you have an edition 1 ROM in your Interface 1, you will find instructions on how to add the new commands \
  180. 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.
  181. 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 \
  182. if you don't, for instructions on how to add the new BASIC commands to your Spectrum.
  183. Although there are only two editions of the Shadow ROM at the moment, there is some possibility that Sinclair Research \
  184. may release further editions of the Interface 1. Should you own one of these, it is likely that the extended BASIC
  185. commands given here will not work properly with it. If the extended BASIC commands do not work for you, and you \
  186. suspect that you might have a third edition or later Shadow ROM, turn to Appendix 11 on page 165 to find out how you \
  187. can implement the new commands.
  188. Basic loader program
  189.  
  190. (For owners of Interface 1s equipped with the edition 1 ROM)
  191.  
  192. If you do not have an Assembler, you may enter the routines into your Spectrum with the following BASIC loader program.
  193.  
  194.  
  195. Enter this program into your Spectrum.
  196.  
  197. 1 CLEAR 63743
  198. 10 FOR A=63744 TO 65046 STEP 12
  199. 20 PRINT "ADDRESS:";A''
  200. 30 LET C=0
  201. 40 FOR B=l TO 12
  202. 50 LET Z=A+B-1: IF Z<=65046 THEN INPUT X: PRINT X: POKE Z,X: LET =C+X
  203. 60 NEXT B
  204. 70 PRINT '"CHECKSUM=";C
  205. 80 INPUT "THIS IS WROMG ? (Y/N) ";LINE Y$: IF CODE Y$=89 OR CODE Y$=l2l THEN PRINT "Retype from address ";A: PAUSE \
  206. 100: CLS: GO TO 20
  207. 90 IF CODE Y$<>78 AND CODE Y$<>l10 THEN GO TO 80
  208. 100 CLS: NEXT A
  209. 110 PRINT "SAVING THE PROGRAM"
  210. 120 SAVE *"M";1;"SHADP"CODE 63744,1303
  211.  
  212.  
  213. When you have finished typing this program into the Spectrum, you should 'RUN' it. You should then type, from the \
  214. listing on the next page, the 12 bytes from the address shown on the screen. When you have typed the first 12 bytes, a \
  215. 'checksum' should be displayed on the screen; if it matches with the one printed on the listing, at the right—hand \
  216. side of each line, then you have not made mistakes in typing the numbers, and you may enter "N" or "n" to continue \
  217. with the next line. If the checksums do not match, you must enter 'y' or 'Y', and then retype the whole line.
  218.  
  219. When all numbers have been entered, the program will automatically be saved on Microdrive cartridge (there must be a \
  220. cartridge with at least 2K free into Microdrive 1). IF you wish to save the program on tape, line 120 of the listing \
  221. should be modified. When at later time you wish to use the routines, you have simply to place the cartridge into \
  222. Microdrive I, and then to enter the following direct commands:
  223.  
  224. CLEAR 63743: LOAD *"M";1;"SHADP"CODE: RANDOMIZE USR 63744
  225.  
  226. And the new commands should be available. Note that if you use NEW command, you must re—enter the command 'RANDOMIZE \
  227. USR 63744' to reinitialise the VECTOR system variable.
  228.  
  229. 63744: 207 49 33 9 249 34 183 92 201 215 24 0 1296
  230. 63756: 254 244 202 45 249 254 42 202 114 249 254 215 2324
  231. 63768: 202 11 250 254 227 202 188 251 254 229 202 12 2282
  232. 63780: 252 254 224 202 175 252 195 240 1 215 32 0 2042
  233. 63792: 254 42 194 75 249 215 121 28 205 183 5 215 1786
  234. 63804: 153 30 197 215 153 30 197 225 193 113 35 112 1653
  235. 63816: 195 193 5 215 130 28 254 44 194 240 1 215 1714
  236. 63828: 32 0 215 140 28 205 183 5 215 241 43 197 1504
  237. 63840: 213 215 153 30 80 89 225 193 120 177 202 193 1890
  238. 63852: 5 237 176 195 193 5 215 32 0 254 207 202 1721
  239. 63864: 102 250 246 32 254 108 194 197 249 215 32 0 1879
  240. 63876: 215 130 28 205 183 5 215 153 30 96 105 124 1489
  241. 63888: 205 135 30 125 205 135 30 62 32 205 169 30 1363
  242. 63900: 229 6 6 197 126 205 158 30 35 16 249 193 1450
  243. 63912: 225 126 230 127 254 32 56 6 254 128 48 2 1488
  244. 63924: 24 2 62 32 205 169 30 35 16 235 62 13 885
  245. 63936: 205 169 30 24 202 254 101 194 240 1 215 32 1667
  246. 63948: 0 215 130 28 205 183 5 215 153 30 253 203 1620
  247. 63960: 12 126 202 240 1 120 230 192 194 240 1 237 1795
  248. 63972: 67 73 92 237 123 61 92 33 7 250 229 42 1306
  249. 63984: 61 92 229 33 127 16 229 237 115 61 92 253 1545
  250. 63996: 54 0 255 215 169 15 33 56 15 229 199 225 1465
  251. 64008: 195 180 18 215 32 0 254 42 194 240 1 215 1586
  252. 64020: 121 28 254 44 194 240 1 215 121 28 205 183 1634
  253. 64032: 5 215 148 30 245 215 148 30 167 40 54 79 1376
  254. 64044: 6 0 197 215 148 30 167 40 44 79 6 0 932
  255. 64056: 197 215 153 30 197 205 0 7 225 209 193 241 1872
  256. 64068: 229 245 197 229 213 205 181 3 209 225 193 241 2370
  257. 64080: 167 237 66 48 240 61 225 32 235 33 193 5 1542
  258. 64092: 34 237 92 207 50 253 54 0 0 239 215 32 1413
  259. 64104: 0 205 30 6 205 183 5 205 109 6 62 2 1018
  260. 64116: 215 1 22 205 232 15 221 126 25 205 247 23 1537
  261. 64128: 205 196 18 33 9 251 17 24 0 205 5 251 1214
  262. 64140: 205 65 19 32 239 33 9 251 203 78 32 232 1390
  263. 64152: 58 9 251 33 12 251 182 230 2 194 169 250 1641
  264. 64164: 205 254 18 24 215 58 13 251 183 40 209 58 1528
  265. 64176: 10 251 183 32 203 221 126 41 221 190 13 40 1531
  266. 64188: 22 205 33 251 205 0 251 221 126 13 183 194 1704
  267. 64200: 128 250 221 126 41 221 119 13 195 128 250 221 1913
  268. 64212: 229 175 205 247 23 205 0 251 221 229 225 17 2027
  269. 64224: 44 0 25 205 178 251 205 0 251 205 56 29 1449
  270. 64236: 123 203 63 215 40 45 215 227 45 205 0 251 1632
  271. 64248: 221 225 205 196 16 195 193 5 62 13 195 102 1628
  272. 64260: 29 229 195 173 24 0 0 0 0 0 0 0 650
  273. 64272: 0 0 0 0 0 0 0 0 0 0 0 0 0
  274. 64284: 0 0 0 0 0 33 140 92 54 255 33 13 620
  275. 64296: 251 205 178 251 62 32 205 102 29 58 9 251 1633
  276. 64308: 203 87 194 62 251 62 245 195 102 29 33 24 1487
  277. 64320: 251 126 183 202 99 251 254 3 202 157 251 61 2040
  278. 64332: 245 62 228 205 102 29 58 29 251 230 31 198 1668
  279. 64344: 96 205 102 29 241 200 62 36 195 102 29 33 1330
  280. 64356: 32 251 126 230 192 192 43 62 202 205 102 29 1668
  281. 64368: 94 35 86 235 17 16 39 205 143 251 17 232 1370
  282. 64380: 3 205 143 251 17 100 0 205 143 251 17 19 1345
  283. 64392: 0 205 143 251 17 1 0 62 255 60 183 237 1414
  284. 64404: 82 48 250 25 246 48 195 102 29 62 175 205 1467
  285. 64416: 102 29 35 229 35 35 205 112 251 62 44 205 1344
  286. 64428: 102 29 225 195 112 251 6 10 126 205 102 29 1392
  287.  
  288.  
  289. 64440: 35 16 249 201 215 32 0 254 35 194 240 1 1472
  290. 64452: 215 121 28 205 183 5 215 148 30 245 215 148 1758
  291. 64464: 30 254 16 210 99 6 215 1 22 221 42 81 1197
  292. 64476: 92 221 126 4 254 77 194 45 6 221 203 24 1467
  293. 64488: 70 194 50 17 241 221 119 13 221 126 25 205 1502
  294. 64500: 247 23 33 255 0 34 201 92 205 132 11 175 1414
  295. 64512: 221 119 11 221 119 12 205 247 23 195 193 5 1571
  296. 64524: 215 32 0 215 130 28 205 183 5 215 148 30 1406
  297. 64536: 254 16 210 99 6 215 1 22 221 42 81 92 1259
  298. 64548: 221 126 4 254 71 194 45 6 221 203 24 70 1445
  299. 64560: 194 2 9 221 126 25 205 247 23 33 255 0 1340
  300. 64572: 34 201 92 205 165 17 56 19 40 14 221 203 1267
  301. 64584: 67 78 49 11 221 126 41 221 119 13 24 3 964
  302. 64596: 205 254 18 205 18 19 32 227 219 239 230 1 1667
  303. 64608: 202 197 26 205 75 26 218 163 17 221 110 69 1529
  304. 64620: 221 102 70 221 117 11 221 116 12 221 203 24 1539
  305. 64632: 198 205 62 30 205 196 18 221 126 13 221 190 1685
  306. 64644: 41 32 245 62 230 211 239 1 104 1 205 250 1621
  307. 64656: 24 221 229 225 11 55 0 25 205 120 24 62 1207
  308. 64668: 238 211 239 205 254 18 221 126 68 221 119 13 1933
  309. 64680: 175 205 247 23 195 193 5 215 32 0 254 33 1577
  310. 64692: 40 1l 254 47 40 33 254 63 40 54 195 240 1271
  311. 64704: 1 215 121 28 205 183 5 215 148 30 167 202 1520
  312. 64716: 245 253 50 16 254 215 148 30 61 50 15 254 1591
  313. 64728: 195 193 5 215 121 28 205 183 5 215 148 30 1543
  314. 64740: 50 17 254 215 148 30 50 18 254 175 50 22 1283
  315. 64752: 254 195 193 5 215 32 0 215 130 28 205 183 1655
  316. 64764: 5 215 148 30 254 1 40 12 62 3 253 203 1226
  317. 64776: 124 142 205 24 23 195 193 5 62 3 215 30 1230
  318. 64788: 23 33 17 0 167 237 66 218 47 5 205 19 1037
  319. 64800: 11 213 33 5 0 25 17 53 253 115 35 114 874
  320. 64812: 62 3 50 216 92 209 195 74 11 254 165 210 1541
  321. 64824: 64 12 253 203 1 134 254 32 56 85 32 4 1130
  322. 64836: 253 203 1 198 245 62 1 50 19 254 241 205 1732
  323. 64848: 60 12 58 15 254 71 58 14 254 184 48 5 1033
  324. 64860: 60 50 14 254 201 205 105 253 175 50 19 254 1640
  325. 64872: 201 62 1 50 19 254 61 50 14 254 58 20 1044
  326. 64884: 254 167 196 90 12 58 21 254 167 196 90 12 1517
  327. 64896: 58 18 254 71 58 22 254 60 184 32 8 58 1077
  328. 64908: 17 254 167 196 90 12 175 50 22 254 201 254 1692
  329. 64920: 13 32 12 58 19 254 167 62 1 50 19 254 941
  330. 64932: 200 24 194 254 6 32 33 42 14 254 58 16 1127
  331. 64944: 254 71 14 0 12 44 125 188 48 167 144 40 1107
  332. 64956: 4 48 251 24 243 197 62 32 205 53 253 193 1565
  333. 64968: 13 32 246 201 254 23 192 17 221 253 42 81 1575
  334. 64980: 92 1 5 0 9 115 35 114 201 50 15 92 729
  335. 64992: 17 229 253 24 237 17 53 253 205 210 253 58 1809
  336. 65004: 15 92 71 58 15 254 184 48 5 253 54 0 1049
  337. 65016: 10 239 58 14 254 144 200 48 5 237 68 79 1356
  338. 65028: 24 187 197 205 105 253 193 72 24 179 0 80 1519
  339. 65040: 20 12 60 1 13 10 0 116
  340.  
  341. Assembler Listings
  342. (For Interface 1s equipped with the edition 1 Shadow ROM.)
  343.  
  344. The following is a complete, fully commented assembler listing of the machine code programs which make the new BASIC \
  345. commands possible. These consist of a main program which sets up the new system variables needed by the Interface 1, \
  346. and a number of small programs, one of which is used by each new command. The equate statements used by these routines \
  347. are included in a seperate table at the end of the listings. To add the new BASIC commands to your Spectrum, enter the \
  348. assembler program on the following pages, as well as the table of EQU statements that follows it, into your assembler, \
  349. assemble it, and save the resulting machine code on tape or microdrive. When you wish to use the new BASIC commands, \
  350. load the machine code file into your Spectrum at 63744 (F900 Hex.), and do
  351.  
  352. RANDOMIZE USR 63744
  353.  
  354. to make the new commands available.
  355. All readers of this book should at least glance through this section, as interspersed with the listings of the new \
  356. commands are examples of their use, and explanations of their functions. A brief explanation of the manner in which \
  357. new commands are added to BASIC is given later in the book, and it may prove useful in understanding what is being \
  358. done in this section.
  359.  
  360. Main program
  361.  
  362. The program starts at the address F900 hex (63744 decimal), and is located above RAMTOP. When it is used for the first \
  363. time, you must use a command
  364.  
  365. RANDOMIZE USR 63744
  366.  
  367. to initialise the system variable VECTOR. You must do this whenever the initial VECTOR contents are defaulted back to \
  368. ERR_6 (01F0). This happens when you use a NEW command to delete the BASIC program from the memory.
  369.  
  370.  
  371. ORG 0F900H
  372. ;
  373. MAINPG EQU $
  374. ;
  375. RST ERROR_1 ;Create new system variables if
  376. DEFB HOOK31 ;nonexistent.
  377. LD HL,STSYN ;Store start address of new routine
  378. LD (VECTOR),HL ;into VECTOR.
  379. RET
  380.  
  381.  
  382. Note that initially 'hook code' +31 is used to create the new system variables if they do not already exist. Failure \
  383. to do so in your programs will cause a probable crash when you try to POKE something into the location where the 'new' \
  384. system variables should be.
  385. The address of the syntax module routine STSYN is then stored into VECTOR. This causes the routine STSYN to be used \
  386. whenever a command fails the syntax of the main ROM interpreter, and then that of the shadow ROM interpreter. The \
  387. system variable CH_ADD will point to the first character of the command that produces the error.
  388.  
  389. The routine STSYN is listed below.
  390.  
  391. STSYN RST CALBAS
  392. DEFW GET_CHAR ;Fetch command code.
  393. CP POKE ;Jump to the appropriate routine,
  394. JP Z,PGM1 ;depending on the command code.
  395. CP "*"
  396. JP Z,PGM3
  397. CP BEEP
  398. JP Z,PGM5
  399. CP READ
  400. JP Z,PGM7
  401. CP RESTORE
  402. JP Z,PGM8
  403. CP LPRINT
  404. JP Z,PGM9
  405. JP ERR_6 ;Give an error if none of these.
  406.  
  407.  
  408. Note that the 'main' ROM restart GET_CHAR is used to fetch the command code into the A register; then a jump is made \
  409. to the required syntax module routine. If the command code is still wrong, the error is confirmed by jumping to ERR_6.
  410.  
  411. A simple 'double POKE' routine: Poke * x,y
  412.  
  413. The first implemented 'new' command is a 'double POKE' command. That is, a POKE command that uses word operands (16 \
  414. bits) instead of byte operands (8 bits). The syntax is 'POKE *x,y•, where 'a' is the address in the range 0..65535, \
  415. and 'y' is the value to be poked at location 'a', again in the range 0..65535. Note that the standard Intel format is \
  416. used, i.e. the low byte goes before the high byte in memory. You may use the new POKE command, for example, to store \
  417. values into two—byte system variables:
  418.  
  419. POKE *23675,32000
  420.  
  421. is a rather straightforward way of changing to '32000' the contents of the UDG system variable, as compared with the \
  422. usual:
  423.  
  424. POKE 23675,32000~256*INT (32000/256)
  425. POKE 23676,INT (32000/256)
  426.  
  427. The machine code program used to do this is very simple:
  428.  
  429. PGM1 RST CALBAS
  430. DEFW NEXT_CHAR ;Advance CH_ADD.
  431. CP "*" ;Jump if it is not a POKE *x,y command.
  432. JP NZ,PGM2
  433. RST CALBAS
  434. DEFW NEXT_2NUM ;Evaluate the two parameters.
  435. CALL ST_END ;Confirm end of statement.
  436. RST CALBAS
  437. DEFW FIND_INT2 ;Fetch number to be POKEd.
  438. PUSH BC ;Save it.
  439. RST CALBAS
  440. DEFW FIND_INT2 ;Fetch address.
  441. PUSH BC ;Move it into HL.
  442. POP HL
  443. POP BC ;Restore value.
  444. LD (HL),C ;POKE the low byte.
  445. INC HL
  446. LD (HL),B ;POKE the high byte.
  447. JP END1 ;Finished.
  448.  
  449.  
  450. Initially the syntax of the new command is checked; CH_ADD is advanced to the character that follows the token 'POKE', \
  451. and if the character '*' is not present, a jump is made to the command for pokeing strings into memory (because the \
  452. current command is not POKE *x,y).
  453. Assuming that our current command is POKE *x,y, the 'main' ROM routine NEXT_2NUM is then used to evaluate two numeric \
  454. expressions (separated by a comma), following the character pointed by CH_ADD. An error will occur if the
  455. expressions have incorrect syntax. Otherwise the syntax is correct and the call to ST_END returns to the 'main' ROM \
  456. during syntax checking. During runtime the execution continues, and the main ROM routine FIND_INT2 is used to fetch \
  457. the values from the calculator stack. After the POKE * has been done, control is returned to the main ROM interpreter \
  458. by jumping to END1.
  459.  
  460. Pokeing strings into memory: POKE n,"s"
  461.  
  462. This command makes it possible to POKE a string in memory, starting from the address 'n'. For example, the statement:
  463.  
  464. POKE 30000, "FRED BLOGGS"
  465.  
  466. Will POKE the ASCII values of the characters in the string "FRED BLOGGS", starting from the address 30000. You may \
  467. check this by reading back the values with PEEK:
  468.  
  469. FOR A=30000 TO 30010: PRINT CHR$ PEEK A;: NEXT A
  470.  
  471. Note that the routine fails the syntax of the interpreter by using a different parameter type (i.e. a string instead \
  472. of a number), while the previous routine used a '*' character following the command code.
  473.  
  474. PGM2 RST CALBAS ;Evaluate the address.
  475. DEFW EXPT_1NUM
  476. CP COMMA ;A separator must be present.
  477. JP NZ,ERR_6 ;Report the error if it is not present.
  478. RST CALBAS ;Advance CH_ADD.
  479. DEFW NEXT_CHAR
  480. RST CALBAS ;Evaluate string expression.
  481. DEFW EXPT_EXP
  482. CALL ST_END ;Confirm end of statement,
  483. RST CALBAS ;Fetch string parameters.
  484. DEFW STK_FETCH
  485. PUSH BC ;Save 'length' and 'start'.
  486. PUSH DE
  487. RST CALBAS ;Fetch address.
  488. DEFW FIND_INT2
  489. LD D,B ;Move address into DE.
  490. LD E,C
  491. POP HL ;Restore string 'start' and 'length'.
  492. POP BC
  493. LD A,B ;Exit with null string.
  494. OR C
  495. JP Z,END1
  496. LDIR ;The actual POKE.
  497. JP END1 ;Finished.
  498.  
  499.  
  500. The routine is entered from the POKE *x,y routine with CH_ADD pointing to the character following the 'POKE' token. \
  501. The main ROM routines EXPT_ 1NUM and EXPT_EXP are then used, respectively to evaluate a numeric and a string
  502. expression. A comma must be placed between them as separator. During runtime, the main ROM routines STK_FETCH and \
  503. FIND_INT2 are used to fetch the string parameters, and the value of the numeric expression. No action is taken iF the
  504. string has null length.
  505. Memorydump: *L n
  506.  
  507. This routine creates a new command '*L n' that lists the memory contents, starting from the address n, in both \
  508. hexadecimal and ASCII. Unprintable ASCII codes ate printed as spaces. For example, the following statement:
  509.  
  510. *L 31920
  511.  
  512. Will list the contents of the memory starting from address 31920. Note that when dumping memory at addresses lower \
  513. than 16384, the 'shadow' ROM code is shown. Try for example to dump from the address 695, that is the start of the \
  514. 'shadow
  515. ROM report messages table. The result will be as follows:
  516.  
  517. 02B7 00 50 72 6F 67 72 Progr
  518. 02BD 61 6D 20 66 69 6E am fin
  519. 02C3 69 73 68 65 64 01 ished
  520. 02C9 41 6F 6E 73 65 6E Nonsen
  521. 02CF 73 65 20 69 6E 20 se in
  522. 02D5 42 41 53 49 43 02 BASIC
  523. ....
  524. ....
  525.  
  526. The routine follows:
  527.  
  528. PGM3 RST CALBAS ;Advance CH_ADD.
  529. DEFW NEXT_CHAR ;Jump if the command is CAT.
  530. CP CAT
  531. JP Z,PGM6
  532. OR 20H ;Make the letter lower case.
  533. CP "l" ;Jump if this is not an "*L" command.
  534. JP NZ,PGM4
  535. RST CALBAS
  536. DEFW NEXT_CHAR ;Advance CH_ADD.
  537. RST CALBAS
  538. DEFW EXPT_1NUM ;Evaluate start address.
  539. CALL ST_END ;Confirm end of statement.
  540. RST CALBAS ;Fetch start address.
  541. DEFW FIND_INT2
  542. LD H,B ;Move it into HL.
  543. LD L,C
  544. AGAIN LD A,H ;Display high byte of address in hex.
  545. CALL DISP_HEX
  546. LD A,L ;Display low byte.
  547. CALL DISP_HEX
  548. LD A,SPACE ;Print a space.
  549. CALL DISP_CH
  550. PUSH HL ;Save current address.
  551. LD B,6 ;Display 6 bytes.
  552. PUSH BC ;Save counter for later,
  553. L_LOOP LD A,(HL) ;Fetch a byte.
  554. CALL DISPHEX2 ;Display it in hex.
  555. INC HL ;Examine each byte in turn.
  556. DJNZ L_LOOP
  557. POP BC ;Restore counter and address.
  558. POP HL
  559. C_LOOP LD A,(HL) ;Fetch a byte.
  560. AND 7FH ;Clear bit 7.
  561. CP SPACE ;Reject codes lower than SPACE.
  562. JR C,REJECT
  563. CP 80H ;Reject codes greater than 7FH.
  564. JR NC,REJECT
  565. JR ACCEPT
  566. REJECT LD A,SPACE ;Replace invalid codes with 'space'
  567. ;code.
  568. ACCEPT CALL DISP_CH ;Print the character.
  569. INC HL ;Advance pointer.
  570. DJNZ C_LOOP ;Continue the toop.
  571. LD A,CR ;Finally print a carriage return.
  572. CALL DISP_CH
  573. JR AGAIN ;Jump back.
  574.  
  575.  
  576. This time, the interpreter syntax is failed by starting the command with a non—standard character, namely, a '*'. The \
  577. letter 'L' (for 'L'ist) maybe either upper or lower case.
  578. Note that the shadow ROM routines DISP_HEX, DISP_HEX2 and DISP_CH are used to print characters onto stream 2 (the \
  579. screen). Note also that the command will never end during runtime. This, however, will not result in an endless loop, \
  580. as you may simply press BREAK when the 'scroll' message is displayed on the screen, to stop the listing. The output \
  581. may be directed to a device other than the screen by first using an OPEN command. i.e. OPEN #2,"T" will direct the \
  582. output to the RS232 "T" channel.
  583. The main ROM routines EXPT_1NUM and FIND_INT2 are used to evaluate and fetch the given parameter 'n'.
  584.  
  585. Modified EDIT function: *E n
  586.  
  587. The normal 'EDIT' function is not very well implemented; if you wish, for example, to EDIT line 4385 of your program, \
  588. you must first make the line 'current' by using something like LIST 4385, and then (after having pressed BREAK to stop \
  589. the listing) press the EDIT key.
  590. By using this routine, you may type simply '*E 4385' to do the same thing. The listing of the routine follows:
  591.  
  592.  
  593. PGM4 CP "e" ;Error if it is not the '*E' command.
  594. JP NZ,ERR_6
  595. RST CALBAS ;Advance CH_ADD.
  596. DEFW NEXT_CHAR
  597. RST CALBAS ;Evaluate line number.
  598. DEFW EXPT_1NUM
  599. CALL ST_END ;Confirm end of statement.
  600. RST CALBAS ;Fetch line number.
  601. DEFW FIND_INT2
  602. BIT 7,(IY+PPC_HI) ;Accept only as 'direct' command.
  603. JP Z,ERR_6
  604. LD A,B ;Error with line number out of range.
  605. AND 0C0H
  606. JP NZ,ERR_6
  607. LD (E_PPC),BC ;Make this line 'current'.
  608. LD SP,(ERR SP) ;Clear machine stack.
  609. LD HL,ENDED ;Final return address.
  610. PUSH HL
  611. LD HL,(ERR_SP) ;Save current error address.
  612. PUSH HL
  613. LD HL,ED_ERROR ;The new error address.
  614. PUSH HL
  615. LD (ERR_SP),SP
  616. LD (IY+ERR_NR),0FFH ;Clear the error.
  617. RST CALBAS
  618. DEFW ED_EDIT ;Copies the line into the editing area.
  619. LD HL,ED_LOOP ;Return to 'EDitor LOOP', and to ENDED
  620. PUSH HL ;below when finished.
  621. RST MAIN_ROM
  622. ;
  623. ;NOTE: Main ROM in use.
  624. ;
  625. ENDED POP HL ;Remove +l303 from the stack.
  626. JP 12B4H ;Jump back to the main execution loop.
  627.  
  628.  
  629. Note that the command is rejected at runtime (BIT 7,PPC_HI) if it is not a 'direct' one: this is because an EDIT \
  630. command used within a program does not make sense.
  631. The command is also rejected if you specify wrong line numbers. If you use a nonexistent line number, the next \
  632. existent number is used.
  633. The routine enters the main ROM 'EDITOR' subroutine, after having copied the line into the editing area, and returns \
  634. to the main execution loop when finished.
  635.  
  636. An improved sound command: BEEP *a,b,c,d
  637.  
  638. The standard 'BEEP x,y' command is very limited: it will only make sounds of a constant pitch. This routine creates a \
  639. new 'BEEP' command that accepts four parameters, giving an endless range of possible sound effects.
  640. The syntax of the new command is 'BEEP * a,b,c,d', where 'a' and 'b' are the values that the main ROM 'BEEPER' \
  641. subroutine accepts as 'pitch' and 'length', 'c' is a 'step' value that will be subtracted from 'a' until it reaches \
  642. zero, and 'd' is a 'repeat' value that defines how many times the whole sound must be made. Try the following \
  643. statement:
  644.  
  645. BEEP * 100,255,10,1
  646.  
  647. The following BASIC program will generate a wide range of sounds:
  648.  
  649.  
  650. 10 LET a=RND*1000+10
  651. 20 LET b=RND*6+1
  652. 30 LET c=RND*50+1
  653. 40 LET d=RND*3+1
  654. 50 BEEP *a,b,c,d
  655. 60 GO TO 10
  656.  
  657.  
  658. The routine is listed below:
  659.  
  660. PGM5 RST CALBAS ;Advance CH_ADD.
  661. DEFW NEXT_CHAR
  662. CP "*" ;The '*' must be present.
  663. JP NZ,ERR_6
  664. RST CALBAS ;Evaluste 'a','b'
  665. DEFW NEXT_2NUM
  666. CP COMMA ;A separator must be found after 'b'.
  667. JP NZ,ERR_6
  668. RST CALBAS ;Evaluate 'c','d'.
  669. DEFW NEXT_2NUM
  670. CALL ST_END ;Confirm end of statement.
  671. RST CALBAS ;Fetch 'd'.
  672. DEFW FND_INTl
  673. PUSH AF ;Save it.
  674. RST CALBAS ;Fetch 'c'.
  675. DEFW FND_INTl
  676. AND A ;Give an error if c=0.
  677. JR Z,RANGE
  678. LD C,A ;Otherwise move it into BC.
  679. LD B,0
  680. PUSH BC ;Save it.
  681. RST CALBAS ;Fetch 'b'.
  682. DEFW FND_INT1
  683. AND A ;Give an error if b=0.
  684. JR Z,RANGE
  685. LD C,A ;Move it into BC.
  686. LD B,0
  687. PUSH BC ;Save 'b' briefly.
  688. RST CALBAS ;Fetch 'a'.
  689. DEFW FIND_INT2
  690. PUSH BC ;Save it temporarily.
  691. CALL UNPAGE ;Use main ROM.
  692. POP HL ;Restore 'a', 'b', 'c' and 'd' values.
  693. POP DE
  694. POP BC
  695. POP AF
  696. LOOP2 PUSH HL ;Save 'a' for next pass.
  697. LOOP1 PUSH AF ;Save values.
  698. PUSH BC
  699. PUSH HL
  700. PUSH DE
  701. CALL BEEPER ;Emit a sound.
  702. POP DE ;Restore values.
  703. POP HL
  704. POP BC
  705. POP AF
  706. AND A
  707. SBC HL,BC ;Subtract 'step' from 'a'.
  708. JR NC,LOOP1 ;Continue while subtraction possible.
  709. DEC A ;Decrease 'd'
  710. POP HL ;Restore 'a' for repetition.
  711. JR NZ,L00P2 ;Repeat the sound until d=0.
  712. LD HL,END1 ;Note how the return is made to the
  713. LD (HD_11),HL ;shadow ROM.
  714. RST ERROR_1
  715. DEFB HOOK32
  716. ;
  717. RANGE LD (IY+ERR_NR),0 ;Call the error handling routine.
  718. RST ROMERR
  719.  
  720.  
  721. 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 \
  722. you would expect from a value of 256.)
  723. 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.
  724. If you have some difficulty in choosing the correct 'a' and 'b' values, you may calculate them as shown below:
  725.  
  726. a = 437500/frequency-30.l25
  727. b = frequency * time
  728.  
  729. (frequency=Hz, time=sec.)
  730.  
  731. You may also use the following BASIC program which calculates the values for A and B, starting from the 'x', 'y' \
  732. values used in a normal BEEP command. For example, the sound obtained with BEEP 0.01,10 requires '908' and '4' as A \
  733. and B
  734. values.
  735.  
  736. 10 DATA 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392, 415.3, 440, 466.16, 493.88
  737. 20 INPUT "TIME (SEC.) ? ";t
  738. 30 INPUT "PITCH ? ";p
  739. 40 LET i=INT p: LET pi=p-i
  740. 50 LET pk=(pi*.0577622606)+1
  741. 60 LET a=i+60: LET b=-6
  742. 70 LET b=b+1: LET a~a-12
  743. 80 IF SGN a()-1 THEN GO TO 70
  744. 90 LET a=a+l2
  745. 100 RESTORE: FOR x=0 TO a: READ c: NEXT x
  746. 110 LET f=(pk*c)*2-b: IF f*t=0 THEN PRINT "ERROR": STOP
  747. 120 PRINT "A=";INT (437500/f-30.125)'"B=";INT (f*t)
  748.  
  749. A faster and more complete catalogue:* CAT n
  750.  
  751. After some 'general purpose' commands come some more complicated routines that use the new Interface's devices. This \
  752. routine adds a new command '* CAT n' that gives a full catalogue of a cartridge held in the microdrive 'n'.
  753. The command runs about 2—3 seconds faster than the standard 'CAT n' command, does not limit the output to 59 names, \
  754. and provides information on the nature of the file, its length, etc., that is not given when the standard 'CAT' \
  755. command is used.
  756. Since the names are printed as they are found on the cartridge, the list is not alphabetically ordered.
  757. Along with each filename the following information will appear:
  758.  
  759. 'PRINT' If it is a PRINT—type file.
  760. 'CODE sssss,nnnnn' If it is a 'bytes' file; 'sss' and 'nnn' are respectively
  761. the start address and the length of the file.
  762. 'DATA x' If it is a numeric array named 'x'.
  763. 'DATA x$' If it is a string array named 'x$'
  764. 'LINE nnnnn' If it is a BASIC program with autostart at line 'nnn'.
  765.  
  766. If nothing is printed after the filename, then the file is a normal BASIC program saved without the autostart.
  767.  
  768.  
  769. The routine is listed below.
  770.  
  771. PGM6 RST CALBAS ;Advance CH_ADD.
  772. DEFW NEXT_CHAR
  773. CALL EXPT_NUM ;Evaluate drive number.
  774. CALL CHECK_M_2 ;Check range of drive number.
  775. CALL ST_END ;Confirm end of statement.
  776. LD A,2 ;Use stream 2 (screen).
  777. RST CALBAS
  778. DEFW CHAN_OPEN
  779. CALL SET_T_MCH ;Create a temporary "m" channel.
  780. LD A,(IX+CHDRIV) ;Turn on drive motor.
  781. CALL SEL_DRIVE
  782. CATLOOP CALL GET_M_HD02 ;Get a header.
  783. LD HL,RDESC ;And a record descriptor from the address
  784. LD DE,18H ;RDESC.
  785. CALL GETD
  786. CALL CHKS_HD R ;Repeat until the checksum is correct.
  787. JR NZ,CATLOOP
  788. LD HL,RDESC ;Repeat also if loaded wrong block type
  789. BIT 0,(HL) ;(header).
  790. JR NZ,CATLOOP
  791. LD A,(RDESC) ;Jump forward with 'not free' sectors.
  792. LD HL,RDESC+3
  793. OR (HL)
  794. AND 2
  795. JP NZ,PRI_NA
  796. CALL RES_B_MAP ;Mark 'free' sectors.
  797. JR CATLOOP
  798. ;
  799. PRI_NA LD A,(RDESC+4) ;Ignore names starting with CHR$ 0.
  800. OR A
  801. JR Z,CATLOOP
  802. LD A,(RDESC+1) ;Ignore other than first records.
  803. OR A
  804. JR NZ,CATLOOP
  805. LD A,(IX+HDNUMB) ;Jump forward when the whole tape has
  806. CP (IX+CHREC) ;been examined.
  807. JR Z,ENDCAT
  808. CALL OUTNAM ;Examine current record.
  809. CALL PRCR ;Print a carriage return.
  810. LD A,(IX+CHREC) ;Jump unless first time (CHREC=0).
  811. OR A
  812. JP NZ,CATLOOP
  813. LD A,(IX+HDNUMB) ;Store current sector number (to
  814. LD (IX+CHREC),A ldetect when the whole tape has been
  815. JP CATLOOP ;examined).
  816. ;
  817. ENDCAT PUSH IX ;Save channel start address.
  818. XOR A ;Turn off drive motors.
  819. CALL SEL_DRIVE
  820. CALL PRCR ;Leave a blank line.
  821. PUSH IX ;Make HL point to HDNANE.
  822. POP HL
  823. LD DE,2CH
  824. ADD HL,DE
  825. CALL PRNANE ;Print cartridge name.
  826. CALL PRCR ;Print a carriage return.
  827. CALL FREESECT ;Fetch number of 'free' sectors.
  828. LD A,E
  829. SRL A ;A holds the number of Kbytes left.
  830. RST CALBAS ;Store this number on calculator stack.
  831. DEFW STACK_A
  832. RST CALBAS ;Print the number on the screen.
  833. DEFW PRINT_FP
  834. CALL PRCR ;Final carriage return.
  835. POP IX ;Restore channel start address.
  836. CALL DEL_M_BUF ;Reclaim the channel.
  837. JP END1 ;Finished.
  838. ;
  839. PRCR LD A,CR ;Print a carriage return.
  840. JP PRCHAR
  841. ;
  842. GETD PUSH HL ;Save start address.
  843. JP GT_M_BLK ;Fetch descriptor and header information.
  844. ;
  845. RDESC DEFB l8H ;Space to store record descriptor.
  846. ;
  847. OUTNAM LD HL,SCR_CT ;Suppresa scrolling.
  848. LD (HL),0FFH
  849. LD HL,RDESC+4 ;Print record name.
  850. CALL PRNAME
  851. LD A,SPACE ;Follow it with a space.
  852. CALL PRCHAR
  853. LD A,(RDESC) ;This is 'RECFLG'.
  854. BIT 2,A ;Jump if this is not a
  855. JP NZ,NOTPRINT ;'PRINT—type' file.
  856. LD A,PRINT ;Otherwise print the keyword 'PRINT'.
  857. JP PRCHAR
  858. ;
  859. LD A,(HL)
  860. OR A ;Jump with type=0 (program files).
  861. JP Z,PROG
  862. CP 3 ;Jump with type=3 (bytes).
  863. JP Z,BYTES
  864. DEC A ;Save zero flag (set with numeric
  865. PUSH AF ;arrays).
  866. LD A,DATA ;Print the keyword DATA.
  867. CALL PRCHAR
  868. LD A,(RDESC+20) ;Fetch array name.
  869. AND 1FH ;Clear bit 5,6,7.
  870. ADD A,60H ;Obtain an ASCII code.
  871. CALL PRCHAR ;Print array name.
  872. POP AF ;Return with numeric arrays.
  873. RET Z
  874. LD A,"$" ;But print '$' with string arrays.
  875. JP PRCHAR
  876. ;
  877. PROG LD HL,RDESC+23 ;Fetch high byte of autostart line no.
  878. LD A,(HL)
  879. AND 0C0H ;Return if no autostart was specified.
  880. RET NZ
  881. DEC HL ;Point to the low byte.
  882. LD A,LINE ;Print the keyword LINE, and then
  883. CALL PRCHAR ;the line number:
  884. ;
  885. FPRINT LD E,(HL) ;Fetch entry indirectly.
  886. INC HL
  887. LD D,(HL)
  888. EX DE,HL ;Move value into DE.
  889. ;
  890. PRNUM LD DE,10000 ;Print first digit.
  891. CALL PRDIG
  892. LD DE,1000 ;Print second digit.
  893. CALL PRDIG
  894. LD DE,100 ;Print third digit.
  895. CALL PRDIG
  896. LD DE,10 ;Print fourth digit.
  897. CALL PRDIG
  898. LD DE,1 ;Print last digit.
  899. PRDIG LD A,-1 ;Counter.
  900. OUTD INC A ;Increment the counter.
  901. OR A ;Clear carry flag.
  902. SBC HL,DE ;'Trial subtraction'.
  903. JR NC,OUTD ;Continue until borrowing found.
  904. ADD HL,DE ;Balance last SBC.
  905. OR 30H ;Make the counter an ASCII character
  906. JP PRCHAR ;and print it.
  907. ;
  908. BYTES LD A,CODE ;Print the keyword CODE.
  909. CALL PRCHAR
  910. INC HL ;Save pointer to 'length'.
  911. PUSH HL
  912. INC HL
  913. INC HL
  914. CALL FPRINT ;Print the 'start'.
  915. LD A,COMMA ;Print a comma.
  916. CALL PRCHAR
  917. POP HL ;Finally print the 'length'.
  918. JP FPRINT
  919. ;
  920. PRNAME LD B,10 ;Counts ten characters.
  921. PRLOOP LD A,(HL) ;Fetch character,
  922. CALL PRCHAR ;Print it.
  923. INC HL ;Advance the pointer.
  924. DJNZ PRLOOP ;Loop for the whole name.
  925. RET
  926.  
  927.  
  928. The routine can be divided into eleven different sections:
  929. 1. A 'temporary "m" channel' and map is created in the CHANS area.
  930. 2. The required Microdrive is turned on.
  931. 3. The current sector number is stored into CHREC.
  932. 4. A 'header' is loaded from the cartridge into the "m" channel header area.
  933. 5. The 'record descriptor' and the 'header informations' are loaded into the RDESC area.
  934. 6. If the 'header' indicates 'free' sector, the appropriate map bit is reset and the program loops back to step (4)
  935. 7. The filename and the various information are taken from the RDESC area and printed on the screen.
  936. 8. The program continues looping back to (4) until the whole tape has been examined; this is done by comparing the \
  937. current sector number against CHREC one.
  938. 9. The cartridge name is taken from HDNAME and printed.
  939. 10. The number of 'free sectors' is used to print the number of Kbytes left in the cartridge.
  940. 11. The Microdrive motor is turned off, and the channel is reclaimed.
  941.  
  942. Names starting with CHR$ 18 are not printed; records other than 'first' ones are not examined, so as to avoid the \
  943. printing of a filename more than once.
  944. Note that the form *CAT #S;N is not supported, because there is not sufficient time to send the information fetched to \
  945. a channel other than the screen, before the next tape sector is due to be examminined. If you wish to direct the \
  946. catalogue to a printer, you must use first a command such as:
  947.  
  948. OPEN #2;"m";d;"CAT"
  949.  
  950. and then use the *CAT n command. Finally 'CLOSE #2' will send the catalogue to the Microdrive. It can then be printed \
  951. with either:
  952.  
  953. MOVE "m";d;"CAT" TO #3 (with the ZX printer)
  954. MOVE "m";d;"CAT" TO "b" (with RS232 printers)
  955.  
  956. The catalogue can then be erased with ERASE "m";n;"CAT" (where 'n' is the drive number).
  957. In this case, you must take care that the output of the catalogue will not require more than 512 characters to be \
  958. printed (otherwise unpredictable results may occur when the Spectrum tries to send the record to the Microdrive while \
  959. the CAT command is operative). This can be done by making sure that there are fewer than 20 files on the cartridge.
  960. Note that to fail the syntax of the interpreter, the command begins with a '*' character; the command may not begin \
  961. with a 'new' command token, such as CAT, SAVE, ERASE, CLS, etc.
  962.  
  963. Pseudo-random file handling: READ #S,N
  964.  
  965. This command will permit a 'pseudo—random' handling of Microdrive files. When READ #S,N is executed, the 'read' \
  966. Microdrive channel attached to the stream 'S' is used, and record 'n' of that file is loaded into the channel buffer.
  967. Since the Microdtive system splits the main 'PRINT—type' files into records 512 bytes long, you may write items with \
  968. 'length=512', thereby having each record contain a single item, and then read back that item with the READ #S,N \
  969. command.
  970. Such an application is shown by using the following BASIC program. Each item is made by 8 elements (length=63 \
  971. characters + carriage return) of an array, exactly 512 bytes.
  972. Without the READ #S,N command you have to read sequentially all items before reaching the desired one.
  973.  
  974. 10 DIM a$(24,63)
  975. 20 REM Some data for the file
  976. 30 DATA "THE MICRODRIVES", "give you fast access to a large memory.", "", "Each Microdrive can hold up to 100 Kbytes \
  977. on a single", "removable cartridge.", "Note that the Microdrive nearest the computer is always known as", "Microdrive \
  978. 1, and the next along is Microdrive 2, and so on.", "There is also a light on the front of each Microdrive."
  979. 40 DATA "THE CARTRIDGES", "come in a protective box; and should always be kept in their", "box when not in use.", \
  980. "But remember...", "Never take the cartridge out of the Microdrive while the light", "is on.", "Never switch the power \
  981. on or of while a cartridge is in the", "Microdrive."
  982. 50 DATA "THE NETWORK", "enables you and your friends to play computer games together", "and to send each other \
  983. programs and data.", "This means that only one of you need ever type in a program.", "Using the lead supplied with \
  984. each Interface you can link up", "as few as two and as many as 64 Spectrum computers."
  985. 60 OPEN #4;"M";1;"FILE"
  986. 70 FOR a=l TO 24: READ a$(a): NEXT a
  987. 80 CLOSE #4
  988. 90 CLEAR: REM The file has been cleared.
  989. 100 OPEN #4;"M";1;"FILE"
  990. 110 CLS: PRINT "Press a key for your choice: "''"0. MICRODRIVES"''"l. CARTRIDGES"''"2. NETWORK"''"3. STOP"
  991. 120 PAUSE 0: LET a$=INKEY$; IF a$<"0" OR a$>"3" THEN GO TO 110
  992. 130 IF a$="3" THEN CLOSE #4: STOP
  993. 140 READ #4,VAL a$
  994. 150 CLS: FOR a=1 TO 8: INPUT #4;a$: PRINT a$: NEXT a
  995. 160 PAUSE 0: GO TO 110
  996.  
  997.  
  998. If the stream(s) specified in the command is not opened, the error "invalid stream" will occur. "Invalid device \
  999. expression" will occur if the stream is not attached to an "m" channel; "Reading a 'write' file" will occur if the \
  1000. channel is opened for writing.
  1001. The cartridge is simply searched for the 'n'th record of the file 'n' being in range 0..255), then it is loaded and \
  1002. CHBYTE cleared so as to direct INKEY$ and INPUT commands to the first byte loaded.
  1003. If the record is not found, or if any reading error occurs, the error 'File not found' will be reported. The listing \
  1004. of the routine follows.
  1005.  
  1006. PGM7 RST CALBAS ;Advance CH_ADD.
  1007. DEFW NEXT_CHAR
  1008. CP "#" ;A hash sign must be present
  1009. JP NZ,ERR_6 ;after READ.
  1010. RST CALBAS ;Evaluate 's','n'
  1011. DEFW NEXT_2NUM
  1012. CALL ST_END ;Confirm end of statement.
  1013. RST CALBAS ;Fetch 'n'.
  1014. DEFW FND_INT1
  1015. PUSH AF ;Save it for later.
  1016. RST CALBAS ;Fetch 's'.
  1017. DEFW FND_INT1
  1018. CP 10H ;Give an error if 's' is greater than 15
  1019. JP NC,NREPORT-2
  1020. RST CALBAS
  1021. DEFW CHAN_OPEN ;Use this stream.
  1022. LD IX,(CURCHL) ;Fetch channel start address.
  1023. LD A,(IX+4) ;Fetch channel specifier.
  1024. CP "M" ;Error if not an "M" channel.
  1025. JP NZ,NREPORT—3
  1026. BIT 0,(IX+CHFLAG) ;Error if the file is opened for
  1027. JP NZ,RWF—ERR ;writlng.
  1028. POP AF ;Store record number into CHREC.
  1029. LD (IX+CHREC),A
  1030. LD A,(IX+CHDRIV) ;The drive motor is turned on.
  1031. CALL SEL_DRIVE
  1032. LD HL,0FFH ;Counts 255 sectors.
  1033. LD (SECTOR),HL
  1034. CALL GET_R_LP ;Fetch record.
  1035. XOR A ;C1ear CHBYTE.
  1036. LD (IX,CHBYTE),A
  1037. LD (IX+CHBYTE+1),A
  1038. CALL SEL_DRIVE ;Switch off drive motor.
  1039. JP END1 ;Finished.
  1040.  
  1041. Adding data to a file: RESTORE #S
  1042.  
  1043. Normally, if you try to write data onto a Microdrive file that has previously been CLOSEd, the error 'Writing to a \
  1044. 'read' file' will occur. This makes the operation of extending a file with more data difficult, as one has to create a \
  1045. 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 \
  1046. very slow process.
  1047. This command will convert the 'read' file attached to the stream 's' back to a 'write' file, thus permiting the \
  1048. addition of more data. When you have finished adding data, you may CLOSE the stream that returns a 'read' file. You \
  1049. may use RESTORE #S again to convert it into a 'write' file if you wish.
  1050.  
  1051. The following BASIC program will demonstrate this.
  1052.  
  1053. 5 PRINT "CREATING THE FILE"
  1054. 10 OPEN #4;"M";1;"NUMBERS"
  1055. 20 FOR N=1 TO 10
  1056. 30 PRINT #4;N'N*N
  1057. 40 NEXT N
  1058. 50 CLOSE #4
  1059. 60 PRINT '"READING THE FILE"
  1060. 70 OPEN #4;"M";l;'NUMBERS"
  1061. 80 PRINT
  1062. 90 FOR B=1 TO 10
  1063. 100 INPUT #4;M;N
  1064. 110 PRINT "THE SQUARE OF ";M;" IS ";N
  1065. 120 NEXT B
  1066. 130 PRINT '"EXTENDING THE FILE"
  1067. 140 RESTORE #4
  1068. 150 FOR N=11 TO 20
  1069. 160 PRINT #4;N'N*N
  1070. 170 NEXT N
  1071. 180 CLOSE #4
  1072. 190 PRINT '"READING EXTENDED FILE"
  1073. 200 OPEN #4;"M";1;"NUMBERS"
  1074. 210 PRINT
  1075. 220 FOR B=l TO 20
  1076. 230 INPUT #4;M;N
  1077. 240 PRINT "THE SQUARE OF ";M;" IS ";N
  1078. 250 NEXT B
  1079. 260 CLOSE #4
  1080.  
  1081.  
  1082. The routine is as folllows:
  1083.  
  1084. PGM8 RST CALBAS ;Advance CH_ADD.
  1085. DEFW NEXT CHAR
  1086. RST CALBAS
  1087. DEFW EXPT_1NUM ;Evaluate stream number.
  1088. CALL ST_END ;Confirm end of statement.
  1089. RST CALBAS ;Fetch stream number.
  1090. DEFW FND_INT1
  1091. CP 10H ;Reject stream number > 15.
  1092. JP NC,NREPORT-2
  1093. RST CALBAS ;Use this stream.
  1094. DEFW CHAN_OPEN
  1095. LD IX,(CURCHL) ;Fetch channel start address.
  1096. LD A,(IX+4) ;Fetch channel specifier.
  1097. CP "M" ;Error if not an "m" channel.
  1098. JP NZ,NREPORT—3
  1099. BIT 0,(IX+CHFLAG) ;Error also with 'write' files.
  1100. JP NZ,NREPORT—N
  1101. LD A,(IX+CHDRIV) ;Turn on drive motor.
  1102. CALL SEL_DRIVE
  1103. LD HL,0FFH ;Counts through 255 sectors.
  1104. LD (SECTOR),HL
  1105. LOOP CALL G_HD_R ;Fetch header and data block.
  1106. JR C,NXTS ;Jump with any error.
  1107. JR Z,RESBIT ;Jump with 'free' sectors.
  1108. BIT 1,(IX+RECFLG) ;Jump if this is not the last record in
  1109. JR Z,NXTS ;the file.
  1110. LD A,(IX+HDNUMB) ;Otherwise fetch sector number to CHREC.
  1111. LD (IX+CHREC),A
  1112. JR NXTS
  1113. RESBIT CALL RES_B_MAP ;Mark 'free' sector.
  1114. NXTS CALL DEC_SECT ;Continue until the whole tape has been
  1115. JR NZ,LOOP ;examined.
  1116. IN A,(0EFH) ;Error with write—protected cartridge.
  1117. AND 1
  1118. JP Z,RS—SH
  1119. CALL RD_SECTOR ;Fetch the EOF record.
  1120. JP C,RS—SH2 ;Error with wrong checksum.
  1121. LD L,(IX+RECLEN) ;Use RECLEN as current position.
  1122. LD H,(IX+RECLEN+l)
  1123. LD (IX+CHBYTE),L
  1124. LD (IX+CHBYTE+1),H
  1125. SET 0,(IX+CHFLAG) ;Make this a 'write' file.
  1126. CALL IN_CHK ;Set 'free sector' descriptor.
  1127. SLOOP CALL GET_M_HD02 ;Fetch a header block.
  1128. LD A,(IX+CHREC) ;Continue if this is not the one.
  1129. CP (IX+HDNUMB)
  1130. JR NZ,SLOOP
  1131. LD A,0E6H ;Start writing.
  1132. OUT (0EFH),A
  1133. LD BC,0168H ;Wait to create a first gap.
  1134. CALL DELAY_BC
  1135. PUSH IX ;Make HL point to data block preamble.
  1136. POP HL
  1137. LD DE,37H
  1138. ADD HL,DE
  1139. CALL OUT_M_BUF ;Erase this sector.
  1140. LD A,0EEH ;'End of writing' signal.
  1141. OUT (0EFH),A
  1142. CALL RES_B_MAP ;Mark 'free' this sector,
  1143. LD A,(IX+RECNUM) ;Copy RECNUM into CHREC.
  1144. LD (IX+CHREC),A
  1145. XOR A Switch off drive motor.
  1146. CALL SEL_DRIVE
  1147. JP END1 ;Finished.
  1148.  
  1149.  
  1150. The steps involved in doing the RESTORE #S command are as follows:
  1151.  
  1152. 1. A 'Microdrive map' is set—up, for use when the channel is made a 'write' channel.
  1153. 2. The last record of the file is loaded into the channel area.
  1154. 3. That record is erased from the cartridge.
  1155. 4. The channel is marked 'write channel'.
  1156.  
  1157. 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" \
  1158. channel, or with "m" channels opened for writing.
  1159.  
  1160. Extending the RS-232 channel
  1161.  
  1162. This routine creates three new commmands for time user who has an RS232 printer connected to their Spectrum.
  1163. Time first command is LPRINT ? n. If n=1, a new RS232 channel is opened, so subsequent LPRINT and LLIST commands will \
  1164. use this for their outputs. If n=0, the "p" channel is defaulted for the LPRINT and LLIST Commands (the ZX Printer).
  1165. The channel opened has more features than the normal "t" channel. The TAB function and the comma are supported on the \
  1166. printer, the 'leading space bug' present with the "t" channel has been corrected, the CR and LF codes are \
  1167. re—definable, an auto CR feature is supported, and finally a re—definable form—feed code is sent after a certain \
  1168. amount of lines printed, so as to advance to the next page before the printing head reaches the end of the sheet.
  1169. The second command is LPRINT ! x,y. The parameter 'x' will define the width of the line. If, for example, you specify \
  1170. a width equal to 32, the standard Spectrum screen format is used. A width of 40, 80, 132 columns, or other, is \
  1171. suitable depending on your choice, and on the maximum width that your printer allows. The parameter 'y' will define \
  1172. the number of columns used as step when printing the 'comma' control code. The default value for 'x' and 'y' are 80 \
  1173. and 20.
  1174. The last command is LPRINT / x,y. In this case, 'x' will define the number of lines that will be printed before the \
  1175. form feed code (which advances to the next page) is sent to the printer (default=60, suitable for 66—line sheets). The \
  1176. parameter 'y' is the form—feed code that your printer accepts; the standard value is 12. You may store codes other \
  1177. than form—feed, such as linefeed, etc., to obtain different results when the 'x' lines have been printed.
  1178. 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 \
  1179. with a double spacing between lines; the problem may be eliminated with POKE 65045,0.
  1180.  
  1181. The assembly code for our final extension to BASIC is listed below.
  1182.  
  1183.  
  1184. PGM9 RST CALBAS ;Advance CH_ADD.
  1185. DEFW NEXT CHAR
  1186. CP "!"
  1187. JR Z,OUT1 ;Jump with LPRINT !x,y
  1188. CP "/"
  1189. JR Z,OUT2 ;Jump with LPRINT /x,y
  1190. CP "?"
  1191. JR Z,OUT3 ;jump with LPRINT ?n
  1192. JP ERR_6 ;Error if none of these.
  1193. ;
  1194. OUT1 RST CALBAS ;Evaluate 'x,y'.
  1195. DEFW NEXT_2NUM
  1196. CALL ST_END ;Confirm end of statement.
  1197. RST CALBAS ;Fetch 'y'.
  1198. DEFW FND_INT1
  1199. AND A ;Reject spacing=0.
  1200. JP Z,OTRNG
  1201. LD (CMMSP),A ;Store this value.
  1202. RST CALBAS ;Fetch 'x'.
  1203. DEFW FND_INT1
  1204. DEC A ;Range of 'x' is from 0 onwards.
  1205. LD (WIDTH),A ;Store the value.
  1206. JP END1 ;Finished.
  1207. ;
  1208. OUT2 RST CALBAS ;Evaluate 'x,y'
  1209. DEFW NEXT_2NUM
  1210. CALL ST_END ;Confirm end of statement.
  1211. RST CALBAS ;Fetch 'y'
  1212. DEFW FND_INT1
  1213. LD (FFC),A ;Store it.
  1214. RST CALBAS ;Fetch 'x'.
  1215. DEFW FND_ NT1
  1216. LD (LPAGE),A ;Store it.
  1217. XOR A
  1218. LD (CLINE),A ;Clear line counter.
  1219. JP END1 ;Finished.
  1220. ;
  1221. OUT3 RST CALBAS ;Advance CH_ADD.
  1222. DEFW NEXT_CHAR
  1223. RST CALBAS
  1224. DEFW EXPT_1NUM ;Evaluate 'n'
  1225. CALL ST_END ;Confirm end of statement.
  1226. RST CALBAS ;Fetch 'n'
  1227. DEFW FND_INT1
  1228. CP 1
  1229. JR Z,NEWOUT ;Open new channel if n=1.
  1230. LD A,3 ;Otherwise stream 3 reverts to "p"
  1231. RES 1,(IY+FLAGS3) ;channel.
  1232. CALL CLOSE
  1233. JP END1 ;Finished.
  1234. ;
  1235. NEWOUT LD A,3
  1236. RST CALBAS
  1237. DEFW STR_DATA1 ;Fetch current stream data.
  1238. LD HL,11H
  1239. AND A
  1240. SBC HL,BC
  1241. JP C,NREPORT—C ;Error if stream is already opened.
  1242. CALL OP_RS_CH ;Open a "t" channel.
  1243. PUSH DE ;Save stream data.
  1244. LD HL,5 ;Make HL point to 'address of output
  1245. ADD HL,DE ;routine'.
  1246. LD DE,NRSOUT ;Change this address to NRSOUT below.
  1247. LD (HL),E
  1248. INC HL
  1249. LD (HL),D
  1250. LD A,3 ;Use stream 3.
  1251. LD (5CD8H),A
  1252. POP DE ;Restore stream data.
  1253. JP OP_STREAM ;Attach channel to a stream.
  1254. ;
  1255. NRSOUT CP 0A5H ;Use shadow ROM routine with token codes.
  1256. JP NC, TCHAN—OUT+4
  1257. RES 0,(IY+FLAGS) ;Clear 'leading space' flag.
  1258. CP SPACE ;Jump forward with control codes lower
  1259. JR C,CTRL ;than 20H.
  1260. JR NZ,NOSPC ;Jump if not a space.
  1261. SET 0,(IY+FLAGS) ;Otherwise set 'leading space' flag.
  1262. NOSPC PUSH AF ;Save the code temporarily.
  1263. LD A,1 ;Accept next CR code.
  1264. LD (CLRCR),A
  1265. POP AF ;Restore the code.
  1266. CALL TCHAN_OUT ;Use "t" channel to print it,
  1267. LD A,(WIDTH)
  1268. LD B,A
  1269. LD A,(POSN)
  1270. CP B
  1271. JR NC,NLIN ;Jump if POSN>WIDTH.
  1272. INC A ;Otherwise increment POSN.
  1273. LD (POSN),A
  1274. RET
  1275. ;
  1276. NLIN CALL ENDLI ;Advance to next line.
  1277. XOR A ;Disable next CR code.
  1278. LD (CLRCR),A
  1279. RET
  1280. ;
  1281. ENDLI LD A,1 ;Accept next CR code.
  1282. LD (CLRCR),A
  1283. DEC A
  1284. LD (POSN),A ;Clear POSN.
  1285. LD A,(CRCD) ;Fetch CR code.
  1286. AND A
  1287. CALL NZ,BCHAN_OUT ;Send it unless zero.
  1288. LD A,(LFEED) ;Fetch LF code.
  1289. AND A
  1290. CALL NZ,BCHAN_OUT ;Send it unless zero.
  1291. LD A,(LPAGE)
  1292. LD B,A
  1293. LD A,(CLINE)
  1294. INC A
  1295. CP B
  1296. JR NZ,NOFEED ;Jump if not the end of the page.
  1297. LD A,(FFC) ;Fetch form feed code.
  1298. AND A
  1299. CALL NZ,BCHAN_OUT ;Send it unless zero.
  1300. XOR A
  1301. NOFEED LD (CLINE),A ;Store new line number.
  1302. RET
  1303. ;
  1304. CTRL CP CR ;Jump if the code is not CR.
  1305. JR NZ,NOCR
  1306. LD A,(CLRCR)
  1307. AND A ;Check current state of CR flag.
  1308. LD A,1 ;Reset flag to 1 for later.
  1309. LD (CLRCR),A
  1310. RET Z ;Do not do a CR if CLRCR=0.
  1311. JR ENDLI ;Otherwise loop back.
  1312. ;
  1313. NOCR CP PRCOMMA ;Jump if not a comma.
  1314. JR NZ,NOCOMMA
  1315. LD HL,(POSN) ;L= POSN H= WIDTH
  1316. LD A,(CMMSP)
  1317. LD B,A
  1318. LD C,0
  1319. ONESPC INC C ;Increment counters.
  1320. INC L
  1321. LD A,L
  1322. CP H
  1323. JR NC,NLIN ;Jump if POSN>=WIDTH.
  1324. CHKPOS SUB B ;Jump if reached the correct place, or
  1325. JR Z,SPLOOP ;continue if not.
  1326. JR NC,CHKPOS
  1327. JR ONESPC
  1328. ;
  1329. SPLOOP PUSH BC ;Print 'C' spaces by calling recursively
  1330. LD A,SPACE ;this routine.
  1331. CALL NRSOUT
  1332. POP BC
  1333. DEC C
  1334. JR NZ,SPLOOP
  1335. RET
  1336. ;
  1337. NOCOMMA CP TAB ;Return if not the TAB code.
  1338. RET NZ
  1339. LD DE,PAR1 ;Alter output address.
  1340. ;
  1341. ALTOP LD HL,(CURCHL)
  1342. LD B,5
  1343. ADD HL,BC
  1344. LD (HL),E ;Store new output address.
  1345. INC HL
  1346. LD (HL),D
  1347. RET
  1348. ;
  1349. PAR1 LD (TVDATA+1),A ;Store 'n'.
  1350. LD DE,PAR2 ;Output address for next byte.
  1351. JR ALTOP
  1352. ;
  1353. PAR2 LD DE,NRSOUT ;Restore initial output address.
  1354. CALL ALTOP
  1355. LD A,(TVDATA+1) ;Fetch column 'n'.
  1356. LD B,A
  1357. LD A,(WIDTH)
  1358. CP B
  1359. JR NC,GOOD
  1360. OTRNG LD (IY+ERR_NR),0AH ;Error if 'n' is greater than WIDTH.
  1361. RST ROMERR
  1362. GOOD LD A,(POSN)
  1363. SUB B
  1364. RET Z ;Return if already in place.
  1365. JR NC,GRT ;Jump if POSN>'n'.
  1366. NEG ;A=number of spaces required.
  1367. LD C,A
  1368. JR SPLOOP ;Jump back.
  1369. GRT PUSH BC
  1370. CALL ENDLI ;First advance to next line.
  1371. POP BC
  1372. LD C,B
  1373. JR SPLOOP ;Jump back to insert the spaces.
  1374. ;
  1375. POSN DEFB 0
  1376. WIDTH DEFB 80
  1377. CMMSP DEFB 20
  1378. FFC DEFB 12
  1379. LPAGE DEFB 60
  1380. CLRCR DEFB 1
  1381. CRCD DEFB CR
  1382. LFEED DEFB 0AH
  1383. CLINE DEFB 0
  1384. ;
  1385. END
  1386.  
  1387. The EQU statements given here define all the labels referred to in the preceding program:
  1388. ;
  1389. ;Shadow ROM addresses
  1390. ;
  1391. MAIN_ROM EQU 00H
  1392. CALBAS EQU 10H
  1393. SH_ERR EQU 20H
  1394. ROMERR EQU 08H
  1395. NEWVAR EQU 30H
  1396. ERR_6 EQU 01F0H
  1397. NREPORT—C EQU 052FH
  1398. ST_END EQU 05B7H
  1399. END1 EQU 05C1H
  1400. EXPT_NUM EQU 061EH
  1401. NREPORT—2 EQU 0663H
  1402. CHECK_M_2 EQU 066DH
  1403. NREPORT—3 EQU 062DH
  1404. UNPAGE EQU 0700H
  1405. NREPORT—N EQU 0902H
  1406. OP_RS_CH EQU 0B13H
  1407. OP_STREAM EQU 0B4AH
  1408. TCHAN_ OUT EQU 0C3CH
  1409. BCHAN_OUT EQU 0C5AH
  1410. SET_T_MCH EQU 0FE8H
  1411. DEL_M_BUF EQU 10C4H
  1412. RWF—ERR EQU 1132H
  1413. GET_R_LP EQU 1184H
  1414. RS—SH2 EQU 11A3H
  1415. G_HD_RC EQU 11A5H
  1416. GET_M_HD2 EQU 12C4H
  1417. RES_B_MAP EQU 12FEH
  1418. DEC_SECT EQU 1312H
  1419. CHKS_HD_R EQU 1341H
  1420. CLOSE EQU 1718H
  1421. SEL_DRIVE EQU 17F7H
  1422. OUT_M_BUF EQU 1878H
  1423. GT_M_BLK EQU 18ADH
  1424. DELAY_BC EQU 18FAH
  1425. RD_SECTOR EQU 1A4BH
  1426. RS—SH EQU 1AC5H
  1427. FREESECT EQU 1D38H
  1428. PRCHAR EQU 1D66H
  1429. IN_CHK EQU 1E3EH
  1430. DISP_HEX EQU 1E87H
  1431. DISPHEX2 EQU IE9EH
  1432. DISP_CH EQU 1EA9H
  1433. ;
  1434. ;Main ROM addresses
  1435. ;
  1436. ERROR_1 EQU 08H
  1437. GET_CHAR EQU 18H
  1438. NEXT_CHAR EQU 20H
  1439. BEEPER EQU 03B5H
  1440. ED_LOOP EQU 0F38H
  1441. ED_EDIT EQU 0FA9H
  1442. ED_ERROR EQU 107FH
  1443. CHAN_OPEN EQU 1601H
  1444. STR_DATA1 EQU 1727H
  1445. NEXT_2NUM EQU 1C79H
  1446. EXPT_1NUM EQU 1C82H
  1447. EXPT_EXP EQU 1C8CH
  1448. FND_INT1 EQU 1E94H
  1449. FIND_INT2 EQU 1E99H
  1450. STK_FETCH EQU 2BF1H
  1451. STACK_A EQU 2D28H
  1452. PRINT_FP EQU 2DE3H
  1453. ;
  1454. ;System variables
  1455. ;
  1456. TVDATA EQU 5C0EH
  1457. ERR_SP EQU 5C3DH
  1458. E_PPC EQU 5C49H
  1459. CHURCHL EQU 5C51H
  1460. SCR_CT EQU 5C8CH
  1461. VECTOR EQU 5CB7H
  1462. SECTOR EQU 5CC9H
  1463. HD_11 EQU 5CEDH
  1464. ;
  1465. ;Offsets
  1466. ;
  1467. ERR_NR EQU 00H
  1468. FLAGS EQU 01H
  1469. CHBYTE EQU 0BH
  1470. PPC_HI EQU 0CH
  1471. CHREC EQU 0DH
  1472. CHFLAG EQU 18H
  1473. CHDRIV EQU 19H
  1474. HDNUMB EQU 29H
  1475. RECFLG EQU 43H
  1476. RECNUM EQU 44H
  1477. RECLEN EQU 45H
  1478. FLAGS3 EQU 7CH
  1479. ;
  1480. ;Hook codes
  1481. ;
  1482. HOOK31 EQU 31H
  1483. HOOK32 EQU 32H
  1484. ;
  1485. ;Keywords
  1486. ;
  1487. BEEP EQU 0D7H
  1488. CAT EQU 0CFH
  1489. CODE EQU 0AFH
  1490. DATA EQU 0E4H
  1491. LINE EQU 0CAH
  1492. LPRINT EQU 0E0H
  1493. POKE EQU 0F4H
  1494. PRINT EQU 0F5H
  1495. READ EQU 0E3H
  1496. RESTORE EQU 0E5H
  1497. ;
  1498. ;ASCII
  1499. ;
  1500. PRCOMMA EQU 06H
  1501. CR EQU 0DH
  1502. TAB EQU 17H
  1503. SPACE EQU 28H
  1504. COMMA EQU 2CH
  1505. Extending Spectrum BASIC
  1506.  
  1507. The information given in this section, together with the examples given earlier should be sufficient to allow \
  1508. experienced machine code programmers to write their own new BASIC commands, and incorporate them into the Spectrum's \
  1509. BASIC. Non—programmers may still be interested in the details of the Spectrum's BASIC interpreter, and of the \
  1510. ingenious mechanism used to extend it. Please note that this information is primarily designed to give a general \
  1511. explanation of how we have implemented our extended BASIC commands. It is not intended to be a step by step guide to \
  1512. writing new BASIC commands. A fuller explanation of this material is given in The Spectrum Microdrive Book by Dr. Ian \
  1513. Logan, also published by Melbourne House.
  1514. We should first consider the workings of the Spectrums syntax checking routine. When the syntax checker detects an \
  1515. error in a statement, either as it is entered, or at runtime, a jump is made to the error handling routine. This is \
  1516. done by a RST 8 instruction, followed by a byte which defines the error type. Note the similarities between this and \
  1517. the hook codes discussed earlier. As with the normal hook codes, the RST 8 causes a jump to the Shadow ROM where \
  1518. there is a second examination of the current BASIC statement, to see if it really is an error.
  1519. It is this 'second chance' that makes it possible for the new BASIC commands provided by the Interface 1 to exist. \
  1520. These new commands are perceived as errors by the Spectrums ROM, so the error routine is called. This passes control \
  1521. to the Interface 1, where the Shadow ROM does its own syntax checking, recognizes the new commands, and performs the \
  1522. appropriate action for each new command, before passing control back to the main Spectrum ROM. Code is provided in the \
  1523. Shadow ROM for checking commands starting with the following keywords: CAT, FORMAT, MOVE, ERASE, OPEN, SAVE, LOAD, \
  1524. VERIFY, MERGE, CLS, and CLEAR.
  1525. More interesting to us, however, is what happens when a statement 'fails the syntax' (that is, is found to be \
  1526. syntactically incorrect) of both the main ROM and the Shadow ROM. When this happens, the Shadow ROM decides that it \
  1527. really has
  1528. found an error, and jumps to the address which is stored in a system variable called VECTOR. This address is normally \
  1529. that of a main ROM error handling routine, which will print out an error message and cease execution. However, since \
  1530. the variable VECTOR is in RAM, we can change the value it holds to that of our own syntax checking routine, which will \
  1531. check the statement yet again, to see if it is one of the new commands that we have defined. If the statement is one \
  1532. of our new statements, our syntax checker will call a machine language subroutine which will perform the appropriate \
  1533. actions before returning control to the main ROM, otherwise it will call a routine to print an error message.
  1534. So, the control routine that must be added to handle a new statement must have two parts: Firstly, there must be a \
  1535. syntax routine which will identify the new command, any parameters that go with it, and the end of the statement it is \
  1536. in. Secondly, there must be a routine which will do the actual work of the command. Finally, of course, the system \
  1537. variable VECTOR must have been redirected to point to the syntax routine, so that 'errors' detected by the Shadow ROM \
  1538. will be redirected to your routine.
  1539. The syntax of your new command can be anything which will be rejected by the syntax checkers in both the main ROM and \
  1540. the Shadow ROM. Note however, that your command must not start with any of the eleven keywords which are recognised
  1541. by the Shadow ROM (see above).
  1542. The execution of the new commands then, is a fairly complex procedure, comprised of the following steps:
  1543.  
  1544. (i) Command is rejected as being syntactically incorrect by the syntax checking routine in main ROM. Accordingly, an \
  1545. error routine is called, using a RST 8 command.
  1546. (ii) This causes control to be transfered to the syntax checking routine in the Shadow ROM.
  1547. (iii) The Shadow ROM syntax checker rejects your statement, and calls the routine whose address is stored in the \
  1548. variable VECTOR. This would normally be the main ROMs "report an error" routine, but since you have previously changed \
  1549. the contents of VECTOR to point to your own syntax checking routine, it will be your routine that is called.
  1550. (iv) Your syntax routine checks to see that you have given what it regards as a correct command. Once it decides that \
  1551. you have, it calls a routine which you have written to do whatever task is required of the new BASIC command.
  1552. (v) Your routine returns control to the BASIC program which is currently running.
  1553. Although the task of extending the Spectrum's BASIC is quite complex a close study of the examples given in this book \
  1554. should be quite rewarding.
  1555.  
  1556. THE SHADOW ROM DISASSEMBLY
  1557.  
  1558. The restart routines
  1559.  
  1560. THE 'RETURN TO MAIN ROM' RESTART
  1561. This restart is used to return to the "main" ROM, starting from the address held in the stack before calling this \
  1562. routine.
  1563.  
  1564. 0000 MAIN-ROM POP HL Remove return address from the
  1565. machine stack.
  1566. 0001 LD (FLAGS3),+00 Clear FLAGS3.
  1567. 0005 JP 0700,UNPAGE Return to 'main' ROM.
  1568.  
  1569. THE 'START'
  1570. This is the main entry point to the 'shadow' ROM; it is paged in when the Program Counter reaches the address +0008 \
  1571. that is, the address of the main ROM 'ERROR' routine. (The other time in which the "shadow" ROM is paged in is when \
  1572. the Program Counter reaches the address +1708 i.e., the middle of the CLOSE command routine, which is not able to deal \
  1573. with Interface's channels.)
  1574.  
  1575. 0008 ST-SHADOW LD HL,(CH-ADD) The first instruction is common to
  1576. both ROMs.
  1577. 000B POP HL Get the return address
  1578. 000C PUSH HL (usually points to the error code)
  1579. 000D JP 009A,START-2 Jump forward.
  1580.  
  1581. THE 'CALL A MAIN ROM ROUTINE' RESTART
  1582. This routine allows for a subroutine in the 'main' ROM to be called from the 'shadow' ROM, and can be called by using \
  1583. a RST 10 instruction, followed by the address of the 'main' ROM subroutine.
  1584.  
  1585. 0010 CALBAS LD (H-L),HL Save HL into SBRT.
  1586. 0013 POP HL Get the return address (points to the
  1587. address following the RST 10).
  1588. 0014 PUSH DE Save DE temporarily.
  1589. 0015 JR 0081,CALBAS-2 Jump forward.
  1590. 0017 DEFB +FF Unused location.
  1591.  
  1592. THE 'TEST IF SYNTAX IS BEING CHECKED' RESTART
  1593. This corresponds to the 'main' ROM 'SYNTAX-Z' subroutine. A test of bit 7 of FLAGS wHL give the Zero flag set during \
  1594. syntax checking, and reset during
  1595. execution.
  1596.  
  1597. 0018 CHKSYNTAX BIT 7,(FLAGS) Test bit 7 of FLAGS.
  1598. 001C RET Finished.
  1599. 001D DEFB +FF,+FF,+FF Unused locations.
  1600.  
  1601. THE 'SHADOW ERROR' RESTART
  1602. Jumps to the required routine to deal with 'new' report messages. This routine can be called by using a RST 20 \
  1603. instruction followed by the error code (in the range +FF...+16).
  1604.  
  1605. 0020 SH-ERR RST 18,CHKSYNTAX Jump to ST-ERROR if checking
  1606. 0021 JR Z,0068,ST-ERROR syntax, or
  1607. 0023 JR 003A,TEST-SP to TEST-SP during runtime.
  1608. 0025 DEFB +FF,+FF,+FF Unused locations.
  1609.  
  1610. THE 'MAIN ROM ERROR' RESTART
  1611. Before calling this routine, (ERR-NR) must contain the error code.
  1612.  
  1613. 0028 ROMERR RES 3,(TVFLAG) Signal 'the mode is to be considered
  1614. unchanged'
  1615. 002C JR 0040,RMERR-2 jump forward.
  1616. 002E DEFB +FF,+FF Unused locations.
  1617.  
  1618. THE 'CREATE NEW SYSTEM VARIABLES' RESTART
  1619. The routine is entered at 01F7.
  1620.  
  1621. 0030 NEWVARS JP 01F7,CRT-VARS Jump forward immediately.
  1622. 0033 DEFB +FF,+FF,+FF Unused locations.
  1623. 0036 DEFB +FF,+FF
  1624.  
  1625. THE 'MASKABLE INTERRUPT' ROUTINE
  1626. While the 'shadow' ROM is paged-in, the keyboard is not scanned.
  1627.  
  1628. 0038 INT-SERV EI Enable interrupts.
  1629. 0039 RET Return immediately.
  1630.  
  1631. THE 'TEST-SP' ROUTINE
  1632. Check if it is necessary to print the required report message.
  1633.  
  1634. 003A TEST-SP CALL 0077,CHECK-SP Use 'main' ROM error handler if
  1635. required.
  1636. 003D JP 0258,REP-MSG Print the report message.
  1637.  
  1638. THE 'MAIN ROM ERROR' ROUTtNE
  1639. The pressing of BREAK during the loading of 'autorun' programs wHL reset the system; otherwise the error routine \
  1640. continues.
  1641.  
  1642. 0040 RMERR-2 RST 18,CHKSYNTAX Jump forward if checking syntax.
  1643. 0041 JR Z,0068,ST-ERROR
  1644. 0043 CALL 0077,CHECK-SP Use 'main' ROM error handler if
  1645. required.
  1646. 0046 CALL 17B9,RCL-T-CH Reclaim all temporary channels &
  1647. switch off drive motors.
  1648. 0049 BIT 1,(FLAGS3) Jump forward if not
  1649. 004D JR Z,0068,ST-ERROR during the loading of
  1650. 004F BIT 4,(FLAGS3) an 'autorun' program.
  1651. 0053 JR Z,0068,ST-ERROR
  1652. 0055 LD A,(ERR-NR) Fetch the error code.
  1653. 0058 CP +14 Check if attempting to BREAK into the
  1654. loading of an autorun program.
  1655. 005A JR NZ,0068,ST-ERROR Jump if not.
  1656. 005C LD HL,+0000 Otherwise reset the system
  1657. 005F PUSH HL by jumping to the address
  1658. 0060 RST 0,MAIN-ROM +0000 in the 'main' ROM.
  1659. 0061 DEFB +FF,+FF,+FF Unused locations.
  1660. 0064 DEFB +FF,+FF
  1661.  
  1662. THE 'NON-MASKABLE INTERRUPT' ROUTINE
  1663. As with maskable interrupts, there are no service routines.
  1664.  
  1665. 0066 NMINT-SRV RETN Return immediately.
  1666.  
  1667. THE 'ST-ERROR' ROUTINE
  1668. This routine must be entered with the error code in (ERR-NR), and has the same effect as the 'main' ROM 'ERROR' restart.
  1669.  
  1670. 0068 STERROR LD HL,(CHADD) The address of the character reached
  1671. 006B LD (X-PTR),HL by the interpreter is copied into
  1672. the error pointer.
  1673. 006E LD SP,(ERR-SP) Clear machine stack.
  1674. 0072 LD HL,+16C5 Return via 'main' ROM 'SET-STK'
  1675. 0075 PUSH HL routine to the error handler
  1676. 0076 RST 0,MAIN-ROM routine.
  1677.  
  1678. THE 'CHECK-SP' ROUTINE
  1679. Use the 'main' ROM error handler only if bit 2 of FLAGS3 is set.
  1680.  
  1681. 0077 CHECK-SP BIT 2,(FLAGS3) Return. (Normally bit 2 is always
  1682. 007B RET Z reset)
  1683. 007C LD SP,(ERR-SP) Make error handler routine the
  1684. 0080 RST 0,MAIN-ROM return addrcs0 & exit.
  1685.  
  1686. THE 'CALBAS-2' ROUTINE
  1687. This routine uses the SBRT area to call the required routine in the 'main' ROM.
  1688.  
  1689. 0081 CALBAS-2 LD E,(HL) Fetch the address of the subroutine
  1690. 0082 INC HL to be called Into the DE
  1691. 0083 LD D,(HL) register pair.
  1692. 0084 LD (5CBD),DE Use the address with the CALL in
  1693. SBRT area.
  1694. 0088 INC HL Points to the return address.
  1695. 0089 EX (SP),HL Exchange with initial value of DE
  1696. register pair (see 0014).
  1697. 008A EX DE,HL Restore initial value of DE.
  1698. 008B LD HL,+0000 Signal "a 'main' ROM routine has been
  1699. 008E PUSh HL called".
  1700. 008F LD HL,+0008 Return address to the shadow ROM
  1701. 0092 PUSH HL is +0008.
  1702. 0093 LD HL,+5CB9 Call indirectly the
  1703. 0096 PUSH HL SBRT subroutine after having
  1704. 0097 JP 0700,UNPAGE paged-out the 'shadow' ROM.
  1705.  
  1706.  
  1707. The control routine
  1708.  
  1709. This routine is called from ST-SHADOW at 0008 when the shadow ROM is paged-in. It has 3 main tasks:
  1710.  
  1711. - If the paging of the shadow ROM is the return after a call to a 'main' ROM
  1712. subroutine, then it returns to the calling routine.
  1713.  
  1714. - If an Interface's channel has been requested, it jumps to the required 'input'
  1715. or 'output' routine.
  1716.  
  1717. - If an error has occurred in the 'main' ROM, a check is made to see if the
  1718. error code is a 'hook code' (and calls the required routine if it is). If it
  1719. is not a 'hook code', then it checks to determine whether the error is
  1720. "Nonsense in BASIC", "Invalid filename", or "Invalid stream". If it is any of
  1721. these, probably a 'new' command has been used. If so, the routine
  1722. corresponding to the command is called, otherwise the error is produced by
  1723. jumping to the address 01F0 (held in the VECTOR system variable - thus
  1724. altering this address to point a routine in RAM wHL give the possLDility of
  1725. adding more 'new' commands). In all other cases, the main ROM error handler
  1726. is used.
  1727.  
  1728. 009A START-2 PUSH AF Save A register.
  1729. 009B LD A,H Check if the return address
  1730. 009C OR L is zero.
  1731. 009D JR NZ,00A5,START-3 Jump forward if it is not.
  1732. 009F POP AF Otherwise a 'main' ROM routine
  1733. 00A0 POP HL has been called; clear stack.
  1734. 00A1 LD HL,(H-L) Restore HL and return to the
  1735. 00A4 RET calling routine.
  1736.  
  1737. Now see if an Interface's channel has been requested.
  1738.  
  1739. 00A5 START-3 PUSH DE Save DE temporarily.
  1740. 00A6 LD DE,+15FE If a channel has been requested,
  1741. this is the return address stored by
  1742. the CALL 162C inside the 'main' ROM
  1743. 'CALL-SUB' subroutine.
  1744. 00A9 SBC HL,DE Jump forward if no
  1745. 00AB POP DE channels have been requested.
  1746. 00AC JR NZ,00BC,START-4
  1747. 00AE POP AF Restore A register (character to be
  1748. transmitted if during 'output').
  1749. 00AF LD HL,+0700 Make return address the
  1750. 00B2 PUSH HL UNPAGE routine.
  1751. 00B3 LD HL,+0004 DE now holds (address of routine
  1752. pointer - 4).
  1753. 00B6 ADD HL,DE HL holds the address of the routine
  1754. pointer.
  1755. 00B7 LD E,(HL) Fetch the low byte.
  1756. 00B8 INC HL
  1757. 00B9 LD D,(HL) Fetch the high byte.
  1758. 00BA EX DE,HL Move the address to HL.
  1759. 00BB JP (HL) Jump to the appropriate 'input' or
  1760. 'output' routine.
  1761.  
  1762. At this point, the shadow ROM has surely been paged-in by an error in the 'main' ROM.
  1763.  
  1764. 00BC START-4 RST 30,NEWVARS Create interface variables if
  1765. 00BD LD A,+01 non-existent, then send some
  1766. 00BF OUT (+F7),A signals to the Interface 1.
  1767. 00C1 LD A,+EE
  1768. 00C3 OUT (+EF),A
  1769. 00C5 POP AF Remove A temporarily.
  1770. 00C6 POP HL Return address (points to the error
  1771. code after a RST 8).
  1772. 00C7 PUSH AF Save A again.
  1773. 00C8 RST 10,CALBAS This calls a single 'LD A,(HL)'
  1774. 00C9 DEFW +007B instruction, so the error code is
  1775. fetched from the main ROM code.
  1776. 00CB LD (ERR-NR),A Store the error code.
  1777. 00CE CP +FF Check if the error is 'OK'.
  1778. 00D0 JR NZ,00E9,TESTCODE Jump if it is not.
  1779. 00D2 BIT 1,(FLAGS3) This is set when using the 'shadow'
  1780. ROM for the first time (i.e. after
  1781. a NEW command).
  1782. 00D6 JR Z,00E7,NREPORT-0 Give an error if not the first time.
  1783. 00D8 BIT 7,(PPC-hi) Give an error also if the
  1784. 00DC JR Z,00E7,NREPORT-0 line is not in the editing area.
  1785. 00DE LD HL,(E-LINE) Otherwise fetch the command code from
  1786. 00E1 LD A,(HL) the editing area.
  1787. 00E2 CP +F7 Check if the command is 'RUN'.
  1788. 00E4 JP Z,0A95,LOAD-RUN Load the 'run' program from
  1789. Microdrive if so.
  1790.  
  1791. 'Program finished'
  1792.  
  1793. 00E7 NREPORT-0 RST 20,SH-ERR Call the error handling
  1794. 00E8 DEFB +FF routine.
  1795.  
  1796. The error code in A determines the task to be executed.
  1797.  
  1798. 00E9 TEST-CODE SUB +1B Reduce the range.
  1799. 00EB JP NC,1981,HOOK-CODE Jump if it's a hook code, or an
  1800. invalid code (greater than 0-32).
  1801. 00EE CP +F0 Jump if the error is
  1802. 00F0 JR Z,00FB,COPYCHADD 'Nonsense in BASIC'.
  1803. 00F2 CP +F3 Also if 'Invalid filename'.
  1804. 00F4 JR Z,00FB,C0PYCHADD
  1805. 00F6 CP +FC Or 'Invalid stream'.
  1806. 00F8 JP NZ,0028,ROMERR If none of these, use 'main' ROM
  1807. error handler to signal the error.
  1808. 00FB COPYCHADD LD HL,(CH-ADD) The character pointer
  1809. 00FE LD (CHADD-),HL is saved.
  1810. 0101 POP AF Clear the stack.
  1811. 0102 BIT 5,(FLAGX) Use 'main' ROM error handler also if
  1812. 0106 JP NZ,0028,ROMERR in INPUT mode, or
  1813. 0109 BIT 0,(FLAGS3) during execution of a 'new' command.
  1814. 010D JP NZ,0028,ROMERR
  1815. 0110 SET 0,(FLAGS3) Signal "execution of a 'new' command"
  1816. 0114 RST 18,CHKSYNTAX Jump if during runtime.
  1817. 0115 JR NZ,011B,RUNTIME
  1818. 0117 LD (PPC-hi),+FF Signal "syntax time".
  1819.  
  1820. Now a loop is entered to find the line that has produced the error.
  1821.  
  1822. 011B RUNTIME LD B,(SUBPPC) Statement counter.
  1823. 011E LD C,+00 Counter of ' " ' characters.
  1824. 0120 BIT 7,(PPC-hi) Jump forward if the line
  1825. 0124 JR Z,0130,PROG-LINE is in the program area.
  1826. 0126 PUSH BC Save counters.
  1827. 0127 RST 10,CALBAS Call main ROM 'E-LINE-NO' (it fetches
  1828. 0128 DEFW +19FB the number of the line in the editing
  1829. area, but is actually used to update
  1830. CH-ADD to the 1st char. in the line).
  1831. 012A POP BC Restore counters.
  1832. 012B RST l0,CALBAS Call GET-CHAR in the main ROM to
  1833. 012C DEFW +0018 update HL to the 1st character in
  1834. the line.
  1835. 012E JR 016F,S-STAT Jump forward.
  1836. 0130 PROG-LINE LD HL,(PROG) Fetch start of program area.
  1837. 0133 SC-L-LOOP LD A,(PPC-hi) Compare the number of the tine to be
  1838. 0136 CP (HL) searched with that of the 'current'
  1839. line.
  1840. 0137 JR NC,013B,TEST-LOW Jump if the 'current' line no. is
  1841. less than or equal to that of the
  1842. line to be searched for.
  1843.  
  1844. Nonsense in BASIC.
  1845.  
  1846. 0139 NREPORT-1 RST 20,SH-ERR Call the error handling
  1847. 013A DEFB +00 routine.
  1848.  
  1849. 013B TEST-LOW INC HL Points to low byte of line no.
  1850. 013C JR NZ,0144,LINE-LEN Jump if the 'current' line is not the
  1851. expected one.
  1852. 013E LD A,(PPC-lo) Compare also the high byte of
  1853. 0141 CP (HL) the line numbers.
  1854. 0142 JR C,0139,NREPORT-1 Give an error if the line dDEs
  1855. not exist.
  1856. 0144 LINE-LEN INC HL Increment the pointer.
  1857. 0145 LD E,(HL) Fetch low byte of the length.
  1858. 0146 INC HL
  1859. 0147 LD D,(HL) Fetch high byte.
  1860. 0148 INC HL Points to start of the line.
  1861. 0149 JR Z,0l6F,S-STAT Jump if the line is found,
  1862. 014B ADD HL,DE otherwise points to next line.
  1863. 014C JR 0l33,SC-L-LOOP Continue until found.
  1864. 014E SKIP-NUN LD DE,+0006 Length of a floating point number.
  1865. 0151 ADD HL,DE Skip the floating point representat.
  1866.  
  1867. This loop advances the pointer 'HP until it reaches the start of the statement that has produced the error.
  1868.  
  1869. 0152 EACH-ST LD A,(HL) Get a character from line.
  1870. 0153 CP +0E Is it the 'number' marker ?
  1871. 0155 JR Z,0l4E,SKIP-NUM If so, advance the pointer after the
  1872. 'number'.
  1873. 0157 INC HL Points to next character.
  1874. 0158 CP +22 Is the character a '"'?
  1875. 015A JR NZ,015D,CHKEND Jump it it is not.
  1876. 015C DEC C Decrement counter for each '"' found
  1877. 015D CHKEND CP +3A Is the character a colon?
  1878. 015F JR Z,0165,CHKEVEN Jump if it is.
  1879. 0161 CP +CB Jump unless the character is 'THEN'.
  1880. 0163 JR NZ,0l69,CHKEND-L Check whether the number of quotes
  1881. 0165 CHKEVEN BIT 0,C found is even (i.e. colon or THEN
  1882. are out of a string).
  1883. 0167 JR Z,016F,S-STAT Jump if the statement is finished.
  1884. 0169 CHKEND-L CP +80 Check whether the line is finished.
  1885. 016B JR NZ,0152,EACH-ST Continue the loop if not.
  1886. 016D JR 0139,NREPORT-1 Give an error (because a wrong number
  1887. of quotes have been found).
  1888. 016F S-STAT DJNZ 0152,EACH-ST Continue with next statement.
  1889. 0171 DEC HL Now HL holds the start address of the
  1890. required statement.
  1891. 0172 LD (CH-ADD),HL Update CH-ADD to this address.
  1892. 0175 RST 18,CHKSYNTAX Jump forward if during runtime.
  1893. 0176 JR NZ,01AA,CL-WORK
  1894. 0178 BIT 7,(PPC-hi) Give an error report if the line is
  1895. 017C JP Z,01F0,ERR-6 not in the editing area.
  1896.  
  1897. The final loop is made during syntax checking, for removing all 6-byte floating point numbers inserted in the line by \
  1898. the 'main' ROM interpreter.
  1899.  
  1900. 017F DEC HL This balances the INC below.
  1901. 0180 LD C,+00 Clear C register.
  1902. 0182 RCLN-NUM INC HL Points to next character.
  1903. 0183 LD A,(HL) Fetch the character.
  1904. 0184 CP +0E Jump if the character is not the
  1905. 0186 JR NZ,01A5,NEXTNUM start of a 'number'.
  1906. 0188 PUSH BC Save the counter.
  1907. 0189 LD BC,+0006 '6' bytes have to be reclaimed.
  1908. 018C RST 10,CALBAS Call RECLAIM-2 in the 'main' ROM to
  1909. 018D DEFW +19E8 reclaim the 'number'.
  1910. 018F PUSH HL Save HL (points after the reclaimed
  1911. 'number' ).
  1912. 0190 LD DE,(CHADD-) Jump forward if the '6' bytes
  1913. 0194 AND A reclaimed were after the character
  1914. 0195 SBC HL,DE pointed by CHADD-.
  1915. 0197 JR NC,01A3,NXT-1
  1916. 0199 EX DE,HL Otherwise CHADD- needs to be updated.
  1917. First move it into HL.
  1918. 019A LD BC,+0006 The character pointed by CHADD- has
  1919. 019D AND A been moved '6' bytes down.
  1920. 019E SBC HL,BC
  1921. 01A0 LD (CHADD-),HL Store the new value.
  1922. 01A3 NXT-1 POP HL Restore pointer and counter.
  1923. 01A4 POP BC
  1924. 01A5 NEXTNUM LD A,(HL) Jump back into the loop until
  1925. 01A6 CP +0D the line is finished.
  1926. 01A8 JR NZ,0182,RCLM-NUM
  1927.  
  1928. Now the working areas and the new system variables are cleared.
  1929.  
  1930. 01AA CL-WORK RST 10,CALBAS Clear work areas by calling main
  1931. 01AB DEFW +16BF ROM 'SET-WORK' routine.
  1932. 01AD CALL 024D,RES-VARS Reset some 'new' variables to +FF.
  1933.  
  1934. Finally, the command code is fetched from the line, and if it is a 'new' command, the appropriate routine is called.
  1935.  
  1936. 01B0 RST 10,CALBAS Call NEXT-CHAR in the main ROM to
  1937. 01B1 DEFW +0020 fetch the command code.
  1938. 01B3 SUB +CE Reduce range of the code.
  1939. 01B5 CP +01 Ia the command a 'CAT'
  1940. 01B7 JP Z,0486,CAT-SYN Check CAT syntax if so.
  1941. 01BA CP +02 Also for 'FORMAT',...
  1942. 01BC JP Z,04B4,FRMT-SYN
  1943. 01BF CP +03 ...'MOVE',...
  1944. 01C1 JP Z,053D,MOVE-SYN
  1945. 01C4 CP +04 ...'ERASE',...
  1946. 01C6 JP Z,053l,ERASE-SYN
  1947. 01C9 CP +05 ...'OPEN',...
  1948. 01CB JP Z,04ED,OPEN-SYN
  1949. 01CE CP +2A ...'SAVE',...
  1950. 01D0 JP Z,082F,SAVE-SYN
  1951. 01D3 CP +21 ...'LOAD',...
  1952. 01D5 JP Z,0894,LOAD-SYN
  1953. 01D8 CP +08 ...'VERIFY',...
  1954. 01DA JP Z,089E,VERIF-SYN
  1955. 01DD CP +07 ...'MERGE',...
  1956. 01DF JP Z,08A8,MRG-SYN
  1957. 01E2 CP +2D ...'CLS#',...
  1958. 01E4 JP Z,0559,CLS#-SYN
  1959. 01E7 CP +2F ...and 'CLEAR#' command.
  1960. 01E9 JP Z,057F,CLR#-SYN
  1961.  
  1962. If the command that has produced the error was none of these, a jump is made to the address held in VECTOR system \
  1963. variable.
  1964.  
  1965.  
  1966. 01EC ERR-V LD HL,(VECTOR) Jump to the address held in
  1967. 01EF JP (HL) VECTOR (normally ERR-6 below).
  1968.  
  1969. Now the error produced by the main ROM is confirmed.
  1970.  
  1971. 01F0 ERR-6 LD HL,(CHADD-) Restore initial CH-ADD contents.
  1972. 01F3 LD (CH-ADD),HL
  1973. 01F6 RST 28,ROMERR Give the appropriate error.
  1974.  
  1975. THE 'CREATE NEW SYSTEMS VARIABLES' ROUTINE
  1976. This routine is used to create the 'new' system variables if nonexistent and it is called from the restart 0030. Many \
  1977. variables are initialised to its default value.
  1978.  
  1979. 01F7 CRT-VARS LD HL,(CHANS) Fetch start of channel area.
  1980. 01FA LD DE,+A349 This is FFFF-5CB6.
  1981. 01FD ADD HL,DE The carry flag is now set it the
  1982. CHANS area starts after the
  1983. address +5CB6.
  1984. 01FE JR C,0235,VAR-EXIST Jump if the 'new' variables already
  1985. exist.
  1986. 0200 LD HL,+0224 Pre-load machine-stack with the
  1987. 0203 PUSH HL address DEFAHLT below.
  1988. 0204 LD HL,(STKBOT) Clear the calculator
  1989. 0207 LD (STKEND),HL stack.
  1990. 020A LD HL,+5C92 Set MEM with the address of
  1991. 020D LD (MEM),HL MEMBOT area.
  1992. 0210 LD HL,+5CB5 One location before the new space
  1993. is needed.
  1994. 0213 LD BC,+003A Length of space needed.
  1995. 0216 LD DE,+0000 Signal 'a main ROM routine has been
  1996. 0219 PUSH DE called'.
  1997. 021A LD E,+08 Store return address to the
  1998. 021C PUSH DE shadow ROM.
  1999. 021D LD DE,+1655 Return address to main ROM
  2000. 0220 PUSH DE is MAKE-ROOM.
  2001. 0221 JP 0700,UNPAGE
  2002.  
  2003. After the 'insertion' of the new space has been made, the program continues here with the initialisation of some \
  2004. variables.
  2005.  
  2006. 0224 DEFAULT LD HL,+023A Base address of 'default values'
  2007. table.
  2008. 0227 LD BC,+0013 Length of table.
  2009. 022A LD DE,+5CB6 Start of 'new variables' area.
  2010. 022D LDIR Store default values.
  2011. 022F LD A,+01 Set COPIES to +01.
  2012. 0231 LD (COPIES),A
  2013. 0234 RET Finished.
  2014.  
  2015. If the new variables already exist, bit 1 of FLAGS3 is reset.
  2016.  
  2017. 0235 VAR-EXIST RES 1,(FLAGS3) 'New variables already exist'.
  2018. 0239 RET Finished.
  2019.  
  2020. THE 'SYSTEM VARIABLES DEFAHLT VALDES' TABLE
  2021. This table contains the default values of all the 'new' system variables from FLAGS3 to SER-FL.
  2022.  
  2023. 023A DEFB +02 Default value for FLAGS3 (bit 1 is
  2024. set to signal that the aheadow ROM
  2025. has been paged for the first time
  2026. (see 00D2).
  2027. 023B DEFW +01F0 Default for VECTOR is ERR-6 address.
  2028. 023D LD HL,+0000 This short subroutine is the SBRT
  2029. 0240 CALL +0000 'variable', used to call main ROM
  2030. 0243 LD (H-L),HL routines from the shadow ROM.
  2031. 0246 RET
  2032. 0247 DEFW +000C default for BAUD is +000C
  2033. (i.e. 9600 baud).
  2034. 0249 DEFB +01 Default for NTSTAT.
  2035. 024A DEFB +00 Default for IOBORD colour (black).
  2036. 024B DEFW +0000 Default for SER-FL.
  2037.  
  2038. THE 'RESET NEW SYSTEM VARIABLES' SUBROUTINE
  2039. Before using the 'new' system variables from NTRESP to HD-11, their values
  2040. are reset to +FF.
  2041.  
  2042. 024D RES-VARS LD HL,NTRESP Points to the 1st variable.
  2043. 0250 LD B,+22 The block is made by '34' bytes.
  2044. 0252 EACH-VAR LD (HL),+FF Store +FF in all the bytes in
  2045. 0254 INC HL the block.
  2046. 0255 DJNZ 0252,EACH-VAR
  2047. 0257 RET Finished.
  2048.  
  2049. THE 'SHADOW REPORT PRINTING' ROUTINE
  2050. This routine is very similar to 'MAIN-3' (+1303) in the 'main' ROM, but the
  2051. report message printed is one of the 'shadow' report.
  2052.  
  2053. 0258 REP-MSG LD (FLAGS3),+00 First clear FLAGS3.
  2054. 025C EI Enable interrupts.
  2055. 025D HALT Accept one interrupt.
  2056. 025E CALL 17B9,RCL-T-CH Reclaim temporary channels and
  2057. switch off drive motors.
  2058. 0261 RES 5,(FLAGS) Signal 'ready for a new key'.
  2059. 0265 BIT 1,(FLAGS2) Jump if the printer buffer
  2060. 0269 JR Z,026E,FETCH-ERR has not been used, otherwise call
  2061. 026B RST 10,CALBAS COPY-BUFF in the main ROM to empty
  2062. 026C DEFW +0ECD the buffer.
  2063. 026E FETCH-ERR POP HL This address points to the error code
  2064. (after a RST 20).
  2065. 026F LD A,(HL) Fetch error code.
  2066. 0270 LD (ERR-NR),A Store it into ERR-NR.
  2067. 0273 INC A Increment error number.
  2068. 0274 PUSH AF Save the new value.
  2069. 0275 LD HL,+0000 The system variables
  2070. 0278 LD (FLAGX),H FLAGX, X-PTR-hi and DEFADD are all
  2071. 027B LD (X-PTR-hi),H set to zero.
  2072. 027E LD (DEFADD),HL
  2073. 0281 INC L Now HL holds +0001.
  2074. 0282 LD (+5C16),HL Displacement for stream 0 is made
  2075. +0001 (i.e. reset stream 0 to the
  2076. "K" channel).
  2077. 0285 RST 10,CALBAS Clear work areas, calculator stack
  2078. 0286 DEFW +16B0 by calling SET-MIN.
  2079. 0288 RES 5,(FLAGX) Signal 'editing mode'.
  2080. 028C RST 10,CALBAS Clear lower screen by calling
  2081. 028D DEFW +0D6E CLS-LOWER.
  2082. 028F SET 5,(TVFLAG) Signal 'the lower screen is to be
  2083. cleared'.
  2084. 0293 RES 3,(TVFLAG) Signal 'the mode is to be conside-
  2085. red unchanged'.
  2086. 0297 POP AF Restore error number.
  2087. 0298 LD HL,+02B7 Base address of 'report messages'
  2088. table.
  2089. 029B LD B,+04 Hake BC hold a sufficiently high
  2090. number.
  2091. 029D CPIR Advance HL to the required report
  2092. message in the table.
  2093. 029F PR-REP-LP LD A,(HL) Fetch character of message.
  2094. 02A0 CP +20 Print it unless reached the
  2095. 02A2 JR C,02AC,END-PR-MS 'marker' of next message.
  2096. 02A4 PUSH HL Save pointer.
  2097. 02A5 RST 10,CALBAS Call main ROM 'PRINT-A' restart
  2098. 02A6 DEFW +0010 to print the character.
  2099. 02A8 POP HL Restore pointer.
  2100. 02A9 INC HL Point to next character.
  2101. 02AA JR 029F,PR-REP-LP Continue with next character.
  2102. 02AC END-PR-MS LD SP,(ERR-SP) Clear machine stack.
  2103. 02B0 INC SP Ignore also the address +1303
  2104. 02B1 INC SP pointed by ERR-SP (that is
  2105. replaced with the +1349 below).
  2106. 02B2 LD HL,+1349 Return to the main ROM in the
  2107. 02B5 PUSH HL middle of the 'print report message
  2108. 02B6 RST 0,MAIN-ROM routine.
  2109.  
  2110. THE 'SHADOW' REPORT MESSAGES
  2111. Before each report there is the correspondent error code, incremented by 1.
  2112.  
  2113. 02B7 DEFB +00
  2114. 02B8 DEFM "Program finished"
  2115. 02C8 DEFB +01
  2116. 02C9 DEFM "Nonsense in BASIC"
  2117. 02DA DEFB +02
  2118. 02DB DEFM "Invalid stream number"
  2119. 02F0 DEFB +03
  2120. 02F1 DEFM "Invalid device expression"
  2121. 030A DEFB +04
  2122. 030B DEFM "Invalid name"
  2123. 0317 DEFB +05
  2124. 0318 DEFM "Invalid drive number"
  2125. 032C DEFB +06
  2126. 032D DEFM "Invalid station number"
  2127. 0343 DEFB +07
  2128. 0344 DEFM "Missing name"
  2129. 0350 DEFB +08
  2130. 0351 DEFM "Missing station number"
  2131. 0367 DEFB +09
  2132. 0368 DEFM "Missing drive number"
  2133. 037C DEFB +0A
  2134. 037D DEFM "Missing baud rate"
  2135. 038E DEFB +0B
  2136. 038F DEFM "Header mismatch error"
  2137. 03A4 DEFB +0C
  2138. 03A5 DEFM "Stream already open"
  2139. 03B8 DEFB +0D
  2140. 03B9 DEFM "Writing to a 'read' file"
  2141. 03D1 DEFB +0E
  2142. 03D2 DEFM "Reading a 'write' file"
  2143. 03E8 DEFB +0F
  2144. 03E9 DEFM "Drive 'write' protected"
  2145. 0400 DEFB +10
  2146. 0401 DEFM "Microdrive full"
  2147. 0410 DEFB +11
  2148. 0411 DEFM "Microdrive not present"
  2149. 0427 DEFB +12
  2150. 0428 DEFM "File not found"
  2151. 0436 DEFB +13
  2152. 0437 DEFM "Hook code error"
  2153. 0446 DEFB +14
  2154. 0447 DEFM "CODE error"
  2155. 0451 DEFB +15
  2156. 0452 DEFM "MERGE error"
  2157. 045D DEFB +16
  2158. 045E DEFM "Verification has failed"
  2159. 0475 DEFB +17
  2160. 0476 DEFM "Wrong file type"
  2161. 0485 DEFB +18
  2162.  
  2163.  
  2164. The syntax checking routines
  2165.  
  2166. The routines in this section of the shadow ROM check the syntax of the 'new' commands and call the command routines \
  2167. during runtime.
  2168.  
  2169. THE 'CAT' COMMAND SYNTAX ROUTINE
  2170. 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 \
  2171. before exiting in syntax time or executing the CAT during runtime.
  2172.  
  2173. 0486 CAT-SYN LD HL,S-STR1 First make the screen
  2174. 0489 LD (HL),+02 'current' stream.
  2175. 048B RST 10,CALBAS Advance CH-ADD with a call to
  2176. 048C DEFW +0020 'NEXT-CHAR' in the main ROM.
  2177. 048E CP +0D If the line ends here, jump to
  2178. 0490 JR Z,0494,MISSING-D produce an error.
  2179. 0492 CP +3A Give an error also if the
  2180. 0494 MISSING-D JP Z,0683,NREPORT-9 statement ends with a colon.
  2181. 0497 CP +23 Jump if after the keyword
  2182. 0499 JR NZ,04A6,CAT-SCRN there is not the 'hash' character.
  2183. 049B CALL 064E,EXPT-STRM Otherwise evaluate stream number.
  2184. 049E CALL 05B1,SEPARATOR Give an error if after the stream
  2185. 04A1 JR NZ,04B2,OREPORT-1 number there is no separator.
  2186. 04A3 RST 10,CALBAS Advance CH-ADD to next
  2187. 04A4 DEFW +0020 character.
  2188. 04A6 CAT-SCRN CALL 061E,EXPT-NUM Evaluate drive number.
  2189. 04A9 CALL 05B7,ST-END Confirm end of statement and exit
  2190. during syntax time.
  2191. 04AC CALL 066D,CHECK-M-2 Checks that drive number held in
  2192. D-STR1 is in range.
  2193. 04AF JP 1E70,CAT-RUN Do the CATalogue.
  2194.  
  2195. 'Nonsense, in BASIC'
  2196. 04B2 OREPORT-1 RST 20,SH-ERR Call the error handling
  2197. 04B3 DEFB +00 routine.
  2198.  
  2199. THE 'FORMAT' COMMAND SYNTAX ROUTINE
  2200. A FORMAT command may have one of the following forms: FORMAT "m";n;"name" -FORMAT "b";n - FORMAT "t";n - FORMAT "n";n. \
  2201. This routine handles all forms and
  2202. sets N-STR1, L-STR1 and D-STR1 as required before exiting during syntax checking, or executing the command during \
  2203. runtime.
  2204.  
  2205. 04B4 FRMT-SYN CALL 05F2,EXPT-SPEC Evaluate (string)(separator)(number)
  2206. and set L-STR1, D-STR1.
  2207. 04B7 CALL 05Bl,SEPARATOR If there is not a further
  2208. 04BA JR NZ,04BF,NO-FOR-M separator, no filename is to be
  2209. expected, so jump.
  2210. 04BC CALL 062F,EXPT-NAME Evaluate "name" and set N-STR1.
  2211. 04BF NO-FOR-M CALL 05B7,ST-END Confirm end of statement and exit
  2212. during syntax checking.
  2213. 04C2 LD A,(L-STR1) Fetch channel specifier.
  2214. 04C5 CP +54 Jump with FORMAT "T"
  2215. 04C7 JR Z,04CD,FOR-B-T
  2216. 04C9 CP +42 Test for FORMAT "B" - note that the
  2217. routine is the same as that of
  2218. FORMAT "T".
  2219. 04CB JR NZ,04D3,NOT-FOR-B Jump with "N" and "M" channels.
  2220. 04CD FOR-B-T CALL 06B0,TEST-BAUD Check that D-STR1 holds a valid baud
  2221. rate.
  2222. 04D0 JP 0AC9,SET-BAUD Set BAUD variable from D-STR1 value
  2223. (the actual FORMAT with RS232 link).
  2224. 04D3 NOT-FOR-B CP +4E Jump if not a FORMAT "N" command.
  2225. 04D5 JR NZ,04E7,FOR-M
  2226. 04D7 CALL 068F,TEST-STAT Check that D-STR1 holds a valid
  2227. station number.
  2228. 04DA LD A,(D-STR1) Give an error if attempting to
  2229. 04DD AND A FORMAT "n"';0 (i.e. with the
  2230. 04DE JP Z,069F,NREPORT-6 'broadcast' specifier).
  2231. 04E1 LD (NTSTAT),A This is the actual FORMAT command
  2232. with the network.
  2233. 04E4 JP 05C1,END1 Finished.
  2234. 04E7 FOR-M CALL 0685,TEST-MNAM Check that the various parameters
  2235. are correct.
  2236. 04EA JP 1E75,FOR-RUN Do the FORMAT "M" command.
  2237.  
  2238. ThE 'OPEN' COMMAND SYNTAX ROUTINE
  2239. This routine deals with OPEN #s;"m";n;"name" - OPEN #s;"b" - OPEN #s;"t" -
  2240. OPEN #s;"n";n commands. All parameters are stored into S-STR1, N-STR1, D-STR1 and L-STR1 variables before exiting \
  2241. during syntax checking or executing the command during runtime.
  2242.  
  2243. 04ED OPEN-SYN CALL 064E,EXPT-STRM Evaluate stream number.
  2244. 04F0 CALL 05B1,SEPARATOR Give an error report if the separator
  2245. 04F3 JR NZ,04B2,OREPORT-1 has been missed after 'stream no.'
  2246. 04F5 CALL 05F2,EXPT-SPEC Evaluate channel specifier,
  2247. (separator numeric expression).
  2248. 04F8 CALL 05B1,SEPARATOR Jump if no further separator is
  2249. 04FB JR NZ,0500,NOT-OP-M present.
  2250. 04FD CALL 062F,EXPT-NAME Otherwise evaluate "name".
  2251. 0500 NOT-OP-M CALL 05B7,ST-END Confirm end of statement and exit
  2252. if syntax is being checked.
  2253. 0503 LD A,(S-STR1) Fetch stream number.
  2254. 0506 RST 10,CALBAS Call main ROM 'STR-DATA1' routine;
  2255. 0507 DEFW +1727 on exit, BC holds 'stream data'.
  2256. 0509 LD HL,+0011 In fact, jump if the current stream
  2257. 050C AND A is already opened with a 'new'
  2258. 050D SBC HL,BC channel.
  2259. 050F JR C,052F,NREPORT-C
  2260. 0511 LD A,(L-STR1) Fetch channel specifier.
  2261. 0514 CP +54 Jump if opening a 't' channel.
  2262. 0516 JR Z,051C,OPEN-RS
  2263. 0518 CP +42 Jump if not a 'b' channel.
  2264. 051A JR NZ,051F,NOT-OP-B
  2265. 051C OPEN-RS JP 0B47,OP-RSCHAN Do the OPEN referred to RS232 link.
  2266. 051F NOT-OP-B CP +4E Jump if not a 'n' channel (i.e.
  2267. 0521 JR NZ,0520,OP-M-C with 'm' channel).
  2268. 0523 CALL 068F,TEST-STAT Check that D-STR1 holds a valid
  2269. station number.
  2270. 0526 JP 0EA3,OPEN-N-ST Do the OPEN referred to the network.
  2271. 0529 OP-M-C CALL 0685,TEST-MNAM Check that all parameters are valid.
  2272. 052C JP 1E7A,OP-RUN Do the OPEN "M" command.
  2273.  
  2274. 'Stream already open'
  2275. 052F NREPORT-C RST 20,SH-ERR Call the error handling
  2276. 0530 DEFB +0B routine.
  2277.  
  2278. THE 'ERASE' COMMAND SYNTAX ROUTINE
  2279. This command has only one form and, thus, this routine is more straightforward than the preceding ones.
  2280.  
  2281. 0531 ERASE-SYN CALL 06A3,EXPT-EXPR Evaluate ("m";n;"name")
  2282. 0534 CALL 05B7,ST-END Confirm end of statement and exit
  2283. during syntax checking.
  2284. 0537 CALL 0685,TEST-MNAM Check that all parameters are
  2285. valid.
  2286. 053A JP 1E66,ERASE-RUN Do the ERASE command.
  2287.  
  2288. THE 'MOVE' COMMAND SYNTAX ROUTINE
  2289. A 'MOVE' command requires two sets of parameters, for the 'input' channel and for the 'output' channel. These \
  2290. parameters are stored respectively in the two areas D-STR1 and D-STR2.
  2291.  
  2292. 053D MOVE-SYN CALL 06B9,EXPT-EXP1 Evaluate stream number, or channel
  2293. expression.
  2294. 0540 CALL 059F,EX-D-STR Exchange D-STR1 and D-STR2 contents.
  2295. 0543 RST 10,CALBAS Call GET-CHAR in the main ROM.
  2296. 0544 DEFW +0018
  2297. 0546 CP +CC The keyword 'TO' must be present
  2298. 0548 JR NZ,0584,NONSENSE between the two expressions.
  2299. 054A CALL 06B9,EXPT-EXP1 Evaluate 2nd stream number, or
  2300. channel expression.
  2301. 054D CALL 059F,EX-D-STR Exchange again D-STR areas.
  2302. 0550 RST 10,CALBAS Call GET-CHAR in the main ROM.
  2303. 0551 DEFW +0018
  2304. 0553 CALL 05B7,ST-END Confirm end of statement and exit
  2305. during syntax checking.
  2306. 0556 JP 1E6B,MOVE-RUN Do the MOVE command,
  2307.  
  2308. THE 'CLS#' COMMAND ROUTINE
  2309. This routine has the tasks of both 'syntax checking' and 'execution'. During runtime, ATTR-P, ATTR-T, MASK-P, MASK-T, \
  2310. P-FLAG and BORDCR system variables are reset to the 'initiaP value (as after a NEW command).
  2311.  
  2312. 0559 CLS#-SYN RST 10,CALBAS Advance CH-ADD after the
  2313. 055A DEFW +0020 keyword CLS.
  2314. 055C CP +23 The character must be a '#'.
  2315. 055E JR NZ,0584,NONSENSE
  2316. 0560 RST 10,CALBAS Advance CH-ADD again.
  2317. 0561 DEFW +0020
  2318. 0563 CALL 05B7,ST-END Confirm end of statement and exii
  2319. during syntax checking.
  2320. 0566 LD HL,+0038 +38 is the attribute byte.
  2321. 0569 LD (ATTR-P),HL Store +38 into ATTR-P, clear MASK-P.
  2322. 056C LD (ATTR-T),HL Store +38 into ATTR-T, clear MASK-T.
  2323. 056F LD (BORDCR),L Store +38 also for lower screen
  2324. attribute.
  2325. 0572 LD (P-FLAG),H Clear P-FLAG.
  2326. 0575 LD A,+07 Set white border.
  2327. 0577 OUT (+FE),A
  2328. 0579 RST 10,CALBAS Call main ROM 'CLS' routine.
  2329. 057A DEFW +0D6B
  2330. 057C JP 05Cl,END1 Finished.
  2331.  
  2332. THE 'CLEAR#' COMMAND ROUTINE
  2333. As in the previous routine, this routine both 'checks' and 'executes' the command. All streams are closed in turn, \
  2334. with bit 1 of FLAGS3 set to signal
  2335. that the remaining buffer contents are to be erased (no data is sent, as
  2336. opposed to the case of a CLOSE# command).
  2337.  
  2338. 057F CLR#-SYN RST 10,CALBAS Advance CH-ADD.
  2339. 0580 DEFW +0020
  2340. 0582 CP +23 The character must be a '#'.
  2341. 0584 NONSENSE JP NZ,04B2,OREPORT-1
  2342. 0587 RST 10,CALBAS Advance CH-ADD again.
  2343. 0588 DEFW +0020
  2344. 058A CALL 05B7,ST-END Confirm end of statement and exit
  2345. during syntax checking.
  2346. 058D XOR A Start with stream 0.
  2347. 058E ALL-STRMS PUSH AF Save stream number.
  2348. 058F SET 1,(FLAGS3) Signal 'CLEAR# command'.
  2349. 0593 CALL 1718,CLOSE Close the current stream.
  2350. 0596 POP AF Restore stream number.
  2351. 0597 INC A Each stream in turn is examined.
  2352. 0598 CP +10 Continue until all streams 0..15
  2353. 059A JR C,058E,ALL-STRMS have been closed.
  2354. 059C JP 05C1,END1 Finished.
  2355.  
  2356. THE 'EXCHANGE FILE SPECIFIERS' SUBROUTINE
  2357. This subroutine exchanges the contents of D-STR1 area with those of the D-STR2 area and vice-versa.
  2358.  
  2359. 059F EX-D-STR LD HL,+5CD6 Start of first area.
  2360. 05A2 LD DE,+5CDE Start of 2nd area.
  2361. 05A5 LD B,+08 Both areas are 8 bytes in length.
  2362. 05A7 ALL-BYTES LD A,(DE) Fetch a byte from D-STR2.
  2363. 05A8 LD C,(HL) Fetch a byte from D-STR1.
  2364. 05A9 LD (HL),A Store into D-STR1 the byte coming
  2365. from D-STR2.
  2366. 05AA LD A,C Byte from D-STR1.
  2367. 05AB LD (DE),A Store it into D-STRZ.
  2368. 05AC INC HL Advance the pointers.
  2369. 05AD INC DE
  2370. 05AE DJNZ 05A7,ALL-BYTES Continue until the areas have
  2371. been exchanged.
  2372. 05B0 RET Finished.
  2373.  
  2374. THE 'SEPARATOR' SUBROUTINE
  2375. This short subroutine is called several times to see if the character held in the accumulator is a valid separator \
  2376. (i.e. a comma or a semicolon). A return with the Zero flag reset is made if the character is not a separator.
  2377.  
  2378. 05B1 SEPARATOR CP +2C Is the character a comma?
  2379. 05B3 RET Z Return with zero flag set if so.
  2380. 05B4 CP +3B Is the character a semicolon?
  2381. 05B6 RET Return with zero flag set if so.
  2382.  
  2383. THE 'END OF STATEMENT' ROUTINE
  2384. After the syntax of the 'new' commands has been checked, a jump is made here to confirm that the statement is \
  2385. finished. An error report is given if there are some characters left in the line. A return is made to the calling \
  2386. routine only during runtime, otherwise the control returns to the 'main' ROM interpreter.
  2387.  
  2388. 05B7 ST-END CP +0D Jump if the statement ends
  2389. 05B9 JR Z,05BF,TEST-RET with ENTER.
  2390. 05BB CP +3A Give an error if character is not
  2391. 05BD JR NZ,0584,NONSENSE a colon (i.e. the statement is not
  2392. finished).
  2393. 05BF TEST-RET RST 18,CHKSYNTAX Return only during runtime,
  2394. 05C0 RET NZ otherwise continue below.
  2395.  
  2396. THE 'RETURN TO THE MAIN INTERPRETER' ROUTINE
  2397. The control returns to the main interpreter, when a 'new' command has been checked or executed, for the interpretation \
  2398. of the next statement.
  2399.  
  2400. 05C1 END1 LD SP,(ERR-SP) Clear machine stack.
  2401. 05C5 LD (ERR-NR),+FF Clear error code.
  2402. 05C9 LD HL,+1BF4 Return address to main ROM is
  2403. 05CC RST 18,CHKSYNTAX STMT-NEXT if syntax being checked.
  2404. 05CD JR Z,05E0,RETAD-RUN-SYN
  2405. 05CF LD A,+7F Give, an error if BREAK is pressed
  2406. 05D1 IN A,(+FE) during runtime.
  2407. 05D3 RRA
  2408. 05D4 JR C,05DD,RETAD-RUN
  2409. 05D6 LD A,+FE
  2410. 05D8 IN A,(+FE)
  2411. 05DA RRA
  2412. 05DB JR NC,05E2,BREAK-PGM
  2413. 05DD RETAD-RUN LD HL,+1B7D Return address during runtime is
  2414. STMT-R-1.
  2415. 05E0 RETAD-SYN PUSH HL Save the return address.
  2416. 05E1 RST 0,MAIN-ROM Return to the main ROM interpreter.
  2417.  
  2418. 'BREAK into program'
  2419. 05E2 BREAK-PGM LD (ERR-NR),+14 Store the error code and call
  2420. 05E6 RST 28,ROMERR the error handling routine.
  2421.  
  2422. THE 'EVALUATE STRING EXPRESSION' SUBROUTINE
  2423. A call to the main ROM 'EXPT-EXP' (class-9A) subroutine is made, to evaluate a string expression. During runtime the \
  2424. parameters of the string (start and length) are returned in the DE and BC register pairs.
  2425.  
  2426. 05E7 EXPT-STR RST 10,CALBAS Call 'EXPT-EXP' in the main ROM.
  2427. 05E8 DEFW +1C8C
  2428. 05EA RST 18,CHKSYNTAX Return if syntax is being checked
  2429. 05EB RET Z
  2430. 05EC PUSH AF Save the zero flag and the character
  2431. following the string.
  2432. 05ED RST 10,CALBAS Call 'STK-FETCH' in the main ROM to
  2433. 05EE DEFW +2BF1 fetch the parameters.
  2434. 05F0 POP AF Zero flag reset to signal 'runtime'
  2435. 05F1 RET Finished.
  2436.  
  2437. THE 'EVALUATE CHANNEL SPECIFIER' SUBROUTINE
  2438. The subroutine is entered at EXPT-SPEC or at EXP-SPEC2 depending upon whether or not the character pointer is to be \
  2439. updated to the next character. A single character string is evaluated, and its upper case ASCII value is stored into
  2440. L-STR1 during runtime. If a separator is present after the single character string, then the routine continues into \
  2441. EXPT-NUM.
  2442.  
  2443. 05F2 EXPT-SPEC RST 10,CALBAS Advance CH-ADD.
  2444. 05F3 DEFW +0020
  2445.  
  2446. 05F5 EXP-SPEC2 CALL 95E7,EXPT-STR Evaluate string expression.
  2447. 05F8 JR Z,060C,TEST-NEXT Jump if syntax is being checked.
  2448. 05FA PUSH AF Save the character following the
  2449. string.
  2450. 05FB LD A,C 'A' holds the low byte of the
  2451. string length.
  2452. 05FC DEC A Jump if there is more than one
  2453. 05FD OR B character in the string (also if the
  2454. 05FE JR NZ,062D,NREPORT-3 string is null).
  2455. 0600 LD A,(DE) Fetch the channel specifier.
  2456. 0601 RST 10,CALBAS Call 'ALPHA' to see whethe nt isi
  2457. 0602 DEFW +2C8D valid letter.
  2458. 0604 JR NC,062D,NREPORT-3 Jump if it is not a valid letter
  2459. 0606 AND +DF Make the letter upper case.
  2460. 0608 LD (L-STR1),A Store the channel specifier.
  2461. 060B POP AF The 'next character' is restored.
  2462. 060C TEST-NEXT CP +0D Return if it is ENTER, or a colon,
  2463. 060E RET Z
  2464. 060F CP +3A
  2465. 0611 RET Z
  2466. 0612 CP +A5 Return also with a keyword.
  2467. 0614 RET NC
  2468. 0615 CALL 05B1,SEPARATOR Otherwise a separator must be found.
  2469. 0618 JP NZ,04B2,OREPORT-1 Give an error if not found.
  2470. 061B RST 10,CALBAS A numeric expression (i.e. drive
  2471. 061C DEFW +0020 no.,station no., baud rate) is
  2472. expected. But first advance CH-ADD
  2473. past the separator.
  2474.  
  2475. THE 'EVALUATE NUMERIC EXPRESSION' SUBROUTINE
  2476. This subroutine is used whenever a single numeric expression is to be evaluated. The result is returned during runtime \
  2477. into the BC register pair and into the
  2478. D-STR1 system variable.
  2479.  
  2480. 061E EXPT-NUM RST 10,CALBAS Call EXPT-NUM in the main ROM to
  2481. 061F DEFW +1C82 evaluate the expression.
  2482. 0621 RST 18,CHKSYNTAX Return if syntax is being checked.
  2483. 0622 RET Z
  2484. 0623 PUSH AF Save character following the
  2485. expression and zero flag.
  2486. 0624 RST 10,CALBAS Call FIND-INT2 to fetch the
  2487. 0625 DEFW +1E99 value from calculator stack.
  2488. 0627 LD (D-STR1),BC Store the value.
  2489. 062B POP AF Restore character and zero flag.
  2490. 062C RET Finished.
  2491.  
  2492. 'Invalid device expression'
  2493.  
  2494. 062D NREPORT-3 RST 20,SH-ERR Call the error handling
  2495. 062E DEFB +02 routine.
  2496.  
  2497. THE 'EVALUATE FILENAME' SUBROUTiNE
  2498. A string expression is evaluated and, provided that the length is within the range 1..10 characters, the 'length' and \
  2499. the 'start' of that string are stored into N-STR1 and (N-STR1 + 2).
  2500.  
  2501. 062F EXPT-NAME RST 10,CALBAS Advance CH-ADD.
  2502. 0630 DEFW +0020
  2503. 0632 CALL 05E7,EXPT-STR Evaluate the string.
  2504. 0635 RET Z Return if syntax is being checked.
  2505. 0636 PUSH AF Save zero flag and 'next character'.
  2506. 0637 LD A,C Give an error with null string.
  2507. 0638 OR B
  2508. 0639 JR Z,064C,NREPORT-4
  2509. 063B LD HL,+000A Give the error also if 'length'
  2510. 063E SBC HL,BC exceeds ten characters.
  2511. 0640 JR C,064C,NREPORT-4
  2512. 0642 LD (N-STR1),BC Store the 'length'.
  2513. 0646 LD (N-STR1+2),DE Store the 'start'.
  2514. 064A POP AF Restore A and zero flag.
  2515. 064B RET Finished.
  2516.  
  2517. 'Invalid name'
  2518.  
  2519. 064C NREPORT-4 RST 20,SH-ERR Call the error handling
  2520. 064D DEFB +03 routine.
  2521.  
  2522. THE 'EVALUATE STREAM NUMBER' SUBROUTINE
  2523. A single numeric expression is evaluated and the result, in the range 0..15, is stored into S-STR1 variable during \
  2524. runtime.
  2525.  
  2526. 064E EXPT-STRM RST 10,CALBAS Advance CH-ADD.
  2527. 064F DEFW +0020
  2528. 0651 RST 10,CALBAS Call EXPT-1NUM to evaluate a numeric
  2529. 0652 DEFW +1C82 expression.
  2530. 0654 RST 18,CHKSYNTAX Return if syntax is being checked.
  2531. 0655 RET Z
  2532. 0656 PUSH AF Save 'next character' and zero flag.
  2533. 0657 RST 10,CALBAS Call FIND-INT1 to fetch the value.
  2534. 0658 DEFW +1E99
  2535. 065A CP +10 Test for numbers greater than 15.
  2536. 065C JR NC,0663,NREPORT-2
  2537. 065E LD (S-STR1),A Store stream number.
  2538. 0661 POP AF Restore A and zero flag.
  2539. 0662 RET Finished.
  2540.  
  2541. 'Invalid stream number'
  2542.  
  2543. 0663 NREPORT-2 RST 20,SH-ERR Call the error handling
  2544. 0664 DEFB +01 routine.
  2545.  
  2546. THE 'CHECK "M" PARAMETERS' SUBROUTINE
  2547. A return to the calling routine is made only if L-STR1 denotes the Microdrive device being used, and if D-STR1 holds a \
  2548. valid drive number.
  2549.  
  2550. 0665 CHECK-M LD A,(L-STR1) Fetch channel specifier.
  2551. 0668 CP +4D Is it "M"?
  2552. 066A JP NZ,062D,NREPORT-3 Report the error if it is not.
  2553. 066D CHECK-M-2 LD DE,(D-STR1) Fetch drive number.
  2554. 0671 LD A,E Report an error if zero.
  2555. 0672 OR D
  2556. 0673 JR Z,0681,NREPORT-5
  2557. 0675 INC DE Test against +FFFF.
  2558. 0676 LD A,E Report an error if no drive number
  2559. 0677 OR D has been evaluated.
  2560. 0678 JR Z,0683,NREPORT-9
  2561. 067A DEC DE Balance the 'INC' above.
  2562. 067B LD HL,+0008 Is drive number within range 1..8?
  2563. 067E SBC HL,DE
  2564. 0680 RET NC Return if in range.
  2565.  
  2566. 'Invalid drive number'
  2567.  
  2568. 0681 NREPORT-5 RST 20,SH-ERR Call the error handling
  2569. 0682 DEFB +04 routine.
  2570.  
  2571. 'Missing drive number'
  2572.  
  2573. 0683 NREPORT-9 RST 20,SH-ERR Call the error handling
  2574. 0684 DEFB +08 routine.
  2575.  
  2576. THE 'CHECK "M" PARAMETERS AND FILENAME' SUBROUTINE
  2577. This subroutine adds to the tests performed by the previous one, also a check to N-STR1-hi, that holds +FF when no \
  2578. filename has been evaluated.
  2579.  
  2580. 0685 TEST-MNAM CALL 0665,CHECK-M Check "m" parameters.
  2581. 0688 LD A,(N-STR1-hi) Fetch high byte of name length.
  2582. 068B AND A Is it 0?
  2583. 068C RET Z Return if so.
  2584.  
  2585. 'Missing name'
  2586.  
  2587. 068D RST 20,SH-ERR Call the error handling
  2588. 068E DEFB +06 routine.
  2589.  
  2590. THE 'CHECK STATION NUMBER' SUBROUTINE
  2591. A return to the calling routine is made only if D-STR1 holds a valid station number in the range 0..64.
  2592.  
  2593. 068F TEST-STAT LD DE,(D-STR1) Fetch station number.
  2594. 0693 INC DE Test against +FFFF.
  2595. 0694 LD A,E
  2596. 0695 OR D No station number has been
  2597. 0696 JR Z,06A1,NREPORT-8 evaluated, so give an error
  2598. 0698 DEC DE Balance the 'INC' above.
  2599. 0699 LD HL,+0040 Return only if the value is no
  2600. 069C SBC HL,DE greater than 64 decimal.
  2601. 069E RET NC
  2602.  
  2603. 'Invalid station number'
  2604.  
  2605. 069F RST 20,SH-ERR Call the error handling
  2606. 06A0 DEFB +05 routine.
  2607.  
  2608. 'Missing station number'
  2609.  
  2610. 06A1 NREPORT-8 RST 20,SH-ERR Call the error handling
  2611. 06A2 DEFB +07 routine.
  2612.  
  2613. THE 'EVALUATE "X";N;"NAME"' SUBROUTINE
  2614. A call to the subroutine EXPT-SPEC will evaluate the '"X";N', while the subroutine EXPT-NAME is used to evaluate the \
  2615. filename. A separator must be found between them.
  2616.  
  2617. 06A3 EXPT-EXPR CALL 05F2,EXPT-SPEC Evaluate channel specifier and drive
  2618. number.
  2619. 06A6 CALL 05B1,SEPARATOR A separator must be present.
  2620. 06A9 JP NZ,04B2,OREPORT-1
  2621. 06AC CALL 062F,EXPT-NAME Evaluate the filename.
  2622. 06AF RET Finished.
  2623.  
  2624. THE 'CHECK BAUD RATE' SUBROUTINE
  2625. 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 \
  2626. accepted (but later rounded to the nearest 'standard' value).
  2627.  
  2628. 06B0 TEST-BAUD LD HL,(D-STR1) Fetch baud rate.
  2629. 06B3 INC HL Accept any value except +FFFF.
  2630. 06B4 LD A,L
  2631. 06B5 OR H
  2632. 06B6 RET NZ
  2633.  
  2634. 'Missing baud rate'
  2635.  
  2636. 06B7 RST 20,SH-ERR Call the error handling
  2637. 06B8 DEFB +09 routine.
  2638.  
  2639. THE 'EVALUATE STREAM OR EXPRESSION' SUBROUTINE
  2640. This subroutine is used to deck the syntax of the MOVE Command. If the 'current' character is a hash sign (#), then a \
  2641. stream number is evaluated and stored into S-STR1 during runtime. Otherwise a channel expression like '"x";n ["name"]' \
  2642. is evaluated, and N-STR1, D-STR1 and L-STR1 are set as required and, if the channel specifier is "M" or "N", the \
  2643. parameters are checked to be in range.
  2644.  
  2645. 06B9 EXPT-EXP1 RST 10,CALBAS Advance CH-ADD.
  2646. 06BA DEFW +0020
  2647. 06BC CP +23 Is the present code an hash sign?
  2648. 06BE JP Z,064E,EXPT-STRM Evaluate stream number if so,
  2649. 06C1 CALL 05F5,EXP-SPEC2 otherwise evaluate "x";n.
  2650. 06C4 CALL 05B1,SEPARATOR Jump if there is no further
  2651. 06C7 JR NZ,06CC,ENDHERE separator.
  2652. 06C9 CALL 062F,EXPT-NAME Otherwise deal with "filename".
  2653. 06CC ENDHERE RST 18,CHKSYNTAX Return if syntax is being checked.
  2654. 06CD RET Z
  2655. 06CE LD A,(LSTR-1) Fetch channel specifier.
  2656. 06D1 CP +54 Return if It is "T".
  2657. 06D3 RET Z
  2658. 06D4 CP +42 Return if it is "B".
  2659. 06D6 RET Z
  2660. 06D7 CP +4E But check station no. if it is "N".
  2661. 06D9 JP Z,068F,TEST-STAT
  2662. 06DC JP 0685,TEST-MNAM Otherwise check "m" parameters.
  2663.  
  2664. 06DF...06FF Unused locations (all set to .FF).
  2665.  
  2666. THE 'UNPAGE' SUBROUTINE
  2667. This subroutine is actually made by a single RET instruction, but the hardware detects that the Program Counter \
  2668. reaches the address +0700 and pages-in the 'main' ROM.
  2669.  
  2670. 0700 UNPAGE RET RETurn to 'main' ROM.
  2671.  
  2672. THE 'EVALUATE PARAMETERS' SUBROUTINE
  2673. This very important subroutine is called to evaluate the syntax of the SAVE, LOAD, VERIFY and MERGE commands referred \
  2674. to the 'new' channels. The subroutine is entered with CH-ADD pointing to the command code; on exit during runtime the \
  2675. variables D-STR1, L-STR1, N-STR1, HD-00, HD-0B, HD-0D, HD-0F, HD-11 are properly set.
  2676.  
  2677. 0701 EXPT-PRMS RST 10,CALBAS The next character is fetched from
  2678. 0702 DEFW +0020 the line.
  2679. 0704 CP +2A It must be a '*'.
  2680. 0706 JR NZ,073C,OREP-1-2 Give an error if not a '*'.
  2681. 0708 RST 10,CALBAS Advance CH-ADD past the '*'.
  2682. 0709 DEFW +0020
  2683. 070B CALL 05F5,EXP-SPEC2 Evaluate "x";n.
  2684. 070E CALL 05B1,SEPARATOR Check that the separator dDEs exist.
  2685. 0711 JR NZ,0716,NO-NAME Jump if no name is to be expected.
  2686. 0713 CALL 062F,EXPT-NAME Evaluate "filename".
  2687. 0716 NO-NAME PUSH AF The next character is saved.
  2688. 0717 LD A,(L-STR1) Fetch channel specifier.
  2689. 071A CP +4E Jump if the channel is not "N",
  2690. 071C JR NZ,0122,NOT-NET
  2691. 071E SET 3,(FLAGS3) otherwise signal "networking".
  2692. 0722 NOT-NET POP AF Restore 'next character'.
  2693. 0723 CP +0D Jump if the statement ends with
  2694. 0725 JR Z,0750,END-EXPT ENTER, or
  2695. 0727 CP +3A with a colon.
  2696. 0729 JR Z,0750,END-EXPT
  2697. 072B CP +AA Jump if the statement continues with
  2698. 072D JR Z,0771,SCREEN$ SCREEN$.
  2699. 072F CP +AF Jump with CODE.
  2700. 0731 JR Z,0789,CODE
  2701. 0733 CP +CA Jump with LINE.
  2702. 0735 JR Z,973E,LINE
  2703. 0737 CP +E4 Jump with DATA, otherwise give
  2704. 0739 JP Z,07D2,DATA an error report.
  2705.  
  2706. 'Nonsense in BASIC'
  2707.  
  2708. 073C OREP-1-2 RST 20,SH-ERR Call the error handling
  2709. 073D DEFB +00 routine.
  2710.  
  2711. Now deal with LINE.
  2712.  
  2713. 073E LINE RST 10,CALBAS Advance CH-ADD.
  2714. 073F DEFW +0020
  2715. 0741 RST 10,CALBAS Call EXPT-1NUM to evaluate the
  2716. 0742 DEFW +1C82 autostart line number.
  2717. 0744 CALL 05B7,ST-END Confirm end of statement, and exit
  2718. during syntax checking.
  2719. 0747 RST 10,CALBAS Fetch the autostart line number from
  2720. 0748 DEFW +1E99 the calculator stack.
  2721. 074A LD (HD-11),BC Store autostart line number.
  2722. 074E JR 0753,PROG Jump forward.
  2723.  
  2724. If there are no parameters (i.e. BASIC program), the syntax checking ends here.
  2725.  
  2726. 0750 END-EXPT CALL 05B7,ST-END Confirm end of statement and exit
  2727. during syntax checking.
  2728. 0753 PROG XOR A Store 0 into HD-00 (signalling
  2729. 0754 LD (HD-00),A 'program' file type).
  2730. 0757 LD HL,(E-LINE) Address past the last location of
  2731. variables area.
  2732. 075A LD DE,(PROG) The 'start' of data is fetched
  2733. 075E LD (HD-0D),DE from PROG, and stored into HD-0D.
  2734. 0762 SCF This calculates
  2735. 0763 SBC HL,DE ((E-LINE)-(PROG))-1, i.e. the length
  2736. of the program and its variables.
  2737. 0765 LD (HD-0B),HL The 'length' is stored.
  2738. 0768 LD HL,(VARS) Now calculate (VARS)-(PROG),
  2739. 076B SBC HL,DE i.e. the length of the program only.
  2740. 076D LD (HD-0F),HL Store it into HD-0F.
  2741. 0770 RET Finished.
  2742.  
  2743. If the token is SCREEN$, the parameters are entered directly into the system variables.
  2744.  
  2745. 0771 SCREEN$ RST 10,CALBAS Advance CH-ADD.
  2746. 0772 DEFW +0020
  2747. 0774 CALL 05B7,ST-END Confirm end of statement and exit
  2748. during syntax checking.
  2749. 0777 LD HL,+1B00 The 'length' of the display file
  2750. 077A LD (HD-0B),HL and attributes is stored.
  2751. 077D LD HL,+4000 The start address of the display
  2752. 0780 LD (HD-0D),HL file.
  2753. 0783 LD A,+03 Signal 'bytes' file type.
  2754. 0785 LD (HD-00),A
  2755. 0788 RET Finished.
  2756.  
  2757. Now deal with CODE.
  2758.  
  2759. 0789 CODE RST 10,CALBAS Advance CH-ADD.
  2760. 078A DEFW +0020
  2761. 078C CP +0D If there ate no further parameters,
  2762. 078E JR Z,079A,DEFLT-0 jump to use '0' as default value.
  2763. 0790 CP +3A Jump it there are parameters to be
  2764. 0792 JR NZ,PAR-1 evaluated (i.e. the next character
  2765. is not a colon).
  2766. 0794 BIT 5,(FLAGS3) Give an error if SAVE "name"CODE is
  2767. 0798 JR NZ,OREP-1-2 encountered by itself
  2768. 079A DEFLT-0 RST 10,CALBAS A call to main ROM routine 'USE-ZERO'
  2769. 079B DEFW +1CE6 is made to use a value of zero as
  2770. default
  2771. 079D JR 07A7,TEST-SAVE Jump forward.
  2772. 079F PAR-1 RST 10,CALBAS Otherwise call EXPT-1NUM to use the
  2773. 07A0 DEFW +1C82 specified value.
  2774. 07A2 CALL 0581,SEPARATOR Jump if a separator is present.
  2775. 07A5 JR Z,0782,PAR-2
  2776. 07A7 TEST-SAVE BIT 5,(FLAGS3) Give an error if a parameter has been
  2777. 07AB JR NZ,073C,OREP-l-2 missed in a SAVE name CODE command.
  2778. 07AD RST 10,CALBAS Use zero also for the 2nd parameter,
  2779. 07AE DEFW +1CE6
  2780. 07B0 JR 07B8,END-CODE Jump forward.
  2781. 07B2 PAR-2 RST 10,CALBAS Advance CH-ADD.
  2782. 07B3 DEFW +0020
  2783. 07B5 RST 10,CALBAS Evaluate the 2nd parameter by calling
  2784. 07B6 DEFW +1CB2 EXPT-1NUM.
  2785. 07B8 END-CODE RST 10,CALBAS Call GET-CHAR to fetch the 'last'
  2786. 07B9 DEFW +0018 character in the statement.
  2787. 07BB CALL 05B7,ST-END Confirm end of statement and exit if
  2788. syntax is being checked.
  2789. 07BE RST 10,CALBAS Fetch the "length" from the
  2790. 07BF DEFW +1E99 calculator stack and
  2791. 07C1 LD (HD-0B),BC store it.
  2792. 07C5 RST 10,CALBAS Fetch the "start" from the calculator
  2793. 07C6 DEFW +1E99 stack and store it.
  2794. 07C8 LD (HD-0D),BC
  2795. 07CC LD A,+03 Signal 'bytes' file type.
  2796. 07CE LD (HD-00),A
  2797. 07D1 RET Finished.
  2798.  
  2799. Finally the routine to evaluate DATA parameters.
  2800.  
  2801. 07D2 DATA BIT 6,(FLAGS3) Jump unless attempting to MERGE
  2802. 07D6 JR Z,07DA,NO-M-ARR an array.
  2803.  
  2804. 'MERGE error'
  2805.  
  2806. 07D8 RST 20,SH-ERR Call the error handling
  2807. 07D9 DEFB +14 routine.
  2808.  
  2809. 07DA NO-M-ARR RST 10,CALBAS Advance CH-ADD to point to
  2810. 07DB DEFW +0020 the array name.
  2811. 07DD RST 10,CALBAS Call LOOK-VARS to look for the
  2812. 07DE DEFW +28B2 array name.
  2813. 07E0 SET 7,C Set bit 7 of array name.
  2814. 07E2 JR NC,07F2,EXISTING Jump if handling an existing array.
  2815. 07E4 LD HL,+0000 Signal 'using a new array'.
  2816. 07E7 BIT 4,(FLAGS3) Jump forward if LOADing the array.
  2817. 07EB JR NZ,080E,LD-DATA
  2818. 07ED LD (ERR-NR),+01 Give the error report 'Variable not
  2819. 07F1 RST 28,ROMERR found' if trying to SAVE a
  2820. nonexistent array.
  2821. 07F2 EXISTING JR Z,07F6,G-TYPE Continue only when handling a numeric
  2822. or alphanumeric array,
  2823.  
  2824. NOTE: This test fails to exclude simple strings, but the 'bug' (present in the main ROM) is corrected at 07FF.
  2825.  
  2826. 07F4 NONS-BSC RST 20,SH-ERR 'Nonsense in BASIC'
  2827. 07F5 DEFB +00
  2828.  
  2829. 07F6 G-TYPE RST 18,CHKSYNTAX Jump forward if syntax is
  2830. 07F7 JR Z,081C,END-DATA being checked.
  2831. 07F9 BIT 5,(FLAGS3) Jump forward if not during a SAVE
  2832. 07FD JR Z,0803,VR-DATA command.
  2833. 07FF BIT 7,(HL) Give an error if trying to SAVE
  2834. 0801 JR Z,07F4,NONS-BSC a simple string.
  2835. 0803 VR-DATA INC HL Point to the 'length' of the array.
  2836. 0804 LD A,(HL) Fetch low byte.
  2837. 0805 LD (HD-0B-lo),A Store it.
  2838. 0808 INC HL Point to high byte of 'length'.
  2839. 0809 LD A,(HL) Fetch high byte.
  2840. 080A LD (HD-0B-hi),A Store it.
  2841. 080D INC HL Advance to the start of the
  2842. array.
  2843. 080E LD-DATA LD A,C Store array name into HD-0F.
  2844. 080F LD (HD-0F-lo),A
  2845. 0812 LD A,+01 Signal 'numeric array'.
  2846. 0814 BIT 6,C Jump if really a numeric array.
  2847. 0816 JR Z,0819,NUM-ARR
  2848. 0818 INC A Otherwise A=2 to signal
  2849. 'alphanumeric array'.
  2850. 0819 NUM-ARR LD (HD-00),A Store file type.
  2851. 081C END-DATA EX DE,HL DE holds the 'start' of the array
  2852. (or +0000 with 'NEW' array to be
  2853. loaded).
  2854. 081D RST 10,CALBAS Advance CH-ADD.
  2855. 081E DEFW +0020
  2856. 0820 CP +29 Check that the ')' dDEs exist.
  2857. 0822 JR NZ,07F4,NONS-BSC Report an error if not.
  2858. 0824 RST 10,CALBAS Advance CH-ADD.
  2859. 0825 DEFW +0020
  2860. 0827 CALL 05B7,ST-END Confirm end of statement and exit
  2861. during syntax checking.
  2862. 082A LD (HD-0D),DE Store "start" of the array.
  2863. 082E RET Finished.
  2864.  
  2865. THE 'SAVE' COMMAND SYNTAX ROUTINE
  2866. The actual saving is handled directly with "B" and "N" channels, or by SAVE-RUN if the 'N" channel is being used.
  2867.  
  2868. 082F SAVE-SYN SET 5,(FLAGS3) Signal "Saving".
  2869. 0833 CALL 0701,EXPT-PRMS Check syntax and set variables.
  2870. 0836 LD A,(L-STR1) Fetch channel specifier.
  2871. 0839 CP +42 Jump with "B" channel being used.
  2872. 083B JR Z,084F,SA-HEADER
  2873. 083D CP +4E Jump with other than "N" channel
  2874. 083F JR NZ,0849,SAVE-M being used (i.e. with "M" channel).
  2875. 0841 CALL 068F,TEST-STAT Check station number.
  2876. 0844 CALL 0EA9,OP-TEMP-N Open a temporary "N" channel.
  2877. 0847 JR 084F,SA-HEADER Jump forward.
  2878. 0849 SAVE-M CALL 0685,TEST-MNAM Check "M" parameters.
  2879. JP 1E7F,SAVE-RUN Jump forward.
  2880.  
  2881. Now a loop is entered to SAVE to the "N" or "B" devices the 'header', i.e. the nine bytes taken from the system \
  2882. variables HD-00 to HD-11.
  2883.  
  2884. 084F SA-HEADER LD B,+09 Nine bytes are to be saved.
  2885. 0851 LD HL,+5CE6 Start of HD variables.
  2886. 0854 HD-LOOP CALL 0880,SA-BYTE Save the byte pointed by HL.
  2887. 0857 INC HL Each header byte in turn is saved.
  2888. 0858 DJNZ 0854,HD-LOOP
  2889. 085A LD HL,(HD-0D) Fetch 'start of data block'.
  2890. 085D BIT 3,(FLAGS3) Jump if "B" channel is being used.
  2891. 0861 JR Z,086E,SA-BLOCK
  2892. 0863 LD A,(HD-00) Jump also if saving a block of memory
  2893. 0866 CP +03 (i.e. SAVE..CODE).
  2894. 0868 JR NC,086E,SA-BLOCK
  2895. 086A LD DE,+0014 Otherwise the data to be saved have
  2896. 086D ADD HL,DE been moved up by '276' bytes after
  2897. the insertion of the "N" channel.
  2898. 086E SABLOCK LD BC,(HD-0B) Fetch the 'length' of the block.
  2899. 0872 SA-BLK-LP LD A,C Jump forward when the counter has
  2900. 0873 OR B reached zero.
  2901. 0874 JR Z,087D,S-BLK-END
  2902. 0876 CALL 0880,SA-BYTE Send the byte pointed by HL.
  2903. 0879 DEC BC Decrement 'length'.
  2904. 087A INC HL Point to next byte.
  2905. 087B JR 0872,SA-BLK-LP Jump back until the whole block has
  2906. been saved.
  2907. 087D S-BLK-END JP 0988,TST-MR-M Jump forward to send the 'end of
  2908. file' block (only with Network).
  2909.  
  2910.  
  2911. THE 'SAVE A BYTE TO NETWORK OR RS232 LINK' SUBROUTINE
  2912. The byte pointed by the HL register pair is fetched and sent by using the "B" or the "N" channel output routing, \
  2913. depending upon the state of bit 3 of the FLAGS3 variable.
  2914.  
  2915. 0880 SA-BYTE PUSH HL Save HL and BC register pairs.
  2916. 0881 PUSH BC
  2917. 0882 BIT 3,(FLAGS3) Test 'networking' bit.
  2918. 0886 LD A,(HL) Fetch the byte to be saved.
  2919. 0887 JR NZ,088E,SA-NET Jump if network is being used.
  2920. 0889 CALL 0C5A,BCHAN-OUT Otherwise send the byte through the
  2921. RS232 link.
  2922. 088C JR 0891,SA-B-END Exit.
  2923. 088E SA-NET CALL 0D6C,NCHAN-OUT Use "N" channel output routine to
  2924. send the byte.
  2925. 0891 SA-B-END POP BC Restore registers and return.
  2926. 0892 POP HL
  2927. 0893 RET
  2928.  
  2929. TUE 'LOAD' COMMAND SYNTAX ROUTINE
  2930. The syntax is checked with a single call to the EXPT-PRMS subroutine.
  2931.  
  2932. 0894 LOAD-SYN SET 4,(FLAGS3) Signal 'doing a LOAD command'.
  2933. 0898 CALL 0701,EXPT-PRMS Check syntax and set variables.
  2934. 089B JP 08AF,LD-VF-MR Do the LOAD.
  2935.  
  2936. THE 'VERIFY' COMMAND SYNTAX ROUTINE
  2937. Again the syntax checking is handled by EXPT-PRMS.
  2938.  
  2939. 089E VERIF-SYN SET 7,(FLAGS3) Signal 'doing a VERIFY command'.
  2940. 08A2 CALL 0701,EXPT-PRMS Check syntax and set variables.
  2941. 08A5 JP O8AF,LD-VF-MR Do the VERIFY.
  2942.  
  2943. THE 'MERGE' COMMAND SYNTAX ROUTINE
  2944. The syntax is handled by EXFT-PRMS the routine continues into the LOAD-VERIFY-MERGE routine below.
  2945.  
  2946. 08A8 MRG-SYN SET 6,(FLAGS3) Signal 'doing a MERGE command'.
  2947. 08AC CALL 0701,EXPT-PRMS Check syntax and set variables.
  2948.  
  2949. THE "LOAD-VERIFY-MERGE' COMMANDS ROUTINE
  2950. 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 \
  2951. area, and is immediately transferred into the D-STR2 area, while the 'new' header is loaded into the HD area.
  2952.  
  2953. 08AF LD-VF-MR LD HL,+5CE6 Start of HD area.
  2954. 08B2 LD DE,+5CDE Start of D-STR2 area.
  2955. 08B5 LD BC,+0007 There are '7' bytes to be copied
  2956. (HD-11 is not affected).
  2957. 08B8 LDIR Copy the 'old' header into the D-STR2
  2958. area.
  2959. 08BA LD A,(L-STR1) Fetch channel specifier.
  2960. 08BD CP +4E Jump if network is being used.
  2961. 08BF JR Z,08CD,TS-L-NET
  2962. 08C1 CP +42 Jump if RS232 link is being used.
  2963. 08C3 JR Z,08D3,TS-L-RS
  2964. 08C5 CALL 0685,TEST-MNAM Check "M" parameters.
  2965. 08C8 CALL 1580,F-M-HEAD Fetch first nine bytes from cartridge
  2966. and store into HD area.
  2967. 08CB JR 08F2,TEST-TYPE Jump forward.
  2968. 08CD TS-L-NET CALL 068F,TEST-STAT Check station number.
  2969. 08D0 CALL 0EA9,OP-TEMP-N Open a temporary "N" channel.
  2970. 08D3 TS-L-RS LD HL,+5CE6 Start of HD area.
  2971. 08D6 LD B,+09 Nine bytes are now expected.
  2972. 08D8 LD-HEADER PUSH HL Save HL and BC register pairs.
  2973. 08D9 PUSH BC
  2974. 08DA BIT 3,(FLAGS3) Jump if using RS232 link.
  2975. 08DD JR Z,08E7,LD-HD-RS
  2976. 08E0 LD-HD-NET CALL 0D12,NCHAN-IN Fetch a byte from "N" channel.
  2977. 08E3 JR NC,08E0,LD-HD-NET Repeat until the byte is acceptable.
  2978. 08E5 JR 08EC,LD-HDR-2 Jump forward.
  2979. 08E7 LD-HD-RS CALL 0B81,BCHAN-IN Fetch a byte from RS232 link.
  2980. 08EA JR NC,08E7,LD-HD-RS Repeat until the byte is acceptable.
  2981. 08EC LD-HDR-2 POP BC Restore registers.
  2982. 08ED POP HL
  2983. 08EE LD (HL),A Store the byte into the HO area.
  2984. 08EF INC HL Advance the pointer.
  2985. 08F0 DJNZ 08D8,LD-HEADER Go around the loop again.
  2986. 08F2 TEST-TYPE LD A,(5CDE) Fetch 'old' type from D-STR2
  2987. 08F5 LD B,A area and store into B register.
  2988. 08F6 LD A,(HD-00) Fetch 'new' file type.
  2989. 08F9 CP B Compare with the 'old' one.
  2990. 08FA JR NZ,0902,NREPORT-N Give an error if it does not match.
  2991. 08FC CP +03 Jump if handling a block of bytes.
  2992. 08FE JR Z,0911,T-H-CODE
  2993. 0900 JR C,0904,TST-MERGE Jump with other types (but refuse
  2994. types greater than 3).
  2995.  
  2996. 'Wrong file type'
  2997.  
  2998. 0902 NREPORT-N RST 20,SH-ERR Call the error handling
  2999. 0903 DEFB +16 routine.
  3000.  
  3001. 0904 TST-MERGE BIT 6,(FLAGS3) Jump if doing a MERGE.
  3002. 0908 JR NZ,0967,MERGE-BLK
  3003. 090A BIT 7,(FLAGS3) Jump if not doing a VERIFY (i.e.
  3004. 090E JP Z,09A3,LD-PR-AR doing a LOAD).
  3005.  
  3006. Now deal with loading of files of type 3 (i.e. CODE and SCREENS), or verifying of all file types.
  3007.  
  3008. 0911 T-M-CODE BIT 6,(FLAGS3) Allow for the loading or
  3009. 0915 JR Z,0919,LD-BLOCK verifying, but not for the mergeing
  3010. of a 'CODE' block.
  3011. 'MERGE error'
  3012.  
  3013. 0917 RST 20,SH-ERR Call the error handling
  3014. 0918 DEFB +14 routine.
  3015.  
  3016. 0919 LD-BLOCK LD HL,(+5CDF) Get 'old' length from D-STR2.
  3017. 091C LD DE,(HD-0B) Get 'new' length.
  3018. 0920 LD A,H Jump forward if 'old' length is 0
  3019. 0921 OR L (i.e. not specified in the command).
  3020. 0922 JR Z,0932,LD-BLK-2
  3021. 0924 SBC HL,DE Accept the 'old' length if it is
  3022. 0926 JR NC,0932,LD-BLK-2 greater than or equal to the
  3023. 'new' one.
  3024. 0928 BIT 4,(FLAGS3) But give an error if attempting
  3025. 092C JR Z,0930,NREPORT-L to LOAD or VERIFY a larger block
  3026. than has been requested.
  3027. 'CODE error'
  3028.  
  3029. 092E RST 20,SH-ERR Call the error handling
  3030. 092F DEFB +13 routine.
  3031.  
  3032. 'Verification has failed'
  3033.  
  3034. 0930 NREPORT-L RST 20,SH-ERR Call the error handling
  3035. 0931 DEFB +15 routine.
  3036.  
  3037. 0932 LD-BLK-2 LD HL,(5CE1) Get 'old' start from D-STR2.
  3038. 0935 LD A,(IX+4) Fetch specifier from the channel area.
  3039. 0938 CP +CD Jump if not "M"+80, i.e. not a
  3040. 093A JR NZ,0941,LD-BLK1 temporary "M" channel.
  3041. 093C LD HL,(5CE4) But if the "M" channel is being
  3042. used, the 'start' has been stored
  3043. into +5CE4 (see +1583).
  3044. 093F JR 0952,LD-BLK4 Jump forward.
  3045. 0941 LD-BLK-3 BIT 3,(FLAGS3) Jump if not using the network.
  3046. 0945 JR Z,0952,LD-BLK-4
  3047. 0947 LD A,(HD-00) Jump if it is a block of bytes.
  3048. 094A CP +03
  3049. 094C JR Z,0952,LD-BLK-4
  3050. 094E LD BC,+01l4 Otherwise the data has been moved
  3051. 0951 ADD HL,BC up by '276' bytes after the
  3052. insertion of the "N" channel.
  3053. 0952 LD-BLK-4 LD A,H Use 'old' start if it has been
  3054. 0953 OR L specified in the command,
  3055. 0954 JR NZ,0959,LD-BLK-5 otherwise use 'new' start.
  3056. 0956 LD HL,(HD-0D)
  3057. 0959 LD-BLK-5 LD A,(HD-00) Use the 'start' in HL for types
  3058. 095C AND A other than 'program'.
  3059. 095D JR NZ,0962,LD~NO-PGM
  3060. 095F LD HL,(PROG) But with 'program' type, the 'start'
  3061. is pointed by PROG.
  3062. 0962 LD-NO-PGM CALL 0A5C,LV-ANY Do the actual LOADing or VERIFYing.
  3063. 0965 JR 0988,TST-MR-M Jump forward to close the channel
  3064. used.
  3065.  
  3066. Now consider the MERGEing of a program.
  3067.  
  3068. 0967 MERGE-BLK LD A,(HD-11-hi) Continue only if the content of
  3069. 096A AND +C0 HD-11 is sufficiently high, i.e. if
  3070. 096C JR NZ,0973,NO-AUTOST the program was not saved with
  3071. 'autostart'
  3072. 096E CALL 17B9,RCL-T-CH Otherwise reclaim channels and give
  3073. 0971 RST 20,SH-ERR a 'MERGE error'.
  3074. 0972 DEFB +14
  3075. 0973 NO-AUTOST LD BC,(HD-0B) Fetch 'length' of program to be
  3076. 0977 PUSH BC merged and save it.
  3077. 0978 INC BC Allows for a further location to
  3078. insert the 'end marker'.
  3079. 0979 RST 10,CALBAS Call BC-SPACES to make the
  3080. 097A DEFW +0030 required room in workspace.
  3081. 097C LD (HL),+80 Mark the end of the space.
  3082. 097E EX DE,HL HL now points to the start of the
  3083. space created.
  3084. 097F POP DE Restore length of program.
  3085. 0980 PUSH HL Save 'start' pointer.
  3086. 0981 CALL 0A5C,LV-ANY Load the program in the workspace.
  3087. 0984 POP HL Restore 'start' pointer.
  3088. 0985 RST 10,CALBAS Do the mergeing with the existing
  3089. 0986 DEFW +08CE program by entering into the main
  3090. ROM 'MERGE' control routine.
  3091. 0988 TST-MR-M LD A,(IX+4) Jump if the specifier is not "M"+80
  3092. 098B CP +CD i.e. if other than "M" channel has
  3093. 098D JR NZ,0994,TST-MR-N been used.
  3094. 098F CALL 12A9,CLOSE-M2 Close the "M" channel.
  3095. 0992 JR 09A0,MERGE-END Jump forward.
  3096. 0994 TST-MR-N BIT 3,(FLAGS3) Exit immediately if the "B" output
  3097. 0998 JR Z,09A0,MERGE-END has been used.
  3098. 099A CALL 0EF5,SEND-NEOF Why?
  3099. 099D CALL 17B9,RCL-T-CH Reclaim the channel.
  3100. 09A0 MERGE-END JP 05C1,END1 Finished.
  3101.  
  3102. The final branch of the routine deals with the LOADIng of a program or an array.
  3103.  
  3104. 09A3 LD-PR-AR LD DE,(HD-0B) Fetch 'new' length.
  3105. 09A7 LD HL,(5CE1) Fetch 'old' start (set to 0 when
  3106. loading a 'new' array).
  3107. 09AA PUSH HL Save it temporarily.
  3108. 09AB LD A,H Jump if not a 'new' array.
  3109. 09AC OR L
  3110. 09AD JR NZ,09B5,LD-PROG
  3111. 09AF INC DE Increment 'length' by 3, i.e. allows
  3112. 09B0 INC DE for the insertion of array name and
  3113. 09B1 INC DE two-byte length.
  3114. 09B2 EX DE,HL Move 'length' into HL.
  3115. 09B4 JR 09BE,TST-SPACE Jump forward.
  3116. 09B5 LD-PROG LD HL,(5CDF) Fetch 'old' length (i.e. length of
  3117. existing program or array) from
  3118. D-STR2 area.
  3119. 09B8 EX DE,HL HL holds the 'new' length.
  3120. 09B9 SCF Jump forward if the program (or
  3121. 09BA SBC HL,DE array) being loaded is no longer
  3122. 09BC JR C,09C7,TST-TYPE than the existing one.
  3123. 09BE TST-SPACE LD DE,+0005 Otherwise a check must be made to
  3124. 09C1 ADD HL,DE ensure that there is sufficient space
  3125. 09C2 LD B,H in memory for the program (or array)
  3126. 09C3 LD C,L to be loaded, with a call to main ROM
  3127. 09C4 RST 10,CALBAS 'TEST-ROOM' subroutine.
  3128. 09C5 DEFW +1F05
  3129. 09C7 TST-TYPE POP HL Restore 'old' start (+0000 when
  3130. handling a 'new' array).
  3131. 09C8 LD A,(HD-00) Jump if 'type' indicates a
  3132. 09CB AND A BASIC program (+00).
  3133. 09CC JR Z,0A15,SET-PROG
  3134. 09CE LD A,H Jump unless an 'old' array is to be
  3135. 09CF OR L erased before
  3136. 09D0 JR Z,09F3,CRT-NEW loading the 'new' one.
  3137. 09D2 LD A,(IX+4) If the channel specifier denotes
  3138. 09D5 CP +CD other than temporary "M" channels
  3139. 09D7 JR NZ,09DE,T-LD-NET (i.e. "M"+80H), the 'start' is
  3140. already held in HL.
  3141. 09D9 LD HL,(5CE4) Otherwise the start address of the
  3142. array is fetched from D-STR2 area.
  3143. 09DC JR 09E8,RCLM-OLD
  3144. 09DE T-LD-NET BIT 3,(FLAGS3) Jump if using the 515232 link.
  3145. 09E2 JR Z,09E8,RCLM-OLD
  3146. 09E4 LD DE,+0114 Otherwise the array has been moved
  3147. 09E7 ADD HL,DE '276' bytes up after the insertion
  3148. of "N" channel.
  3149. 09E8 RCLM-OLD DEC HL Points to the high byte of 'array
  3150. length'.
  3151. 09E9 LD B,(HL) Fetch high byte.
  3152. 09EA DEC HL Points to the low byte.
  3153. 09EB LD C,(HL) Fetch low byte.
  3154. 09EC DEC HL Points to the array name.
  3155. 09ED INC BC Include 'length' and 'name' in the
  3156. 09EE INC BC array length.
  3157. 09EF INC BC
  3158. 09F0 RST 10,CALBAS Call RECLAIM-2 to delete the array.
  3159. 09F1 DEFW +19E8
  3160. 09F3 CRT-NEW LD HL,(E-LINE) Points to the end of variables area.
  3161. 09F6 DEC HL
  3162. 09F7 LD BC,(HD-0B) Fetch the length of the array to be
  3163. loaded.
  3164. 09FB PUSH BC Save it.
  3165. 09FC INC BC Include in the length one byte for
  3166. 09FD INC BC array name and two for 'length of
  3167. 09FE INC BC array
  3168. 09FF LD A,(5CE3) Fetch array name from D-STR2 area.
  3169. 0A02 PUSH AF Save it briefly.
  3170. 0A03 RST 10,CALBAS Call MAKE-ROOM to create the space
  3171. 0A04 DEFW +1655 for the array.
  3172. 0A06 INC HL Points to the first 'new' location
  3173. inserted.
  3174. 0A07 POP AF Restore array name and store into
  3175. 0A08 LD (HL),A the 1st location.
  3176. 0A09 POP DE Fetch 'array length'.
  3177. 0A0A INC HL Store it into the following two
  3178. 0A0B LD (HL),E locations.
  3179. 0A0C INC HL
  3180. 0A0D LD (HL),D
  3181. 0A0E INC HL The array will be loaded from this
  3182. location.
  3183. 0A0F END-LD-PR CALL 0A5C,LV-ANY Load array or BASIC program.
  3184. 0A12 JP 0988,TST-MR-M Jump back to close the channel.
  3185.  
  3186. If the file loaded is a program, the space required is to be crested and some actions to be performed.
  3187.  
  3188. 0A15 SET-PROG RES 1,(FLAGS3) Signal 'no autostart'
  3189. 0A19 LD DE,(PROG) Fetch start of existing program.
  3190. 0A1D LD HL,(E-LINE) Fetch end of existing program.
  3191. 0A20 DEC HL
  3192. 0A21 RST 10,CALBAS Call RECLAIM-1 in the main ROM to
  3193. 0A22 DEFW +19E5 delete the program.
  3194. 0A24 LD BC,(HD-0B) Fetch length of program and variables.
  3195. 0A28 LD HL,(PROG) Fetch start address of program.
  3196. 0A2B RST 10,CALBAS Call MAKE-ROOM to create the
  3197. 0A2C DEFW +1655 required space.
  3198. 0A2E INC HL Points to the first location.
  3199. 0A2F LD BC,(HD-0F) Fetch program length.
  3200. 0A33 ADD HL,BC Calculate and store the start of
  3201. 0A34 LD (VARS),HL variables area.
  3202. 0A37 LD A,(HD-11-hi) This is set to +FF when no autostart
  3203. 0A3A LD H,A is required.
  3204. 0A3B AND +C0
  3205. 0A3D JR NZ,0A4E,NO-AUTO Jump with 'no autostart'.
  3206. 0A3F SET 1,(FLAGS3) Signal 'autostart' (see +0049).
  3207. 0A43 LD A,(HD-11-lo) Fetch low byte of autostart line
  3208. 0A46 LD L,A number.
  3209. 0A47 LD (NEWPPC),HL Store autostart line no.
  3210. 0A4A LD (NSPPC),+00 Clear NSPPC to signal 'jump'.
  3211. 0A4E NO-AUTO LD HL,(PROG) Fetch start address of program area.
  3212. 0A51 LD DE,(HD-0B) Fetch program length.
  3213. 0A55 DEC HL Make DATADD point to the last byte
  3214. 0A56 LD (DATADD),HL of the CHANS area.
  3215. 0A59 INC HL Balance the DEC above.
  3216. 0A5A JR 0A0F,END-LD-PR Jump back to LOAD the new program.
  3217.  
  3218. THE 'LOAD OR VERIFY' SUBROUTINE
  3219. This subroutine is used to LOAD or VERIFY (depending upon the state of bit 7 of FLAGS3 system variable) a block of \
  3220. bytes. It must be entered with the 'start' and the 'length' in the HL and DE register pairs, and with all system \
  3221. variables properly set.
  3222.  
  3223. 0A5C LV-ANY LD A,D Return if 'length' is zero.
  3224. 0A5D OR E
  3225. 0A5E RET Z
  3226. 0A5F LD A,(IX+4) Fetch channel specifier and jump if
  3227. 0A62 CP +CD handling with RS232 or network.
  3228. 0A64 JR NZ,0A6A,LV-BN
  3229. 0A66 CALL 15A9,LV-MCH LOAD or VERIFY from Microdrive.
  3230. 0A69 RET Finished.
  3231. 0A6A LV-BN PUSH HL Save 'start' and 'length'.
  3232. 0A6B PUSH DE
  3233. 0A6C BIT 3,(FLAGS3) Jump if RS232 link is being used.
  3234. 0A70 JR Z,0A79,LV-B
  3235. 0A72 LV-N CALL 0D12,NCHAN-IN Fetch a byte by using the "N" channel
  3236. 0A75 JR NC,0A72,LV-N Input routine.
  3237. 0A77 JR 0A7E,LV-BN-E Jump forward.
  3238. 0A79 LV-B CALL 0B81,BCHAN-IN Fetch a byte by using the "B" channel
  3239. 0A7C JR NC,0A79,LV-B input routine.
  3240. 0A7E LV-BN-E POP DE Restore 'length' and decrease it.
  3241. 0A7F DEC DE
  3242. 0A80 POP HL Restore 'start'.
  3243. 0A81 BIT 7,(FLAGS3) Jump when VERIFYING.
  3244. 0A85 JR NZ,0A8A,VR-BN
  3245. 0A87 LD (HL),A The actual LOAD, i.e. store the
  3246. received byte.
  3247. 0A88 JR 0A8F,LVBN-END Jump forward.
  3248. 0A8A VR-BN CP (HL) The actual VERIFY, i.e. compare the
  3249. received byte with that held in
  3250. memory.
  3251. 0A8B JR Z,0A8F,LVBN-END Continue only if the bytes are equal.
  3252.  
  3253. 'Verification has failed'
  3254.  
  3255. 0A8D RST 20,SH-ERR Call the error handling
  3256. 0A8E DEFB +15 routine.
  3257.  
  3258. 0A8F LVBN-END INC HL Move 'start' on to address the next
  3259. location.
  3260. 0A90 LD A,E Repeat until 'length' has reached 0.
  3261. 0A91 OR D
  3262. 0A92 JR NZ,0A6A,LV-BN
  3263. 0A94 RET Finished.
  3264.  
  3265.  
  3266. THE 'LOAD "RUN" PROGRAM' ROUTINE
  3267. First the various system variables are properly set, then a nine-byte header is fetched from the first record of the \
  3268. program called 'run'. The routine continues
  3269. into the middle of the LOAD~VERIFY-MERGE commands routine.
  3270.  
  3271. 0A95 LOAD-RUN LD BC,+0001 Load from drive 1.
  3272. 0A98 LD (D-STR1),BC
  3273. 0A9C LD BC,+0003 The filename 'run' is three
  3274. 0A9F LD (N-STR1),BC characters in length.
  3275. 0AA3 LD BC,+0AC6 The filename is stored from this
  3276. 0AA6 LD (N-STR1+2),BC location.
  3277. 0AAA SET 4,(FLAGS3) Signal 'loading'.
  3278. 0AAE CALL 0753,PROG Set HD variablea as required.
  3279. 0AB1 LD HL,+5CE6 Copy 'old' header into D-STR2 area.
  3280. 0AB4 LD DE,+5CDE
  3281. 0AB7 LD BC,+0009
  3282. 0ABA LDIR Clear the 'jump' signal set by using
  3283. 0ABC SET 7,(NSPPC) the RUN command.
  3284. 0AC0 CALL 1580,F-M-HEAD Load the 'new' 9-byte header.
  3285. 0AC3 JP 08F2,TEST-TYPE Jump back in the middle of the
  3286. LOAD-VERIFY-MERGE commands routine.
  3287.  
  3288. 0AC6 DEFM "run" The 'run' filename.
  3289.  
  3290.  
  3291. The RS-232 link routines
  3292.  
  3293. THE 'SET "BAUD" SYSTEM VARIABLE' ROUTINE
  3294. This routine is entered with a baud rate in the range 0. .65534 in the system
  3295. variable D-STR1. It rounds the value to the nearest 'standard' value and sets the BAUD system variable with the \
  3296. appropriate timing constant. It is used by the 'FORMAT' command routine.
  3297.  
  3298. 0AC9 SET-BAUD LD BC,(D-STR1) Fetch baud rate.
  3299. 0ACD LD HL,+0AEF Start of RS232 timing constants table.
  3300. 0AD0 NXT-ENTRY LD E,(HL) Fetch an entry in the DE register
  3301. 0AD1 INC HL pair.
  3302. 0AD2 LD D,(HL)
  3303. 0AD3 INC HL
  3304. 0AD4 EX DE,HL Pass the value to HL.
  3305. 0AD5 LD A,H Fetch high byte.
  3306. 0AD6 CP +48 Jump if the end of the table has been
  3307. 0AD8 JR NC,0AE4,END-SET reached.
  3308. 0ADA AND A Jump also if this value is greater
  3309. 0ADB SBC HL,BC than or equal to the supplied one.
  3310. 0ADD JR NC,0AE4,END-SET
  3311. 0ADF EX DE,HL Restore the 'pointer' in HL.
  3312. 0AE0 INC HL Skip the constant and jump back
  3313. 0AE1 INC HL to examine the next table entry.
  3314. 0AE2 JR 0AD0,NXT-ENTRY
  3315. 0AE4 END-SET EX DE,HL Restore the pointer in HL.
  3316. 0AE5 LD E,(HL) Fetch the timing constant.
  3317. 0AE6 INC HL
  3318. 0AE7 LD D,(HL)
  3319. 0AE8 LD (BAUD),DE Store the constant.
  3320. 0AEC JP 05C1,END1 Finished.
  3321.  
  3322. THE 'RS232 TIMING CONSTANTS' TABLE
  3323. The '9' entries in this table are the 'standard' baud rate values (from 75 to 19200), each one followed by the 'timing \
  3324. constant' to be stored in the BAUD system variable.
  3325.  
  3326. 0AEF DEFW +0032 First baud rate=50 (but the constant
  3327. 0AF1 DEFW +0A82 is for 75 baud).
  3328. 0AF3 DEFW +006E 2nd baud rate=110.
  3329. 0AF5 DEFW +04C5 Constant for 110 baud.
  3330. 0AF7 DEFW +012C 3rd baud rate=300.
  3331. 0AF9 DEFW +01BE Constant for 300 baud.
  3332. 0AFB DEFW +0258 4th baud rate=600.
  3333. 0AFD DEFW +00DE Constant.
  3334. 0AFF DEFW +04B0 5th baud rate=1200.
  3335. 0B01 DEFW +006E Constant.
  3336. 0B03 DEFW +0960 6th baud rate=2400.
  3337. 0B05 DEFW +0036 Constant.
  3338. 0B07 DEFW +12C0 7th baud rate=4800.
  3339. 0B09 DEFW +001A Constant.
  3340. 0B0B DEFW +2580 8th baud rate=9600.
  3341. 0B0D DEFW +000C Constant.
  3342. 0B0F DEFW +4B00 Last baud rate=l9200.
  3343. 0B11 DEFW +0005 Constant.
  3344.  
  3345. THE 'OPEN RS232 CHANNEL IN CHANS AREA' SUBROUTINE
  3346. This subroutine opens a permanent "B" or "T" channel (depending upon the specifier held in L-STR1) at the end of the \
  3347. CHANS area. On return, the DE
  3348. register pair will hold the start of the channel.
  3349.  
  3350. 0B13 OP-RS-CH LD HL,(PROG) The start address
  3351. 0B16 DEC HL of the channel.
  3352. 0B17 LD BC,+000B The channel is '11' bytes in length.
  3353. 0B1A PUSH BC
  3354. 0B1B RST 10,CALBAS Call MAKE-ROOM to create the required
  3355. 0B1C DEFW +1655 space.
  3356. 0B1E POP BC Restore 'length'.
  3357. 0B1F PUSH DE Save address of last byte in the
  3358. inserted area.
  3359. 0B20 CALL 1691,REST-N-AD Restore start address of 'filename' if
  3360. it has been moved up after the
  3361. insertion of the new space.
  3362. 0B23 POP DE Restore 'end of channel' address.
  3363. 0B24 LD HL,+0B6E Last byte in the "T" channel data
  3364. table.
  3365. 0B27 LD BC,+000B Length of the table.
  3366. 0B2A LDDR Copy the 'T' channel data.
  3367. 0B2C INC DE Point to the 1st location of the
  3368. channel.
  3369. 0B2D LD A,(L-STR1) Fetch channel specifier.
  3370. 0B30 CP +42 Return if the requested channel was
  3371. 0B32 RET NZ not the 'B' channel.
  3372. 0B33 PUSH DE Save channel start address.
  3373. 0B34 LD HL,+0005 Point to the 'shadow ROM output
  3374. 0B37 ADD HL,DE routine' pointer.
  3375. 0B38 LD DE,+0C5A the address of the BCHAN—OUT routine.
  3376. 0B3B LD (HL),E Store the low byte.
  3377. 0B3C INC HL
  3378. 0B3D LD (HL),D Store the high byte.
  3379. 0B3E INC HL Point to the 'shadow ROM input
  3380. routine' pointer.
  3381. 0B3F LD DE,+0B75 The address of the B—INPUT routine,
  3382. 0B42 LD (HL),E Store the low byte.
  3383. 0B43 INC HL
  3384. 0B44 LD (HL),D Store the high byte.
  3385. 0B45 POP DE Restore channel start address.
  3386. 0B46 RET Finished.
  3387.  
  3388. THE 'ATTACH CHANNEL TO A STREAM' ROUTINE
  3389. The entry point is OP-RSCHAN if the channel is "B" or "T", otherwise the routine is entered at OP-STREAM with "N" \
  3390. channel (from 0EA6), with DE holding the channel start address. The correct displacement is calculated for the stream \
  3391. whose number is held in S-STR1, and stored in the STRMS area.
  3392.  
  3393. 0B47 OP-RSCHAN CALL 0Bl3,OP-RS-CH Create the channel area.
  3394. 0B4A OP-STREAM LD HL,(CHANS) Calculate the displacement to be
  3395. 0B4D DEC HL stored in STRMS.
  3396. 0B4E EX DE,HL
  3397. 0B4F AND A
  3398. 0B50 SBC HL,DE
  3399. 0B52 EX DE,HL Pass the displacement to DE.
  3400. 0B53 LD HL,+5C16 Location in STRMS for stream 0.
  3401. 0B56 LD A,(S-STR1) Fetch stream number and
  3402. 0B59 RLCA double it.
  3403. 0B5A LD C,A Move the offset to the BC register
  3404. 0B5B LD B,+00 pair.
  3405. 0B5D ADD HL,BC Index into the STRMS area.
  3406. 0B5E LD (HL),E Store the displacement.
  3407. 0B5F INC HL
  3408. 0B60 LD (HL),D
  3409. 0B61 JP 05C1,END1 Finished.
  3410.  
  3411. THE '"T" CHANNEL DATA' TABLE
  3412. The '11' bytes that composes a "T" RS232 channel are as follows:
  3413.  
  3414. 0B64 DEFW +0008 Main ROM 'output' routine.
  3415. 0B66 DEFW +0008 Main ROM 'input' routine.
  3416. 0B68 DEFB +54 "T" (channel specifier).
  3417. 0B69 DEFW +0C3C Shadow ROM 'output' routine.
  3418. 0B6B DEFW +0B6F Shadow ROM 'input' routine.
  3419. 0B6D DEFW +000B Length of this channel.
  3420.  
  3421. THE '"T" CHANNEL INPUT' ROUTINE
  3422. The actual 'input' is handled by the CALL-INP routine; the service routine is TCHAN-IN below.
  3423.  
  3424. 0B6F T-INPUT LD HL,+0B7B Address of TCHAN-IN routine.
  3425. 0B72 JP 0CBD,CALL-INP Jump forward.
  3426.  
  3427. THE '"B" CHANNEL INPUT' ROUTINE
  3428. As with the "T" channel, the 'input' is handled by CALL-INP; however the service routine is BCHAN-IN.
  3429.  
  3430. 0B75 B-INPUT LD HL,+0B81 Address of BCHAN-IN routine.
  3431. 0B78 JP 0CBD,CALL-INP Jump forward.
  3432.  
  3433. THE '"T" CHANNEL INPUT' SERVICE ROUTINE
  3434. The only difference in respect to the "B" input is that the most significant bit of the received character is always \
  3435. cleared.
  3436.  
  3437. 0B7B TCHAN-IN CALL 0B81,BCHAN-IN Use the "B" channel input service
  3438. routine.
  3439. 0B7E RES 7,A Accept only codes in the range +00...
  3440. +7F (ASCII 7 bit).
  3441. 0B80 RET Finished.
  3442.  
  3443. THE '"B" CHANNEL INPUT' SERVICE ROUTINE
  3444. This subroutine is also called by using the hook code +1D; it always returns
  3445. 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 \
  3446. been read.
  3447.  
  3448. 0B81 BCHAN-IN LD HL,+5CC7 Fetch contents of SER-FL-lo system
  3449. 0B84 LD A,(HL) variable.
  3450. 0B85 AND A Proceed in receiving the byte if it
  3451. 0B86 JR Z,0B8E,REC-BYTE holds zero.
  3452. 0B88 LD (HL),+00 Otherwise clear SER-FL-lo and fetch
  3453. 0B8A INC HL the byte from SER-FL-hi.
  3454. 0B8B LD A,(HL)
  3455. 0B8C SCF Signal 'acceptable code'.
  3456. 0B8D RET
  3457. 0B8E REC-BYTE LD A,+7F Read port +7FFE.
  3458. 0B90 IN A,(+FE)
  3459. 0B92 RRCA Rotate bit 0 into carry.
  3460. 0B93 JR C,0B9A,REC-PROC Jump if SPACE not being pressed.
  3461. 0B95 LD (ERR-NR),+14 Otherwise give the 'Break into
  3462. 0B99 RST 28,ROMERR program' error report.
  3463. 0B9A REC-PROC DI Disable interrupts.
  3464. 0B9B LD A,(IOBORD) Fetch new border colour.
  3465. 0B9E OUT (+FE),A Change border colour.
  3466. 0BA0 LD DE,(BAUD) Fetch timing constant.
  3467. 0BA4 LD HL,+0320 Repeat '800' times the test.
  3468. 0BA7 LD B,D Copy timing constant into the BC
  3469. 0BA8 LD C,E register pair.
  3470. 0BA9 SRL B Make BC hold (constant/2).
  3471. 0BAB RR C
  3472. 0BAD LD A,+FE Make high the CTS line.
  3473. 0BAF OUT (+EF),A
  3474.  
  3475. 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 \
  3476. line is high for at least '77' T cycles. If after about 25 ms no 'start bit' is found, the routine continues forward.
  3477.  
  3478. 0BB1 READ-RS IN A,(+F7) Read TXdata line.
  3479. 0BB3 RLCA Shift state into carry.
  3480. 0BB4 JR NC,0BC5,TST-AGAIN Jump if the line has a low level.
  3481. 0BB6 IN A,(+F7) Repeat the test three times, i.e. make
  3482. 0BB8 RLCA sure that TXdata is still high after
  3483. 0BB9 JR NC,0BC5,TST-AGAIN 77 T cycles,
  3484. 0BBB IN A,(+F7)
  3485. 0BBD RLCA
  3486. 0BBE JR NC,0BC5,TST-AGAIN
  3487. 0BC0 IN A,(+F7)
  3488. 0BC2 RLCA
  3489. 0BC3 JR C,0BD1,START-BIT Jump if the beginning of a 'start bit'
  3490. is found.
  3491. 0BC5 TST-AGAIN DEC HL Decrease the counter.
  3492. 0BC6 LD A,H Repeat the test until the counter
  3493. 0BC7 OR L reaches zero.
  3494. 0BC8 JR NZ,0BB1,READ-RS
  3495. 0BCA PUSH AF Save zero flag set.
  3496. 0BCB LD A,+EE Make the CTS line low again.
  3497. 0BCD OUT (+EF),A
  3498. 0BCF JR 0BF0,WAIT-1 Jump forward to repeat the test.
  3499.  
  3500. 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 \
  3501. cycles is entered, so the first reading is made at the middle of the first data bit. The seven subsequent readings are \
  3502. separated by a delay of (47+26*(BAUD)) T cycles, that is the length of each bit.
  3503.  
  3504. 0BD1 START-BIT LD H,B Get (BAUD/2) into HL.
  3505. 0BD2 LD L,C
  3506. 0BD3 LD B,+80 Set a marker into bit 7.
  3507. 0BD5 DEC HL Decrease HL three times, i.e. short
  3508. 0BD6 DEC HL the loop by 78 T cycles, balancing
  3509. 0BD7 DEC HL the time spent before.
  3510. 0BD8 SERIAL-IN ADD HL,DE Add (BAUD) to HL.
  3511. 0BD9 NOP Wait 4 T cycles.
  3512. 0BDA BD-DELAY DEC HL Insert a delay (26*BAUD) T cycles in
  3513. 0BDB LD A,H length.
  3514. 0BDC OR C
  3515. 0BDD JR NZ,0BDA,BD-DELAY
  3516. 0BDF ADD A,+00 Wait 7 T cycles.
  3517. 0BE1 IN A,(+F7) Read a bit.
  3518. 0BE3 RLCA Shift it into carry flag, then into
  3519. 0BE4 RR B the B register.
  3520. 0BE6 JR NC,0BD8,SERIAL-IN Repeat until the 'marker' is found
  3521. (i.e., 8 bits have been read),
  3522. 0BE8 LD A,+EE Make the CTS line having a low level.
  3523. 0BEA OUT (+EF),A
  3524. 0BEC LD A,B Fetch the received byte.
  3525. 0BED CPL Complement it (the bits are sent
  3526. inverted through the RS232 link).
  3527. 0BEE SCF Signal 'acceptable codes' when exit.
  3528. 0BEF PUSH AF Save the byte and carry flag.
  3529. 0BF0 WAIT-1 ADD HL,DE Make HL hold (BAUD).
  3530. 0BF1 WAIT-2 DEC HL Wait until the first stop bit is
  3531. 0BF2 LD A,H finished.
  3532. 0BF3 OR L
  3533. 0BF4 JR NZ,0BF1,WAIT-2
  3534. 0BF6 ADD HL,DE
  3535. 0BF7 ADD HL,DE
  3536. 0BF8 ADD HL,DE HL now holds (BAUD)*3.
  3537.  
  3538. Now a loop similar to that at 0BB1 is entered. If the TXdata line is found high for at least 77 T cycles, the \
  3539. 'sending' device is sending the 'start' bit for a second byte, even if the CTS line has a low signal level. This byte \
  3540. is to be read and stored into SER-FL.
  3541.  
  3542. 0BF9 T-FURTHER DEC HL Decrease counter.
  3543. 0BFA LD A,L Repeat test until it has reached 0.
  3544. 0BFB OR H
  3545. 0BFC JR Z,0C36,END-RS-IN Exit if there is no further byte to
  3546. be received.
  3547. 0BFE IN A,(+F7) Read TXdata line.
  3548. 0C08 RLCA Shift received bit into carry.
  3549. 0C01 JR NC,0BF9,T-FURTHER Jump back with TXdats low.
  3550. 0C03 IN A,(+F7) Otherwise repeat the test three times
  3551. 0C05 RLCA to ensure that TXdata is still
  3552. 0C06 JR NC,0BF9,T-FURTHER high after 77 T cycles,
  3553. 0C08 IN A,(+F7)
  3554. 0C0A RLCA
  3555. 0C0B JR NC,0BF9,T-FURTMER
  3556. 0C0D IN A,(+F7)
  3557. 0C0E RLCA
  3558. 0C10 JR NC,0BF9,T-FURTHER
  3559. 0C12 LD H,D Fetch timing constant into HL.
  3560. 0C13 LD L,E
  3561. 0C14 SRL H Calculate (BAUD)/2 into HL.
  3562. 0C16 RR L
  3563.  
  3564. The next instructions are the same as those stored from 0BD3 above, so they are not commented.
  3565.  
  3566. 0C18 LD B,+00
  3567. 0C1A DEC HL
  3568. 0C1B DEC HL
  3569. 0C1C DEC HL
  3570. 0C1D SER-IN-2 ADD HL,DE
  3571. 0C1E NOP
  3572. 0C1F BD-DELAY2 DEC HL
  3573. 0C20 LD A,H
  3574. 0C21 OR L
  3575. 0C22 JR NZ,0C1F,BD-DELAY2
  3576. 0C24 ADD A,+00
  3577. 0C26 IN A,(+F7)
  3578. 0C28 RLCA
  3579. 0C29 RR B
  3580. 0C2B JR NC,0C1D,SER-IN-2
  3581.  
  3582. Finally, the last byte received is stored into SER-FL, and the first one returned into the A register.
  3583.  
  3584. 0C2D LD HL,+5CC7 Points to SER-FL-lo
  3585. 0C30 LD (HL),+01 Set it to +01, indicating that
  3586. SER-FL-hi holds a valid byte.
  3587. 0C32 INC HL Points to SER-FL-hi.
  3588. 0C33 LD A,B Fetch the received byte.
  3589. 0C34 CPL Complement it and store into
  3590. 0C35 LD (HL),A SER-FL-hi.
  3591. 0C36 END-RS-IN CALL 0CA9,BORDREST Restore border colour.
  3592. 0C39 POP AF Restore first byte and flags.
  3593. 0C3A EI Enable interrupts.
  3594. 0C3B RET Finished.
  3595.  
  3596.  
  3597. THE '"T" CHANNEL OUTPUT' ROUTINE
  3598. The "t" channel output involves the 'sending' over the RS232 link of the character held into the A register, provided \
  3599. that it is within the range +20...+7F. Characters from +80 to +A4 are sent as '?', while tokens are de-tokenised. \
  3600. Codes lower than +20 are ignored, except for +0D that sends both CR and LF codes. The routine unfortunately contains a \
  3601. mistake as it does not suppress the 'leading space' flag (bit 0 of FLAGS) as required. The result is that when sending \
  3602. two tokens (i.e., THEN GOTO), two spaces are inserted between them, instead of one. The correct routine should include \
  3603. the following two instructions after the final 'RET C': 'JR NZ,BCHAN-OUT' and 'SET 0,(FLAGS)', and a 'RES 0,(FLAGS)' \
  3604. before the 'CP +7F'.
  3605.  
  3606. 0C3C TCHAN-OUT CF +A5 Jump if the code is not a token code.
  3607. 0C3E JR C,0C46,NOT-TOKEN
  3608. 0C40 SUB +A5 Reduce range of token,
  3609. 0C42 RST 10,CALBAS and detokenise it by calling
  3610. 0C43 DEFW +0C10 recursively this routine via main ROM
  3611. 0C45 RET 'PO-TOKENS' routine.
  3612. 0C46 NOT-TOKEN CP +7F Jump if the character is not a
  3613. 0C48 JR C,0C4C,NOT-GRAPH graphic character.
  3614. 0C4A LD A,+3F Otherwise send a '?'.
  3615. 0C4C NOT-GRAPH CP +0D Is the code 'ENTER'?
  3616. 0C4E JR NZ,0C57,NOT-CR Jump if not.
  3617. 0C50 CALL 0C5A,BCHAN-OUT Otherwise send the CR code.
  3618. 0C53 LD A,+0A Follow it with a linefeed code.
  3619. 0C55 CALL 0C5A,BCHAN-OUT
  3620. 0C57 NOT-CR CP +20 Ignore all codes lower than +20,
  3621. 0C59 RET C otherwise use BCHAN-OUT below to send
  3622. the character.
  3623.  
  3624. THE '"B" CHANNEL OUTPUT' ROUTINE
  3625. The 8 bits that forms the byte held in the A register are sent inverted through the RS232 link, after an initial \
  3626. 'start' bit (high), and followed by two 'stop' bits (or rather a 'double length' stop bit, with low signal level). As \
  3627. with 'b' channel input, the bits have a fixed length, depending upon the selected baud rate. This subroutine is also \
  3628. called by the 'hook code' +1E.
  3629.  
  3630. 0C5A BCHAN-OUT LD B,+0B Counts '11' bits.
  3631. 0C5C CPL Invert the eight data bits.
  3632. 0C5D LD C,A C holds the byte to be sent.
  3633. 0C5E LD A,(IOBORD) Fetch new border colour.
  3634. 0C61 OUT (+FE),A Change border colour.
  3635. 0C63 LD A,+EF Reset CTS and select RS232.
  3636. 0C65 OUT (+EF),A
  3637. 0C67 CPL
  3638. 0C68 OUT (+F7),A Make RXdata have a low signal level.
  3639. 0C6A LD HL,(BAUD) Fetch timing constant.
  3640. 0C6D LD D,H Copy into DE register pair.
  3641. 0C6E LD E,L
  3642. 0C6F BD-DEL-1 DEC DE Firstly wait (26*(BAUD)) T cycles.
  3643. 0C70 LD A,D
  3644. 0C7l OR E
  3645. 0C72 JR NZ,0C6F,BD-DEL-1
  3646. 0C74 TEST-DTR LD A,+7F Read port +7FFE (SPACE key).
  3647. 0C76 IN A,(+FE)
  3648. 0C78 OR +FE Read port +FEFE (CAPS SHIFT key) only
  3649. 0C7A IN A,(+FE) if SPACE is being pressed.
  3650. 0C7C RRA Test bit 0.
  3651. 0C7D JP NC,0CB4,BRK-INOUT Give an error if BREAK is pressed.
  3652. 0C80 IN A,(+EF) Read DTR line.
  3653. 0C82 AND +08 Only bit 3.
  3654. 0C84 JR Z,0C74,TEST-DTR Jump back until DTR is found high.
  3655. 0C86 SCF Set carry flag (start bit).
  3656. 0C87 DI Disable interrupts.
  3657. 0C88 SER-OUT-L ADC A+00 In fact, shift carry into bit 0 of
  3658. accumulator.
  3659. 0C8A OUT (+F7),A Send this bit over RS232 link.
  3660. 0C8C LD D,H Copy timing constant into DE.
  3661. 0C8D LD E,L
  3662. 0C8E BD-DEL-2 DEC DE Wait 26*(BAUD) T cycles after having
  3663. 0C8F LD A,D sent each bit.
  3664. 0C90 OR E
  3665. 0C9l JR NZ,0C8E,BD-DEL-2
  3666. 0C93 DEC DE Wait 6 T cycles.
  3667. 0C94 XOR A Clear A for next pass.
  3668. 0C95 SRL C Shift the bit to be sent into carry.
  3669. 0C97 DJNZ 0C88,SER-OUT-L Loop for all 11 bits.
  3670. 0C99 DI Enable interrupts.
  3671. 0C9A LD A,+01
  3672. 0C9C LD C,+EF
  3673. 0C9E LD B,+EE
  3674. 0CA0 OUT (+F7),A Make RXdata having a high level.
  3675. 0CA2 OUT (C),B Turn off RS232.
  3676. 0CA4 BD-DEL-3 DEC HL Insert a final delay before returning
  3677. 0CA5 LD A,L via the border-restore routine
  3678. 0CA6 OR H below.
  3679. 0CA7 JR NZ,0CA4,BD-DEL-3
  3680.  
  3681. THE 'BORDER COLOUR RESTORE' SUBROUTINE
  3682. This subroutine is used whenever the border colour has been changed to IOBORD during an I/O operation, and needs to be \
  3683. restored to its original state.
  3684.  
  3685. 0CA9 BORD-REST LD A,(BORDCR) Fetch lower screen attribute.
  3686. 0CAC AND +38 Only bits 3,4,5, i.e. BORDER.
  3687. 0CAE RRCA Rotate colour into bits 0,l,2.
  3688. 0CAF RRCA
  3689. 0CB0 RRCA
  3690. 0CB1 OUT (+FE),A Restore colour.
  3691. 0CB3 RET Finished.
  3692.  
  3693. THE 'BREAK INTO I/O OPERATION' ROUTINE
  3694. Whenever BREAK is pressed during an I/O operation, the interrupts have to be enabled, the border colour to be restored \
  3695. and the error "BREAK into program" to be given.
  3696.  
  3697. 0CB4 BRK-INOUT EI Enable interrupts.
  3698. 0CB5 CALL 0CA9,BORD-REST Restore border colour.
  3699. 0CB8 LD (ERR-NR),+l4 Store error code and give the error.
  3700. 0CBC RST 28,ROMERR
  3701.  
  3702. THE 'CALL-INP' ROUTINE
  3703. All inputs from "B", "T", "N" and "M" channels are handled by loading HL with the address of the service 'input' \
  3704. routine for the channel, and then jumping to this routine. The routine handles both INPUT and INKEY$ commands referred \
  3705. to the
  3706. 'new' channels.
  3707.  
  3708. 0CBD CALL-INP RES 3,(TVFLAG) 'The mode is to be considered as being
  3709. unchanged'
  3710. 0CC1 PUSH HL Save address of the service routine.
  3711. 0CC2 LD HL,(ERR-SP) Points to the error address.
  3712. 0CC5 LD E,(HL) Fetch low byte of error addres
  3713. 0CC6 INC HL
  3714. 0CC7 LD D,(HL) Fetch high byte.
  3715. 0CC8 AND A Prepare for a true subtraction.
  3716. 0CC9 LD HL,+107F This is ED-ERROR.
  3717. 0CCC SBC HL,DE Jump forward if not during an INPUT
  3718. 0CCE JR NZ,0CFB,INKEY$ command.
  3719.  
  3720. Now deal with 'INPUT #' command referred to an Interface channel.
  3721.  
  3722. 0CD0 POP HL Restore address of service routine.
  3723. 0CD1 LD SP,(ERR-SP) Clear machine stack.
  3724. 0CD5 POP DE Remove ED-ERROR.
  3725. 0CD6 POP DE The old value of ERR-SP
  3726. 0CD7 LD (ERR-SP),DE is restored.
  3727. 0CDB IN-AGAIN PUSH HL Save address of the service routine.
  3728. 0CDC LD DE,+0CE1 Return address is INPUT-END below.
  3729. 0CDF PUSH DE
  3730. 0CE0 JP (HL) Jump to the service routine.
  3731.  
  3732. When the character has been read from the required channel, a return is made here to add the character to the INPUT \
  3733. line, or to return if the character is ENTER.
  3734.  
  3735. 0CE1 INPUT-END JR C,0CED,ACC-CODE Jump with acceptable codes.
  3736. 0CE3 JR Z,0CEA,NO-READ Jump with no data read.
  3737. 0CE5 OREPORT-8 LD (ERR-NR),+07 Otherwise report the 'End of file'
  3738. 0CE9 RST 28,ROMERR error.
  3739. 0CEA NO-READ POP HL Restore address of service routine
  3740. 0CEB JR 0CDB,IN-AGAIN and try again.
  3741. 0CED ACC-CODE CP +0D Jump if the code is ENTER.
  3742. 0CEF JR Z,0CF7,END-INPUT
  3743. 0CF1 RST 10,CALBAS Otherwise the character is to be added
  3744. 0CF2 DEFW +0F85 to the INPUT line - so enter into the
  3745. main ROM 'ADD-CHAR' subroutine.
  3746. 0CF4 POP HL Restore address of service routine
  3747. 0CF5 JR 0CDB,IN-AGAIN and read the next byte.
  3748. 0CF7 END-INPUT POP HL Remove address of service routine.
  3749. 0CF8 JP 0700,UNPAGE Return to the main ROM calling
  3750. routine.
  3751.  
  3752. Enter here to deal with the INKEY$ function (a single character is returned).
  3753.  
  3754. 0CFB INKEY$ POP HL Address of service routine.
  3755. 0CFC LD DE,+0D01 Return address is INK$-END below.
  3756. 0CFF PUSH DE
  3757. 0D00 JP (HL) Jump to the service routine.
  3758.  
  3759. After having read the byte, a return is made here.
  3760.  
  3761. 0D01 INK$-END RET C Return with acceptable codes, or
  3762. 0D02 RET Z no character read.
  3763. 0D03 BIT 4,(FLAGS3) Give the 'end of file' error if bit
  3764. 0D07 JR Z,0CE5,OREPORT-8 4 of FLAGS3 is reset.
  3765. 0D09 OR +01 Otherwise the MOVE command has been
  3766. 0D0B RET used - so return with carry and zero
  3767. flags both reset.
  3768.  
  3769.  
  3770. The Network routines
  3771.  
  3772. THE '"N" CHANNEL INPUT' ROUTINE
  3773. The actual 'input' is handled via the CALL-INP routine above. The service routine is NCHAN-IN.
  3774.  
  3775. 0D0C N-INPUT LD HL,+0D12 Address of NCHAN-IN routine.
  3776. 0D0F JP 0CBD,CALL-INP Jump to the control routine.
  3777.  
  3778. THE '"N" CHANNEL INPUT' SERVICE ROUTINE
  3779. The actual "n" input involves the reading of the byte from the network buffer. If no other bytes are found in the \
  3780. buffer, a further data block is to be received (provided that the 'current' block is not the 'EOF' one) before reading \
  3781. the byte.
  3782.  
  3783. 0D12 NCHAN-IN LD IX,(CURCHL) Fetch start of "n" channel.
  3784. 0D16 LD A,(NCOBL) This holds 0 while 'receiving'.
  3785. 0D19 AND A Jump if it is a "read" file.
  3786. 0D1A JR Z,0D1E,TEST-BUFF
  3787.  
  3788. 'Reading a 'write' file'
  3789.  
  3790. 0D1C RST 20,SH-ERR Call the error handling
  3791. 0D1D DEFB +0D routine.
  3792.  
  3793. 0D1E TEST-BUFF LD A,(NCIBL) Fetch number of bytes to be read
  3794. from the buffer.
  3795. 0D21 AND A If NCIBL holds zero, then the buffer
  3796. 0D22 JR Z,0D38,TST-N-EOF is empty.
  3797. 0D24 LD E,(NCCUR) Otherwise fetch the current position.
  3798. 0D27 DEC A Decrease number of bytes to be read
  3799. from the buffer.
  3800. 0D28 SUB E Subtract position from the result.
  3801. 0D29 JR C,0D38,TST-N-EOF Jump if all bytes have been read.
  3802. 0D2B LD D,+00 Clear D register.
  3803. 0D2D INC E Update the character position.
  3804. 0D2E LD (NCCUR),E
  3805. 0D31 ADD IX,DE Points to 'byte to be read - 20'.
  3806. 0D33 LD A,(IX+20) Read the byte.
  3807. 0D36 SCF Carry is set to signal 'acceptable
  3808. byte'.
  3809. 0D37 RET Finished.
  3810.  
  3811. If no data is found in the buffer, consider whether this data block is the last one.
  3812.  
  3813. 0D38 TST-N-EOF LD A,(NCTYPE) Fetch packet type.
  3814. 0D3B AND A Jump if packet type = 0.
  3815. 0D3C JR Z,0D3F,GET-N-BUF Indicating a normal packet.
  3816. 0D3E RET Otherwise return with both zero and
  3817. carry flags reset to signal 'end of
  3818. file'.
  3819.  
  3820. A further data block is to be received if the current data block is not the 'EOF' one.
  3821.  
  3822. 0D3F GET-N-BUF LD A,(IOBORD) Fetch new border colour.
  3823. 0D42 OUT (+FE),A Change border colour.
  3824. 0D44 DI Disable interrupts.
  3825. 0D45 TRY-AGAIN CALL 0F1E,WT-SCOUT Wait for a 'scout' leader.
  3826. 0D48 JR NC,0D5F,TIME-OUT Jump if 'time out' occurs.
  3827. 0D4A CALL 0E18,GET-NBLK Wait for header and data block.
  3828. 0D4D JR NZ,0D5F,TIME-OUT Jump with any error.
  3829. 0D4F EI Enable interrupts.
  3830. 0D51 CALL 0CA9,BORD-REST Restore border colour.
  3831. 0D53 LD (NCCUR),+00 The position is 0.
  3832. 0D57 LD A,(NTTYPE) Copy this byte
  3833. 0D5A LD (NCTYPE),A to signal the packet type.
  3834. 0D5D JR 0D1E,TEST-BUFF Try now to fetch the byte.
  3835. 0D5F TIME-OUT LD A,(NCIRIS) Fetch destination station no.
  3836. 0D62 AND A There is no 'time-out' when
  3837. 0D63 JR Z,0D45,TRY-AGAIN broadcasting (NCIRIS=0).
  3838. 0D65 DI Enable interrupts.
  3839. 0D66 CALL 0CA9,BORD-REST Restore border colour.
  3840. 0D69 AND +00 Return with zero flag set and carry
  3841. 0D6B RET reset, signalling that no data has
  3842. been read.
  3843.  
  3844. THE '"N" CHANNEL OUTPUT' ROUTINE
  3845. The routine that handles the "n" channel output is quite straightforward. It involves the storing of the byte held in \
  3846. the A register into the 255-byte buffer; whenever this is filled, the subroutine S-PACK-1 is called, so the data block \
  3847. is sent over the network.
  3848.  
  3849. 0D6C NCHAN-OUT LD IX,(CURCHL) Point to start of channel.
  3850. 0D70 LD B,A Save temporarily into B the byte to
  3851. be sent.
  3852. 0D71 LD A,(NCIBL) This holds 0 for 'write' channel.
  3853. 0D74 AND A Set zero flag as required.
  3854. 0D75 LD A,B Restore the byte to be sent.
  3855. 0D76 JR Z,0D7A,TEST-OUT Continue only if using a 'write'
  3856. channel (NCIBL=0).
  3857. 'Writing to a 'read' file'
  3858.  
  3859. 0D78 RST 20,SH-ERR Call the error handling
  3860. 0D79 DEFB +0C routine.
  3861. 0D7A TEST-OUT LD E,(NCOBL) Fetch length of output buffer.
  3862. 0D7D INC E Include the current byte in the
  3863. length count.
  3864. 0D7E JR NZ,0D88,ST-BF-LEN Jump unless the buffer is filled.
  3865. 0D80 PUSH AF Save the byte to be sent.
  3866. 0DB1 XOR A Signal normal packet type.
  3867. 0D82 CALL 0DAB,S-PACK-1 Send the packet.
  3868. 0D85 POP AF Restore the byte to be sent.
  3869. 0D86 LD E,+01 'Only 1 byte in the buffer'.
  3870. 0D88 ST-BF-LEN LD (NCOBL),E Store new buffer length.
  3871. 0D8B LD D,+00 Make IX point to 'first free byte in
  3872. 0D8D ADD IX,DE the buffer - 20).
  3873. 0D8F LD (IX+20),A Store byte in the buffer.
  3874. 0D92 RET Finished.
  3875.  
  3876. THE 'OUT-BLK-N' SUBROUTINE
  3877. This subroutine calls the OUTPAK subroutine to send over the network the block of bytes starting from (HL), and whose \
  3878. length is held into the E register. Then a 'response byte' is to be received into the NTRESP system variable (provided \
  3879. that you are not using the broadcast). The zero flag is returned reset if no
  3880. response byte has been received. This subroutine is called from SEND-PACK below to send the header and then the data \
  3881. block over the network.
  3882.  
  3883. 0D93 OUT-BLK-N CALL 0FC5,OUTPAK Send the block.
  3884. 0D96 LD A,(NCIRIS) This holds zero when broadcasting.
  3885. 0D99 AND A
  3886. 0D9A RET Z Return if broadcasting.
  3887. 0D93 LD HL,+5CCD Address of NTRESP system variable.
  3888. 0D9E LD (HL),+00 First clear NTRESP.
  3889. 0DA0 LD E,+01 A single byte is to be received
  3890. into NTRESF.
  3891. 0DA2 CALL 0F92,INPAK Get response byte (+01).
  3892. 0DA5 RET NZ Return with zero flag reset if the
  3893. network was inactive.
  3894. 0DA6 LD A,(NTRESP) Now fetch the response byte.
  3895. 0DA9 DEC A It must be +01.
  3896. 0DAA RET Return with zero flag reset if it
  3897. is not +01.
  3898.  
  3899. THE 'S-PACK-1' SUBROUTINE
  3900. This subroutine simply calls SEND-PACK below. If broadcasting, a certain delay is to be inserted after having sent the \
  3901. packet.
  3902.  
  3903. 0DAB S-PACK-1 CALL 0DB2,SEND-PACK Send the packet.
  3904. 0DAE RET NZ Return if not broadcasting.
  3905. 0DAF JP 0E0F,BR-DELAY Otherwise exit through the delay
  3906. routine.
  3907.  
  3908. THE 'SEND-PACK' SUBROUTINE
  3909. This subroutine is also called by using 'hook code' +30. It sends over the network a SCOUT leader, followed by the \
  3910. header and the data block for the "n" channel pointed by the IX register. On entry, the A register may hold +01 or +00 \
  3911. depending upon whether the block is the 'end of file' one or not. NCNUMB is incremented before returning. The zero \
  3912. flag is returned set if the destination station number denotes that the 'broadcasting' is being used.
  3913.  
  3914. 0DB2 SEND-PACK LD (NCTYPE),A Store packet type, i.e. +00 for
  3915. normal, +01 for end of file.
  3916. 0DB5 LD B,(NCOBL) Fetch block length.
  3917. 0DB8 LD A,(IOBORD) Fetch new border colour.
  3918. 0DBB OUT (+FE),A
  3919. 0DBD PUSH IX Make DE point to the start of the
  3920. 0DBF POP DE "n" channel.
  3921. 0DC0 LD HL,+0015 Add this offset to point to
  3922. 0DC3 ADD HL,DE the start of the 255-byte buffer.
  3923.  
  3924. Now the checksum of the data block is calculated.
  3925.  
  3926. 0DC4 XOR A First clear A register.
  3927. 0DC5 CHKS1 ADD A,(HL) Add this byte.
  3928. 0DC6 INC HL Point to next location.
  3929. 0DC7 DJNZ 0DC5,CHKS1 Repeat for all bytes in the block.
  3930. 0DC9 LD (NCDCS),A Store the checksum obtained.
  3931. 0DCC LD HL,+000B Now points to NCIRIS.
  3932. 0DCF ADD HL,DE
  3933. 0DD0 PUSH HL Save the pointer.
  3934.  
  3935. The checksum of the header is calculated.
  3936.  
  3937. 0DD1 LD B,+07 Checksum is for 7 bytes.
  3938. 0DD3 XOR A Clear A register.
  3939. 0DD4 CHKS2 ADD A,(HL) Add this byte.
  3940. 0DD5 INC HL Point to next location.
  3941. 0DD6 DJNZ 0DD4,CHKS2 Repeat for all bytes.
  3942. 0DD8 LD (HL),A Store checksum into NCHCS.
  3943.  
  3944. Now the SCOUT leader, followed by the 8-byte header, is sent, and a response code is received (if not broadcasting).
  3945.  
  3946. 0DD9 DI Disable interrupts.
  3947. 0DDk SENDSCOUT CALL 9Fb1,SEND-SC Send the SCOUT (i.e. a leader
  3948. followed by station number).
  3949. 0DD0 POP HL Restore pointer to NCIEIS,
  3950. 0DD1 PUSH HL i.e. Start of header block.
  3951. 0DD1 LD 1,48 The header Is made by '8' bytes.
  3952. 0DE1 CALL 9II93,OUT-BLK-N The header is sent, and the response
  3953. code received.
  3954. 0DE4 JR NZ,0DDA,SENDSCOUT Repeat until successfully.
  3955. 0DE6 PUSH IX Make HL point to the start of the "n"
  3956. 0DE8 POP HL channel.
  3957. 0DE9 LD DE,+0015 Now points to the start of the data
  3958. 0DEC ADD HL,DE block.
  3959. 0DED LD E,(NCOBL) Get block length.
  3960. 0DF0 LD A,E If NCOBL is zero (i.e. if the buffer
  3961. 0DF1 AND A is empty); no data needs to be sent.
  3962. 0DF2 JR Z,0DFD,INC-BLKN
  3963. 0DF4 LD B,+20 Wait 418 T cycles before proceeding.
  3964. 0DF6 SP-DL-1 DJNZ 0DF6,SP-DL-1
  3965.  
  3966. Now the data block is sent, and NCNUMB updated.
  3967.  
  3968. 0DF8 CALL 0D93,OUT-BLK-N Send the data block and get the
  3969. response code.
  3970. 0DF8 JR NZ,0DDA,SENDSCOUT Repeat until succesfully.
  3971. 0DF0 INC_BLKN INC (NCNUMB-lo) Increment low byte of block number.
  3972. 0E00 JR NZ,0E05,SP-N-END
  3973. 0E02 INC (NCNUMB-hi) Increment also high byte when low
  3974. byte reaches zero.
  3975. 0E05 SP-N-END POP HL Restore pointer to NCIRIS.
  3976. 0E06 CALL 0CA9,BORD-REST Restore border colour.
  3977. 0E09 EI Enable interrupts.
  3978. 0E0k LD A,(NCIRIS) Get destination station number.
  3979. 0E00 AND A Set zero flag if NCIRIS is 0 (i.e.
  3980. broadcasting).
  3981. 0E01 RET Finished.
  3982.  
  3983. THE 'BR-DELAY' SUBROUTINE
  3984. This short subroutine inserts a delay of about 40 msec. when it is called. Its task is that of separating outputs \
  3985. during 'broadcasts' transmissions.
  3986.  
  3987. 0E01 BR-DELAY LD DE,+1500 Set a counter.
  3988. 0E12 DL-LOOP DEC DE Decrease it.
  3989. 0E13 LD A,E Check whether the counter has reached
  3990. 0E14 OR D zero.
  3991. 0E15 JR NZ,0E12,DL-LOOP Repeat if not.
  3992. 0E17 RET Finished.
  3993.  
  3994. THE 'HEADER AND DATA BLOCK RECEIVING' ROUTINES
  3995. The following two subroutines are used to get from the Network an 8-byte header and a data block respectively. Both \
  3996. require that the IX register point to the start of the "n" channel. The zero flag is returned reset with any error.
  3997.  
  3998. 0E18 GET-NBLK LD HL,+5CCE Point to NTDEST, i.e. first byte of
  3999. header block.
  4000. 0E1B LD E,+08 Length of the block.
  4001. 0E1D CALL 0F92,INPAK Receive the header.
  4002. 0E20 RET NZ Return with network inactive (i.e.
  4003. no header has been found).
  4004. 0E21 LD HL,+5CCE Points again to NTDEST.
  4005.  
  4006. Now the header checksum is calculated, and compared with NTCHS checksum.
  4007.  
  4008. 0E24 XOR A First clear A.
  4009. 0E25 LD B,+07 Checksum for next 7 bytes.
  4010. 0E27 CHKS3 ADD A,(HL) Add this byte.
  4011. 0E28 INC HL Point to next location.
  4012. 0E29 DJNZ 0E27,CHKS3 Repeat for all bytes.
  4013. 0E2B CP (HL) Compare with NTCHS checksum.
  4014. 0E2C RET NZ Return if they do not match.
  4015.  
  4016. Some other tests are now made.
  4017.  
  4018. 0E2D LD A,(NTDEST) Fetch destination station number.
  4019. 0E30 AND A Jump if broadcasting.
  4020. 0E31 JR Z,0E40,BRCAST
  4021. 0E33 CP (NCSELF) Otherwise compare with NCSELF.
  4022. 0E36 RET NZ Return if this data block is for
  4023. another Spectrum.
  4024. 0E37 LD A,(NTSRCE) Source station number.
  4025. 0E3A CP (NCIRIS) Compare against NCIRIS.
  4026. 0E3D RET NZ Return if the transmitting Spectrum
  4027. is not the required one.
  4028. 0E3E JR 0E45,TEST-BLKN Jump forward.
  4029. 0E40 BRCAST LD A,(NCIRIS) Make sure that it is broadcasting
  4030. 0E43 OR A (i.e. NTDEST and NCIRIS both 0).
  4031. 0E44 RET NZ Return if you are not waiting for a
  4032. broadcast.
  4033. 0E45 TEST-BLKN LD HL,(NTNUMB) Fetch number of block being
  4034. transmitted.
  4035. 0E48 LD E,(MCNUMB-lo) Fetch number of expected block.
  4036. 0E4B LD D,(NCNUMB-hi)
  4037. 0E4E AND A
  4038. 0E4F SBC HL,DE Jump if the block received is the
  4039. 0E51 JR Z,0E65,GET-NBUFF expected one.
  4040. 0E53 DEC HL Accept also the previous block
  4041. 0E54 LD A,H (already received, but 'response'
  4042. 0E55 OR C lost).
  4043. 0E56 RET NZ But refuse other blocks.
  4044. 0E57 CALL 0E65,GET-NBUFF Receive the block.
  4045. 0E5A DEC (NCNUMB-lo) Decrease NCNUMB, i.e. 'ignore' this
  4046. 0E5D JR NC,0E62,GETNB-END block.
  4047. 0E5F DEC (NCNUMB-hi)
  4048. 0E62 GETNB-END OR +01 Return with zero flag reset, so that
  4049. 0E64 RET the procedure is repeated.
  4050.  
  4051. Now follows the second routine, used to get the data block from the network.
  4052.  
  4053. 0E65 GET-NBUFF LD A,(NTDEST) This holds zero when broadcasting.
  4054. 0E68 AND A
  4055. 0E69 CALL NZ,0FBE,SEND-RESP Send the 'response' code (for the
  4056. header) unless broadcasting.
  4057. 0E6C LD A,(NTLEN) Fetch data block length.
  4058. 0EbF AND A Jump if the data block is empty.
  4059. 0E73 JR Z,0E93,STORE-LEN
  4060. 0E72 PUSH IX Make HL point to the start of the
  4061. 0E74 POP HL channel.
  4062. 0E75 LD DE,+0015 Point to the start of data buffer.
  4063. 0E78 ADD HL,DE
  4064. 0E79 PUSH HL Save start address.
  4065. 0E?A LD E,A Length of the block to be received
  4066. goes into E.
  4067. 0E7B CALL 0F92,INPAK Receive the data block.
  4068. 0E7E POP HL Restore start address.
  4069. 0E7F RET NZ Return if the network was inactive.
  4070. 0E83 LD A,(NTLEN) Pass length of data block to the
  4071. 0E83 LD B,A B register.
  4072. 0E84 LD A,(NTDCS) Start with the data block checksum.
  4073. 0E87 CHKS4 SUB (HL) Subtract current byte.
  4074. 0E88 INC HL Point to next location.
  4075. 0E89 DJNZ 0E87,CHKS4 Repeat for all bytes in the block.
  4076. 0E8B RET NZ Return if the checksum is wrong.
  4077. 0E8C LD A,(NTDEST) This holds 0 when broadcasting.
  4078. 0E8F AND A
  4079. 0E93 CALL NZ,0FBE,SEND-SCOUT Send response code for the data block
  4080. (unless broadcasting).
  4081. 0E93 STORE-LEN LD A,(NTLEN) Fetch data block length.
  4082. 0E96 LD (NCIBL),A Copy it into NCIBL.
  4083. 0E99 INC (NCNUMB-lo) Finally increment block number.
  4084. 0E9C JR NZ,0EA1,GETBF-END
  4085. 0E9E INC (NCNUMB-hi)
  4086. 0EA1 GETBF-END CP A Return with zero flag set to signal
  4087. 0EA2 RET 'block successfully received'.
  4088.  
  4089. THE 'OPEN "N" CHANNEL' COMMAND ROUTINE
  4090. This routine is the actual OPEN command referred to the network. It is called from the 'OPEN' command syntax routine \
  4091. to attach a permanent "n" channel to a stream.
  4092.  
  4093. 0EA3 OPEN-N-ST CALL 0EB5.OP-PERM-N Open a permanent "n" channel.
  4094. 0EA6 JP 0B4A,OP-STREAM Attach it to a stream.
  4095.  
  4096. THE 'OPEN TEMPORARY "N" CHANNEL' SUBROUTINE
  4097. This subroutine is also called by using the 'hook code' +2D. It simply opens a permanent 'n' channel, and then makes \
  4098. it "temporary" by setting bit 7 of the channel specifier. The variables are to be set as for the OP-PERM-N subroutine \
  4099. below. The start of the channel area is returned in the IX index register.
  4100.  
  4101. 0EA9 OP-TEMP-N CALL 0EB5,OP-PERM-N Open a permanent "n" channel.
  4102. 0EAC LD IX,(CURCHL) Fetch start of channel area.
  4103. 0EB1 SET 7,(IX+4) Make the channel temporary.
  4104. 0EB4 RET Finished.
  4105.  
  4106. THE 'OPEN PERMANENT "N" CHANNEL" SUBROUTINE
  4107. On entry, D-STR1 must hold the destination station number to be copied into NCIRIS, while NTSTAT must hold the own \
  4108. station number to be copied into NCSELF. A permanent "n" channel is created into the CHANS area, and it is made, the \
  4109. 'current' channel. The routine returns the channel base address into the DE register pair.
  4110.  
  4111. 0EB5 OP-PERN-N LD HL,(PROG) Fetch start address of the channel
  4112. 0EB8 DEC HL created.
  4113. 0EB9 LD BC,+0114 Length of the channel.
  4114. 0EBC PUSH BC Save it briefly.
  4115. 0EBD RST 10,CALBAS Call main ROM 'MAKE-ROOM' subroutine
  4116. 0EBE DEFW +1655 to make the required space.
  4117. 0EC3 INC HL Point to the first new location.
  4118. 0EC1 POP BC Restore 'length' of space inserted.
  4119. 0EC2 CALL I691,RESThN.,.AD Restore start address of 'filename'
  4120. possibly moved up after the
  4121. insert ion.
  4122. 0EC5 LD (CHURCHL),HL Make the Channel 'current'
  4123. 0EC8 EX DE,HL Pass 'start' to DE.
  4124. 0EC9 LD HL,+0EEA Start of "n" Channel data.
  4125. 0ECC LD BC,+000B Length of data.
  4126. 0ECF LDIR Copy the data into the channel area.
  4127. 0ED1 LD A,(DSTR-1) Fetch destination station number.
  4128. 0ED4 LD (DE),A Copy it into NCIRIS.
  4129. 0ED5 INC DE Points to NCSELF.
  4130. 0ED6 LD A,(NTSTAT) Fetch own station number.
  4131. 0ED9 LD (DE),A Copy it into NCSELF.
  4132. 0EDA INC DE Points to NCNUMB.
  4133. 0EDB XOR A Clear it.
  4134. 0EDC LD (DE),A
  4135. 0EDD LD H,D Fill the remaining bytes with zeros.
  4136. 0EDE LD L,E
  4137. 0EDF INC DE
  4138. 0EE0 LD BC,+0106
  4139. 0EE3 LDIR
  4140. 0EE5 LD DE,(CURCHL) Fetch start address of the channel.
  4141. 0EE9 RET Finished.
  4142.  
  4143. THE '"N" CHANNEL DATA' TABLE
  4144. The '11' bytes that composes the initial part of a "N" channel are as follows:
  4145.  
  4146. 0EEA DEFW +0008 Main ROM 'output' routine.
  4147. 0EEC DEFW +0008 Main ROM 'input' routine.
  4148. 0EEE DEFB +43 "N" (channel specifier)
  4149. 0EEF DEFW +0D6C Shadow ROM 'output' routine.
  4150. 0EF1 DEFW +0D0C Shadow ROM 'input' routine.
  4151. 0EF3 DEFW +0114 Length of "n" channel.
  4152.  
  4153. THE 'SEND EOF BLOCK TO NETWORK' SUBROUTINE
  4154. This subroutine is used whenever the remaining buffer contents of the current "n" channel have to be sent as the "end \
  4155. of file" block.
  4156.  
  4157. 0EF5 SEND-NEOF LD IX,(CURCHL) Fetch start address of channel.
  4158. 0EF9 LD A,(NCOBL) Fetch data block length.
  4159. 0EFC AND A Return if this is a 'read' channel
  4160. 0EFD RET Z (NCOBL=0).
  4161. 0EFE LD A,+01 Signal 'EOF' packet.
  4162. 0F00 JP 0DAB,S-PACK-1 Send packet and exit.
  4163.  
  4164. THE 'NETWORK STATE' SUBROUTINE
  4165. This subroutine returns when the network is considered to be 'resting', i.e. when the network line is inactive for 3-4 \
  4166. ms. The exact time is 'randomised' as to prevent Spectrums from claiming the network at the same time.
  4167.  
  4168. 0F03 NET-STATE LD A,R Get a random value.
  4169. 0F05 CP +C0 Allow only the range 192..255.
  4170. 0F07 LD B,A Pass the value to B.
  4171. 0F08 CALL 0F8E,CHK-REST Check network state.
  4172. 0F0B JR C,0F03,NET-STATE Repeat until the network is resting,
  4173. or BREAK pressed.
  4174. 0F0D RET Return when 'ready to claim'.
  4175.  
  4176. THE 'CHECK-RESTING' SUBROUTINE
  4177. This subroutine checks the state of the network and returns with carry reset if it is inactive for a 'sufficient' time \
  4178. determined by the value passed to the B register ((B * 54) - 22) T cycles).
  4179.  
  4180. 0F0E CHK-REST LD A,+7F First check SPACE key.
  4181. 0F10 IN A,(+FE)
  4182. 0F12 RRCA
  4183. 0F13 JR NC,0F4D,E-READ-N Give an error if it is pressed.
  4184. 0F15 MAKESURE PUSH BC Wait 21 T cycles.
  4185. 0F16 POP BC
  4186. 0Fl7 IN A,(+F7) Check network state.
  4187. 0F19 RRCA Only bit 0.
  4188. 0F1A RET C Return if the network is already
  4189. claimed by another Spectrum.
  4190. 0F1B DJNZ 0F15,MAKESURE Repeat the test.
  4191. 0F1D RET Return with carry reset when network
  4192. is resting.
  4193.  
  4194. THE 'WAIT-SCOUT' SUBROUTINE
  4195. This subroutine is used to identify a SCOUT leader from the network. This is done by checking the network line for \
  4196. about 7000 T cycles, to prove whether it is resting. After this, the network is examined until it is active. At this \
  4197. point, the SCOUT is identified. The subroutine returns the carry flag reset if 'time-out' has occurred and no SCOUT \
  4198. has been identified. Remember that there are no 'time-outs' when broadcasting.
  4199.  
  4200. 0F1E WT-SCOUT LD HL,+01C2 Set a counter.
  4201. 0F21 CLAIMED LD B,+80 This constant allows the network to
  4202. be tested for 6890 T cycles.
  4203. 0F23 CALL 0F9E,CHK-REST Check network state.
  4204. 0F26 JR NC,0F35,WT-SYNC Jump for waiting the SCOUT.
  4205. 0F28 DEC HL Loop again if the network is active,
  4206. 0F29 DEC HL until the counter reaches zero.
  4207. 0F2A LD A,H
  4208. 0F2B OR C
  4209. 0F2C JR NZ,0F21,CLAIMED
  4210. 0F2E LD A,(NCIRIS) There is no 'time-out' when
  4211. 0F31 AND A broadcasting.
  4212. 0F32 JR Z,0F21,CLAIMED
  4213. 0F34 RET Return with carry reset to signal
  4214. 'time-out'.
  4215.  
  4216. Now the SCOUT pulse is waited for.
  4217.  
  4218. 0F35 WT-SYNC IN A,(+F7) Read the network line.
  4219. 0F37 RRCA Only bit 0.
  4220. 0F38 JR C,0F56,SCOUT-END Jump if the SCOUT is identified.
  4221. 0F3A CD A,+7F Check SPACE key.
  4222. 0F3C IN A,(+FE)
  4223. 0F3E RRCA
  4224. 0F3F JR NC,0F4O,E-READ-N Give an error if it is pressed.
  4225. 0F41 DEC HL decrease counter.
  4226. 0F42 LD A,H Repeat until it reaches zero.
  4227. 0F43 OR C
  4228. 0F44 JR NZ,0F35,WT-SYNC
  4229. 0F46 CD A,(NCIRIS) There is no 'time-out' when
  4230. 0F49 AND A broadcasting.
  4231. 0F4A JR Z,0F35,WT-SYNC
  4232. 0F4C RET Carry reset signals 'time-out',
  4233. 0F4D E-READ-N EI Enable interrupts.
  4234. 0F4E CALL 0CA9,BORD-REST Restore border colour.
  4235. 0F51 LD (ERR-NR),+14 Give the error 'BREAK into program'.
  4236. 0F55 RST 28,ROMERR
  4237.  
  4238. NOTE: The above routine is a 'duplicate' of BRK-INOUT at 0CB4.
  4239.  
  4240. When the SCOUT has been identifIed, the routine waits until it is finished.
  4241.  
  4242. 0F56 SCOUT-END LD L,+09 Set a counter.
  4243. 0F58 LP-SCOUT DEC L Decrease it.
  4244. 0F59 SCF Return with carry set (to signal
  4245. 0F5A RET Z 'scout identified') when the counter
  4246. reaches zero.
  4247. 0F5B LD B,+0E Wait a while.
  4248. 0F5D DELAY-SC DJNZ 0F5D,DELAY-SC
  4249. 0F5F JR 0F58,LP-SCOUT Go back into the loop,
  4250.  
  4251. THE 'SEND-SCOUT' SUBROUTINE
  4252. This is the opposite of the preceding routine; the SCOUT leader, followed by an 8-bit station number, is sent over the \
  4253. network. After having sent every bit, a test is made to see if the network has the expected state from the current bit \
  4254. value; if any error is found, then the whole procedure is repeated.
  4255.  
  4256. 0F61 SEND-SC CALL 0F03,NET-STATE Wait until the network Is resting.
  4257. 0F64 LD C,+F7 Output port.
  4258. 0F66 LD HL,+0009 H=0 (leader bit value)
  4259. L=9 (bit counter).
  4260. 0F69 LD A,(NTSTAT) Fetch global station number,
  4261. 0F6C LD E,A Pass it to the E register.
  4262. 0F6D IN A,(+F7) Start again if some data is found
  4263. 0F6F RRCA into the network line.
  4264. 0F70 JR C,0F61,SEND-SC
  4265. 0F72 ALL-BITS OUT (C),H Send a bit.
  4266. 0F74 LD D,H Save the bit into D.
  4267. 0F75 LD H,+00 Clear H.
  4268. 0F77 RLC E Rotate 'station no.' left.
  4269. 0F79 RL H Bit 7 of station no. goes into bit
  4270. 0 of H.
  4271. 0F7B LD B,+08 Wait 196 T cycles.
  4272. 0F7D S-SC-DEL DJNZ 0F7D,S-SC-DEL
  4273. 0F7F IN A,(+F7) Read the network.
  4274. 0F81 AND +01 Only bit 0.
  4275. 0F83 CP D Repeat again the procedure if the
  4276. 0F84 JR Z,0F61,SEND-SC network does not have the right state
  4277. from the current bit value.
  4278. 0F86 DEC L Decrease bit counter.
  4279. 0F87 JR NZ,0F72,ALL-BITS Send all bits.
  4280. 0F89 LD A,+01 Make network inactive.
  4281. 0F8B OUT (+F7),A
  4282. 0F8D LD B,+0E Wait 184 T cycles.
  4283. 0F8F END-S-DEL DJNZ 0F8F,END-S-DEL
  4284. 0F91 RET Finished.
  4285.  
  4286. THE 'INPAK' SUBROUTINE
  4287. This basic subroutine is used to receive from the network a block of bytes. On entry. HL must hold the address from \
  4288. which the bytes will be loaded, while E must hold the length of the block. The subroutine returns with the zero flag \
  4289. reset if the network is found inactive and no data has been read. The bits are read every 40 T cycles.
  4290.  
  4291. 0F92 INPAK LD B,+FF Set a counter.
  4292. 0F94 N-ACTIVE IN A,(+F7) Read the network.
  4293. 0F96 RRA Only bit 3.
  4294. 0F97 JR C,0F9D,INPAK-2 Jump if found active.
  4295. 0F99 BJNZ 0F94,N-ACTIVE Otherwise try again.
  4296. 0F9B INC B Return with zero flag reset to
  4297. 0F9C RET indicate 'network inactive'.
  4298.  
  4299. Now the block is received.
  4300.  
  4301. 0F9D INPAK-2 LD B,E B holds the length of the block.
  4302. 0F9E INPAK-L LD E,+80 Set a marker into bit 7.
  4303. 0FAI LD A,+CE Make Wait and CTS having a low level,
  4304. 0FA2 OUT (+EF),A enable network comm.
  4305. 0FA4 NOP Wait 48 T cycles at the start of each
  4306. 0FA5 NOP byte.
  4307. 0FA6 INC IX
  4308. 0FA8 DEC IX
  4309. 0FAA INC IX
  4310. 0FAC DEC IX
  4311. 0FAE UNTIL-MK LD A,+00 Wait 7 T cycles.
  4312. 0FB0 IN A,(+F7) Get a bit into carry
  4313. 0FB2 RRA flag.
  4314. 0FB3 RR E Shift the bit into E.
  4315. 0FB5 JP NC,0FAE,UNTIL-MK Repeat for 8 bits.
  4316. 0FB8 LD (HL),E Store the received byte.
  4317. 0FB9 INC HL Point to next location.
  4318. 0FBA DJNZ 0F9E,INPAK-L Get next byte.
  4319. 0FBC CP A Return with zero flag set to signal
  4320. 0FBD RET 'successfully read'.
  4321.  
  4322. THE 'SEND RESPONSE BYTE' SUBROUTINE
  4323. A 'response byte' is simply a byte +01 that is sent over the network to confirm that some data has been successfully \
  4324. received.
  4325.  
  4326. 0FBE SEND-RESP LD A,+0l This is the response byte.
  4327. 0FC0 LD HL,+5CCD Store it into NTRESP.
  4328. 0FC3 LD (HL),A
  4329. 0FC4 LD E,A A 'single byte' is to be sent.
  4330.  
  4331. The subroutine continues into OUTPAK below.
  4332.  
  4333. THE 'OUTPAK' SUBROUTINE
  4334. This is the opposite to the INPAK subroutine and thus, is used to send over the network a block of bytes. Again, on \
  4335. entry HL must hold the address fro which the block is stored, and E must hold its length. Initially a leader (length \
  4336. 98 T cycles) is sent, followed by each byte, with an initial 'start' period, and then the 8 bits (each 40 T cycles).
  4337.  
  4338. 0FC5 OUTPAK XOR A Begin with a 'start' leader.
  4339. 0FC6 OUT (+F7),A
  4340. 0FC8 LD B,+04 Insert the required delay.
  4341. 0FCA DEL_O-1 DJNZ 0FCA,DEL_O-1
  4342. 0FCC OUTPAK-L LD A,(HL) Get the byte to be sent,
  4343. 0FCD CPL Send the bits inverted.
  4344. 0FCE SCF The start bit is high.
  4345. 0FCF RLA Rotate bit into A.
  4346. 0FD0 LD B,+0A '10' bits to be sent (start, data,
  4347. stop).
  4348. 0FD2 UNT-MARK OUT (+F7),A Send the bit.
  4349. 0FD4 RRA Next bit.
  4350. 0FD5 AND A But clear carry.
  4351. 0FD6 DEC B becrease bit counter.
  4352. 0FD7 LD D,+00 Wait 7 T cycles.
  4353. 0FD9 JP NZ,0FB2,UNT-MARK Loop for all bits.
  4354. 0FDC INC HL Point to next location in the block.
  4355. 0FDD DEC E Decrease 'block length'.
  4356. 0FDE PUSH HL Wait 22 T cycles.
  4357. 0FDF POP HL
  4358. 0FE0 JP NZ,0FCC,OUTPAK-L Loop until all bytes have been sent.
  4359. 0FE3 LD A,+01
  4360. 0FE5 OUT (+F7),A Finally make the network inactive.
  4361. 0FE7 RET Finished.
  4362.  
  4363.  
  4364. The Microdrive routines
  4365.  
  4366. THE 'SET A TEMPORARY "M" CHANNEL' SUBROUTINE
  4367. This very important subroutine sets a temporary "M" channel in the CHANS area; the Microdrive map is created unless it \
  4368. already exists (if another channel refers to the same drive). The subroutine returns with the IX register pointing to \
  4369. the start of the channel, and with the HL register holding a suitable displacement to be eventually inserted in the \
  4370. STRHS area to attach the channel to a stream. Note that the HL' register is corrupted if you call this routine from \
  4371. your own program.
  4372.  
  4373. 0FE8 SET-T-MCH EXX Swap registers.
  4374. 0FE9 LD HL,+0000 Signal 'map to be created'.
  4375. 0FEC EXX Swap registers again.
  4376. 0FED LD IX,(CHANS) Start of channel area.
  4377. 0FF1 LD DE,+0014 Points to the start of the channels
  4378. 0FF4 ADD IX,DE Other than the 'standard' ones.
  4379. 0FF6 CHK-LOOP LD A,(IX+0) Jump forward it the CHANS area is
  4380. 0FF9 CP +80 finished.
  4381. 0FFB JR Z,1034,CHAN-SPC
  4382. 0FFD LD A,(IX+4) Fetch channel specifier.
  4383. 1000 AND +7F Clear bit 7.
  4384. 1002 CP +4D Jump if this is not an "m" channel.
  4385. 1004 JR NZ,102A,NEXT-CHAN
  4386. 1006 LD A,(D-STR1) Fetch drive number.
  4387. 1009 CP (CHDRIV) Jump if this channel uses a different
  4388. l00C JR NZ,102A,NEXT-CHAN drive.
  4389. 100E EXX Swap registers.
  4390. 100F LD L,(CHMAP-lo) Move address of map area into H'L'
  4391. 1012 LD H,(CHMAP-hi)
  4392. 1015 LXX Swap registers again.
  4393. 1016 LD BC,(N-STR1) Length of filename.
  4394. 101A LD HL.(N-STR1+2) Start address of filename.
  4395. 101D CALL 131E,CHK-NAME Check name against 'CHNAME' of this
  4396. channel.
  4397. 1020 JR NZ,102A,NEXT-CHAN Jump if not the same file.
  4398. 1022 BIT 3,(IX+24) This is set with 'write' files.
  4399. 1026 JR Z,102A,NEXT-CHAN Continue with 'read' files.
  4400. 1028 RST 20,SH-ERR Give the 'Reading a 'write' file'
  4401. 1029 DEFB +0D error if the file is already opened
  4402. for writing.
  4403. 102A NEXT-CHAN LD E,(IX+9) Fetch length of channel into the DE
  4404. 102D LD D,(lX+10) register pair.
  4405. 1030 ADD IX,DE Point to the next channel.
  4406. 1032 JR 0FF6,CHK-LOOP Back again.
  4407.  
  4408. Now the space for the new channel is created at the end of the CHANS area.
  4409.  
  4410. 1034 CHAN-SPC LD HL,(PROG) Fetch the start address of the
  4411. 1037 DEC HL channel,
  4412. 1038 PUSH HL Save it.
  4413. 1039 LD BC,+0253 Length is '595' bytes.
  4414. 103C RST 10,CALBAS Call MAKE-ROOM to create the required
  4415. 103D DEFW +1655 space.
  4416. 103E POP DE Restore start address of the channel.
  4417. 1040 PUSH DE
  4418. 1041 LD HL,+13CC Start of "M" channel data.
  4419. 1044 LD BC,+0019 Length of data.
  4420. 1047 LDIR Store data into the channel.
  4421. 1049 LD A,(D-STR1) Fetch drive number.
  4422. 104C LD (CHDRIV),A Initialise CHDRIV.
  4423. 104F LD BC,+0253 Length of channel.
  4424. 1052 PUSH IX Fetch start of channel into HL.
  4425. 1054 POP HL
  4426. 1055 CALL 1691,REST-N-AD Restore start of 'filename' possibly
  4427. moved after the 'insertion' of the
  4428. channel.
  4429. 1058 EX DE,HL The start address of the filename goes
  4430. to HL.
  4431. 1059 LD BC,(N-STR1) Fetch length of filename.
  4432. 105D BIT 7,B Jump if the name does not exist
  4433. 105F JR NZ,106F,TEST-MAP (N-STR1 = +FFFF).
  4434.  
  4435. The channel name is transferred into CHNAME.
  4436.  
  4437. 1061 T-CH-NAME LD A,B The loop continues until 'length'
  4438. 1062 OR C reaches zero.
  4439. 1063 JR Z,106F,TEST-MAP Fetch character of name.
  4440. 1065 LD A,(HL)
  4441. 1066 LD (IX+14),A Store it into CHNAME.
  4442. 1069 INC HL Point to next locations.
  4443. l06A INC IX
  4444. 106C DEC BC Decrease 'length'.
  4445. 106D JR 106l,T-CH-NAME Continue with next character.
  4446.  
  4447. Now the 'map' is created unless it already exists.
  4448.  
  4449. 106F TEST-MAP POP IX Restore start address of channel.
  4450. 1071 EXX Use alternate registers.
  4451. 1072 LD A,H Address of map, or +0000 if the map
  4452. 1073 OR L does not exist.
  4453. 1074 JR NZ,108A,ST-MAP-AD Jump if the map already exists.
  4454. 1076 LD HL,(CHANS) Otherwise the map is to be created.
  4455. 1079 PUSH HL
  4456. 107A DEC HL
  4457. 107B LD BC,+0020 Length of the map is 32 bytes.
  4458. 107E RST 10,CALBAS Call MAKE-ROOM to make the space.
  4459. 107F DEFW +1655
  4460. 1081 POP HL Restore start of map.
  4461. 1082 LD BC,+0020 Restore 'start' of channel.
  4462. 1085 ADD IX,BC
  4463. 1087 CALL 1691,REST-N-AD Restore 'start' of filename.
  4464. 108A ST-MAP-AD LD (CHMAP-lo),L Lastly store the start address
  4465. 108E LD (CHMAP-hi),H of the Microdrive map.
  4466.  
  4467. All bits in the map are made high; then the 'preambles' are collected from the table at +13E5 and stored in the channel.
  4468.  
  4469. 1090 LD A,+FF All bits high.
  4470. 1092 LD B,+20 Length of map.
  4471. l094 FILL-MAP LD (HL),A Store +FF into this location.
  4472. 1095 INC HL Advance the pointer.
  4473. 1096 DJNZ 1094,FILL-MAP Continue for 32 bytes.
  4474. 1098 PUSH IX Pass start of channel to HL.
  4475. 109A POP HL
  4476. 109B LD DE,+001C Make DE register pair point to the
  4477. 109E ADD HL,DE header block preamble area.
  4478. 109F EX DE,HL
  4479. 10A0 LD HL,+13E5 Start of 'preamble' data.
  4480. l0A3 LD BC,+000C Preamble is 12 bytes in length.
  4481. 10A6 LDIR Set-up header preamble.
  4482. 10A8 PUSH IX Pass again 'start' to HL.
  4483. 10AA POP HL
  4484. 10AB LD DE,+0037 Offset for data block preamble.
  4485. 10AE LD BC,+000C Preamble is again 12 bytes.
  4486. 10B1 ADD HL,DE Make DE register pair point to the
  4487. 10B2 EX DE,HL data block preamble.
  4488. 10B3 LD HL,+13E5 Start of 'preamble data'.
  4489. 10B6 LDIR Set-up the data block preamble.
  4490. 10B8 PUSH IX Move 'start' of channel into HL
  4491. 10BA POP HL register pair.
  4492. 10BB LD DE,(CHANS) Calculate the required 'stream
  4493. 10BF OR A offset' into HL.
  4494. 10C0 SBC HL,DE
  4495. 10C2 INC HL
  4496. 10C3 RET Finished.
  4497.  
  4498. THE 'RECLAIM "M" CHANNEL' SUBROUTINE
  4499. This subroutine (also called by using 'hook code' +2C) is used to reclaim the "m" channel pointed by the IX index \
  4500. register. Any stream attached to this channel will be closed, and other 'dynamic' areas updated. The map is also \
  4501. reclaimed, unless it is used by another channel.
  4502.  
  4503. 10C4 DEL-M-BUF LD L,(CHMAP-lo) Fetch address of map into HL.
  4504. 10C7 LD H,(CHMAP-hi)
  4505. 10CA PUSH HL Save it for later.
  4506. 10CB LD A,(CHDRIV) Fetch drive number.
  4507. 10CE PUSH AF Save it for later.
  4508. 10CD PUSH IX Make HL point to the start of
  4509. 10D1 POP HL the channel.
  4510. 10D2 LD BC,+0253 Length of the channel.
  4511. 10D5 RST 10,CALBAS RECLAIM-2 is called to delete
  4512. 10D6 DEFW +19E8 the channel area.
  4513. 10D8 PUSH IX Make HL point again to the start of
  4514. 10DA POP HL the (reclaimed) channel.
  4515. 10DB LD DE,(CHANS) Calculate 'offset' used into STRMS
  4516. 10DF OR A area for the deleted channel,
  4517. 10E0 SBC HL,DE possibly attached to a stream.
  4518. 10E2 INC HL
  4519. l0E3 LD BC,+0253 Amount of bytes moved down.
  4520.  
  4521.  
  4522. 10E6 CALL l35F,REST-STRM Close required streams and update
  4523. data for other streams.
  4524.  
  4525. Look for any channel that uses the same map as that of the channel deleted.
  4526.  
  4527. 10E9 POP AF Restore drive number, and start
  4528. 10EA POP HL address of map.
  4529. 10EB LD B,A Drive number goes into B.
  4530. 10EC LD IX,(CHANS) Start of channel area.
  4531. 10F0 LD DE,+0014 Skip initial 'standard' channels.
  4532. 10F3 ADD IX,DE
  4533. 10F5 TEST-MCHL LD A,(IX+0) Jump if the channel area is finished.
  4534. 10F8 CP +80
  4535. 10FA JR Z,1114,RCLM-MAP
  4536. 10FC LD A,(IX+4) Fetch channel specifier.
  4537. 10FF AND +7F Clear bit 7 (no distinction is made
  4538. between 'temporary' and 'permanent'
  4539. channels).
  4540. 1101 CP +4D Jump if this is not an "m" channel.
  4541. 1103 JR NZ,113A,NXTCHAN
  4542. 1105 LD A,(CHDRIV) Fetch drive number of this channel.
  4543. 1108 CP B If it is the same as that of the
  4544. 1109 RET Z deleted channel, the map is not to
  4545. be reclaimed.
  4546. 110A NXTCHAN LD E,(IX+9) Fetch length of this channel.
  4547. 110D LD B,(IX+10)
  4548. 1110 ADD IX,DE Points to next channel.
  4549. 1112 JR 10F5,TEST-MCHL Back again for next channel.
  4550.  
  4551. If no channel uses the map used by the deleted one, it is to be deleted too.
  4552.  
  4553. 1114 RCLM-HAP LD BC,+0020 Length of the map.
  4554. 1117 PUSH HL Save start of map.
  4555. 1118 PUSH BC Save length of map. Note: this is
  4556. not necessary.
  4557. 1119 RST 10,CALBAS Call RECLAIM-2 to delete the map.
  4558. 111A DEFW +19E8
  4559. 111C POP BC Restore length and start of the
  4560. 111D POP HL deleted map.
  4561. 111E CALL 1391,REST-MAP Update addresses of other maps.
  4562. 1121 RET Finished.
  4563.  
  4564. THE '"M" CHANNEL INPUT' ROUTINE
  4565. The actual 'input' is handled via CALL-INP. The service routine is MCHAN-IN below.
  4566.  
  4567. 1122 M-INPUT LD IX,(CURCHL) First make IX point to start of
  4568. channel.
  4569. 1126 LD HL,+112C Address of MCHAN-IN routine.
  4570. 1129 JP 0CBD,CALL-INP Jump to the control routine.
  4571.  
  4572. THE '"M" CHANNEL INPUT' SERVICE ROUTINE
  4573. Similarly to the "n" input, the "m" input involves the reading of a byte from the data block. When it is empty, a \
  4574. further block is to be received from Microdrive (Provided that the 'current' data block is not the 'end of file' one) \
  4575. before reading the byte.
  4576.  
  4577. 112C MCHAN-IN BIT 0,(CHFLAG) This is reset to indicate a 'read'
  4578. file.
  4579. 1130 JR Z,1134,TEST-M-BF Jump with 'read' file.
  4580.  
  4581. 'Reading a write file'
  4582.  
  4583. 1132 RWF-ERR RST 20,SH-ERR Call the error handling routine.
  4584. 1133 DEFB +0D
  4585.  
  4586. 1134 TEST-M-BF LD E,(CHBYTE-lo) Fetch current byte counter.
  4587. 1137 LD D,(CHBYTE-hi)
  4588. 113A LD L,(RECLEN-lo) Fetch record length.
  4589. 113D LD H,(RECLEN-hi)
  4590. 1140 SCF Include byte to be read.
  4591. 1141 SEC HL,DE Jump if all bytes have been read.
  4592. 1143 JR C,1158,CHK-M-EOF
  4593. 1145 INC DE Include byte to be read in the
  4594. byte counter.
  4595. 1146 LD (CHBYTE-lo),E Store pew byte Counter.
  4596. 1149 LD (CHBYTE-hi),D
  4597. 114C DEC DE Position of character to be read.
  4598. 114D PUSH IX Save start address of channel.
  4599. 114F Abb IX,DE IX now points to 'byte to be
  4600. read - 82'.
  4601. 1151 LD A,(IX+82) Fetch the byte.
  4602. 1154 POP IX Restore start of channel.
  4603. 1156 SCF Signal 'acceptable code'.
  4604. 1157 RET Finished.
  4605.  
  4606. 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 \
  4607. one.
  4608.  
  4609. 1158 CHK-M-EOF BIT 1,(RECFLG) This is set to signal 'EOF'.
  4610. 115C JR Z,1162,NEW-BUFF Jump if not the last block.
  4611. 115E XOR A Otherwise zero and carry flags are
  4612. returned reset to signal EOF.
  4613. 115F ADD A,+0D Returned byte is +0D.
  4614. 1161 RET Finished.
  4615.  
  4616. A new data block is now read from the Microdrive unit.
  4617.  
  4618. 1162 NEW-BUFF LD DE,+0000 The byte counter is cleared.
  4619. 1165 LD (CHBYTE-lo),E
  4620. 1168 LD (CHBYTE-hi),D
  4621. 116B INC (CHREC) Increment record number.
  4622. 116E CALL 1177,GET-RECD Fetch a new data block.
  4623. 1171 XOR A Turn off drive motor.
  4624. 1172 CALL 17F7,SEL-DRIVE
  4625. 1175 JR 1134,TEST-M-BF Now read the byte.
  4626.  
  4627. THE 'GET A RECORD' SUBROUTINE
  4628. This subroutine is used to load a record of a 'PRINT-type file. The number of the wanted record must be stored into \
  4629. CHREC, the drive number into CHDRIV and the filename into CHNAME. If after five passes of the tape the record is not \
  4630. found, or if a checksum error occurs, the error 'File not found' is given.
  4631.  
  4632. 1177 GET-RECD LD A,(CHDRIV) Fetch drive number.
  4633. 117A CALL 17F7,SEL-DRIVE Start drive motor.
  4634. 117D GET-R-2 LD BC,+04FB Initialise SECTOR to 1275 (i.e., at
  4635. 1180 LD (SECTOR),BC least five passes of the tape).
  4636. 1184 GET-R-LP CALL 11A5,G-HD-RC Get header and data block.
  4637. 1187 JR C,119E,NXT-SCT Consider next sector with errors, or
  4638. 1189 JR Z,119E,NXT-SCT if it is unused.
  4639. 118B CD A,(RECNUM) Fetch record number.
  4640. 118E CP (CHREC) Test against CHREC.
  4641. 1191 JR NZ,119E,NXT-SCT Next sector also if this record is
  4642. not the expected one.
  4643. 1193 PUSH IX Fetch base of "m" channel into HL.
  4644. 1195 POP HL
  4645. 1196 LD DE,+0052 Points to the start of the buffer.
  4646. 1199 ADD HL,DE
  4647. 119A CALL 1346,CHKS-BUFF Return if the checksum is correct.
  4648. 119D RET Z
  4649. 119E NXT-SCT CALL 1312,DEC-SECT Decrease SECTOR.
  4650. 11A1 JR NZ,1184,GET-R-LP Continue until five passes of the
  4651. tape have been made.
  4652. 'File not found'
  4653.  
  4654. 11A3 RS-SH2 RST 20,SH-ERE Call the error handling routine.
  4655. 11A4 DEFB +11
  4656.  
  4657. THE 'GET HEADER AND DATA BLOCK' SUBROUTINE
  4658. This subroutine is used to collect from the selected Hicrodrive unit a header followed by its data block. Note that \
  4659. the drive motor is to be turned on before calling G-HD-RC. The flags returned denote the following states:
  4660.  
  4661. - zero set, carry reset The sector is unused.
  4662. - zero reset, carry reset Successful loading.
  4663. - carry set With any error.
  4664.  
  4665. The 'errors' include wrong checksums, and no matching between the wanted filename (CHNAME) and the loaded one (RECNAM).
  4666.  
  4667. 11A5 G-HD-RC CALL 12C4,GET-M-HD2 Fetch the header.
  4668. 11A8 LD DE,+001B Make HL point to RECLCG, i.e.,
  4669. 11AB ADD HL,DE start of record area.
  4670. 11AC CALL 18A9,GET-M-BF Fetch the record.
  4671. 11AF CALL 1341,CHKS-HD-R Calculate record checksum.
  4672. 11B2 JR NZ,11D6,G-REC-ERR Exit if the checksum is wrong.
  4673. 11B4 BIT 0,(RECFLG) This is set to signal a header block.
  4674. 11B8 JR NZ,11D6,G-REC-ERR Exit if a header instead of a data
  4675. block has been fetched.
  4676. 11BA LD A,(RECFLG) Bit 1 of RECFLG and of REGLEN-hi
  4677. 11BD OR (RECLEN-hi) are both reset with 'unused sector'.
  4678. 11C0 AND +02 Take only bit 1.
  4679. 11C2 RET Z Return with unused sectors.
  4680. 11C3 PUSH IX Make HL point to the start of the
  4681. 11C5 POP HL channel.
  4682. 11C6 LD DE,+0047 Points to RECNAM.
  4683. 11C9 ADD HL,DE
  4684. 11CA LD BC,+000A Name is ten characters in length.
  4685. 11CD CALL 131E,CHK-NAME Compare it against CHNAME.
  4686. 11D0 JR NZ,11D6,G-REC-ERR Exit if they do not match.
  4687. 11D2 LD A,+FF Exit with zero and carry flags reset
  4688. 11D4 OR A when successful.
  4689. 11D5 RET
  4690. 11D6 G-REC-ERR SCF Exit with carry set if any error has
  4691. 11D7 RET been detected.
  4692.  
  4693. THE '"M" CHANNEL OUTPUT' ROUTINE
  4694. The routine is very similar to that for the "N" channel output. The byte passed to the accumulator is stored into the \
  4695. 512-byte buffer. When it is filled, the record is written onto the Microdrive cartridge.
  4696.  
  4697. 11D8 MCHAN-OUT LD IX,+FFFA Point to the start of the channel
  4698. 11DC ADD IX,DE (i.e. DE-6, see 00BA).
  4699. 11E1 BIT 0,(CHFLAG) Continue only if this is a 'write'
  4700. 11E2 JR NZ,11E6,NOREAD file.
  4701.  
  4702. 'Writing to a 'read' file'
  4703.  
  4704. 11E4 RST 20,SH-ERR Call the error handling routine.
  4705. 11E5 DEFB +0C
  4706.  
  4707. 11E6 NOREAD LD E,(CHBYTE-lo) Fetch byte counter.
  4708. 11E9 LD D,(CHBYTE-hi)
  4709. 11EC PUSH IX Save start address of channel.
  4710. 11EE ADD IX,DE Now IX points to 'first free byte
  4711. in the buffer'-82.
  4712. 11F0 LD (IX+82),A Store a byte in the buffer.
  4713. 11F3 POP IX Restore start address of channel.
  4714. 11F5 INC DE Points to first 'free byte' in the
  4715. buffer.
  4716. 11F6 LD (CHBYTE-lo),E Update byte counter,
  4717. 11F9 LD (CHBYTE-hi),D
  4718. 11FC BIT 1,D Return if the buffer is not filled
  4719. 11FE RET Z (position 512 has not been reached).
  4720.  
  4721. If the buffer is filled, the routine continues into WR-RECD below.
  4722.  
  4723. THE 'WRITE A RECORD ONTO MICRODRIVE' SUBROUTINE
  4724. This subroutine is also called by using hook code +26. The record held in the "m" channel pointed by the IX register \
  4725. (with name CHNAME and number CHREC), is written into the first unused sector in the cartridge inserted in the drive \
  4726. CHDRIV. Then the appropriate map bit is set and CHREC is automatically incremented. An error is produced if no more \
  4727. space is available on the cartridge to write the record.
  4728.  
  4729. 11FF WR-RECD LD A,(CHDRIV) Fetch drive number.
  4730. 1202 CALL 17F7,SEL-DRIVE Turn on the motor.
  4731. 1205 CALL 120D,WRITE-PRC Write the record.
  4732. 1208 XOR A Turn off the motor.
  4733. 1209 CALL 17F7,SEL-DRIVE
  4734. 120C RET Finished.
  4735. 120D WRITE-PRC CALL 1264,CHK-FULL Check if the cartridge is full,
  4736. 1210 JR NZ,121B,NOFULL and jump if it is not.
  4737. 1212 CALL 10C4,DEL-M-BUF Otherwise reclaim the channel.
  4738. 1215 XOR A Turn off drive motors.
  4739. 1216 CALL 17F7,SEL_DRIVE
  4740.  
  4741. 'Microdrive full'
  4742.  
  4743. 1219 RST 20,SH-ERR Call the error handling routine.
  4744. 121A DEFB +0F
  4745.  
  4746. 121B NOFULL PUSH IX Save base address of channel.
  4747. 121D LD B,+0A Counts ten characters.
  4748. 121F CP-NAME LD A,(IX+14) Copy CHNAME into RECNAM.
  4749. 1222 LD (IX+71),A
  4750. 1225 INC IX
  4751. 1227 DJNZ 121F,CP-NAME
  4752. 1229 POP IX Restore start of channel.
  4753. 122B LD C,(CHBYTE-lo) Copy CHBYTE into RECLEN.
  4754. 122E CD (RECLEN-lo),C
  4755. 1231 LD A,(CHBYTE-hi)
  4756. 1234 LD (RECLEN-hi),A
  4757. 1237 LD A,(CHREC) Copy CHREC into RECNUM.
  4758. l23A LD (RECNUM),A
  4759. 123D PUSH IX Make HL point to the start of the data
  4760. 123F POP HL block workspace, i.e. RECFLG.
  4761. 1240 LD DE,+0043
  4762. 1243 ADD HL,DE
  4763. 1244 CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
  4764. 1247 LD DE,+000F Hake HL point to the start of the
  4765. 124A ADD HL,DE 512-byte buffer.
  4766. 124B CALL 1346,CHKS-BUFF Calculate DCHK checksum.
  4767. 124E PUSH IX Three useless instructions.
  4768. 1250 POP HL
  4769. 1251 LD DE,+0047
  4770. 1254 CALL 1275,SEND-BLK Send the record to Microdrive.
  4771. 1257 LD DE,+0000 Clear CHBYTE.
  4772. 125A LD (CHBYTE-lo),E
  4773. 125D LD (CHBYTE-hi),D
  4774. 1260 INC (CHREC) Finally increment record number.
  4775. 1263 RET Finished.
  4776.  
  4777. THE 'CHK-FULL' SUBROUTINE
  4778. This subroutine is used to check whether the currently used Microdrive unit contains a full cartridge, with no 'free \
  4779. tot use' sectors. The zero flag is returned set if the cartridge is full (i.e. if all map bits are set).
  4780.  
  4781. 1264 CHK-FULL LD L,(CHMAP-lo) Fetch address of the map.
  4782. 1267 LD H,(CHMAP-hi)
  4783. i26A LD B,+20 Length of the map.
  4784. 126C NXT-B-MAP LD A,(HL) Fetch a byte.
  4785. 126D CP +FF Exit with zero flag reset if not all
  4786. 126F RET NZ bits are set.
  4787. 1273 INC HL Point to the next byte,
  4788. 1271 DJNZ 126C,NXT-B-MAP Loop for all bytes.
  4789. 1273 XOR A Return with zero flag set to signal
  4790. 1274 RET that the cartridge is full.
  4791.  
  4792. TIlE 'SEND-BLK' SUBROUTINE
  4793. The following subroutine fetches the first 'free' header and then writes the
  4794. buffer into the sector, provided that the cartridge is not write-protected. Finally the map bit is set.
  4795.  
  4796. 1275 SEND-BLK PUSH IX Make HL point to the data block
  4797. 1277 POP HL preamble.
  4798. 1278 LD DE,+0037
  4799. 127B ADD HL,BE
  4800. l27C PUSH HL Save this address.
  4801. 127D FAILED CALL 12C4,GET-M-HD2 Fetch the first header.
  4802. 1280 CALL 12DF,CHECK-MAP Check map bit for this header.
  4803. 1283 JR NZ,127D,FAILED Continue if the sector is not 'free
  4804. for use'.
  4805. 1285 EX (SP),HL Now (SP) holds the map bit address;
  4806. and HL the start of the data block
  4807. preamble.
  4808. 1286 PUSH BC Save map bit position.
  4809. 1287 IN A,(+EF) Jump if the write-protect tab is
  4810. 1289 AND +01 present.
  4811. 128B JR NZ,128F,NO-PRT
  4812.  
  4813. 'Drive 'write' protected'
  4814.  
  4815. 128D RST 20,SH-ERR Call the error handling routine.
  4816. 128E DEFB +0E
  4817.  
  4818. 128F NO-PRT LD A,+E6 Start the writing process.
  4819. 1291 OUT (+EF),A
  4820. 1293 LD BC,+0168 Wait until the first gap is finished.
  4821. 1296 CALL 18FA,DELAY-BC
  4822. 1299 CALL 1878,OUT-M-BUF Write preamble and data block.
  4823. 129C LD A,+EE Send a signal when finished.
  4824. 129E OUT (+EF),A
  4825. 12A0 POP BC Restore map bit position.
  4826. 12A1 POP HL Restore map bit address.
  4827. 12A2 LD A,B Set the required map bit.
  4828. 12A3 OR (HL)
  4829. 12A4 LD (HL),A
  4830. 12A5 RET Finished.
  4831.  
  4832. THE 'CLOSE FILE' SUBROUTINE
  4833. This subroutine CLOSEs a 'PRINT-type' "m" channel. If the channel is used for reading, then it is reclaimed; but if it \
  4834. is used for writing, any unsent data in the buffer is written onto the Microdrive cartridge before reclaiming the \
  4835. channel. The entry point CLOSE-M is used when the start address of the channel is held in the HL register pair, while \
  4836. CLOSE-M2 (also used by 'hook code' +23) is used when that address is held in the IX index register.
  4837.  
  4838. 12A6 CLOSE-M PUSH HL Make IX register point to the start
  4839. 12A7 POP IX of the channel.
  4840. 12A9 CLOSE-M2 BIT 0,(CHFLAG) Jump forward when 'reading'.
  4841. 12AD JR Z,12B6,NOEMP
  4842. 12AF SET 1,(RECFLG) Otherwise signal 'EOF' record,
  4843. 12B3 CALL 11FF,WR-RECD and write it onto drive.
  4844. 1236 NOEMP XOR A Switch off motor.
  4845. 1237 CALL 17F7,SEL-DRIVE
  4846. 12BA CALL 10C4,DEL-M-BUF Reclaim the channel.
  4847. 12BD RET Finished.
  4848.  
  4849. THE 'MAIN ERROR RESTART' EMULATION ROUTINE
  4850. This routine, called in the format 'CALL ERR-RS / DEFB nn' emulates the sequence 'RST 8 / DEFB nn' that is used (when \
  4851. the main ROM is paged in) to give an error report. ERR-RS is never called from the shadow ROM code.
  4852.  
  4853. 12BE ERR-RS POP HL Fetch return address (points to the
  4854. error code).
  4855. 12BF LD A,(HL) Fetch error code.
  4856. 12C0 LD (ERR-NR),A Store it.
  4857. 12C3 RST 28,ROMERR Give the error report.
  4858.  
  4859. THE 'FETCH HEADER FROM HICRODRIVE' SUBROUTINE
  4860. This subroutine is used to fetch a header from the current Microdrive unit (whose motor must be turned on). The header \
  4861. is loaded into HDFLG...HDCHK. The procedure is repeated unless the checksum is correct.
  4862.  
  4863. 12C4 GET-M-HD2 PUSH IX Make HL point to MDFLAG, i.e. location
  4864. 12C6 POP HL from which the header will be loaded.
  4865. 12C7 LD DE,+0028
  4866. 12CA ADD HL,DE
  4867. 12CB CALL 18A3,GET-M-HD Fetch the header.
  4868. 12CE CALL 1341,CHKS-HD-R Calculate checksum.
  4869. 12D1 JR NZ,12C4,GET-M-HD2 Repeat if it does not match with the
  4870. 'old' checksum.
  4871. 12D3 BIT 0,(HDFLAG) Repeat if a record descriptor has
  4872. 12D7 JR Z,12C4,GET-M-HD2 been loaded instead of a header.
  4873. 12D9 RET Finished.
  4874.  
  4875. THE 'CHECK MAP BIT STATE' SUBROUTINE
  4876. The bit correspondent to a given sector in the microdrive map is checked. The zero flag is returned set if the bit was \
  4877. reset, and vice-versa. Also the B register will hold, on return, a bit set in the position of the map bit; HL will \
  4878. hold the address of that map bit. The entry point is CHK-MAP-2 when the sector number has to be collected from RECNUM, \
  4879. or CHECK-MAP if from HDNUMB.
  4880.  
  4881. 12DA CHK-KAP-2 CD E,(RECNUM) Fetch sector number.
  4882. 12DD JR 12E2,ENTRY Jump forward.
  4883. 12E1 CHECK-MAP LD E,(HDNUMB) Fetch sector number.
  4884. 12E2 ENTRY LD L,(CHMAP-lo) Fetch map start address.
  4885. 12E5 LD H,(CHMAP-hi)
  4886. 12E8 ENTRY-2 XOR A Clear D register.
  4887. 12E9 LD D,A
  4888. 12EA LD A,E Move sector number to A.
  4889. 12EB AND +07 Only 3 less significant bits,
  4890. (i.e. 'bit position').
  4891. 12ED SRL E Shift out the 'position' from E.
  4892. 12EF SRL E
  4893. 12F1 SRL E
  4894. 12F3 ADD HL,DE Calculate map bit address.
  4895. 12F4 LD B,A Pass 'position' to B.
  4896. 12F5 INC B Range is now 1..8.
  4897. 12F6 XOR A Clear A register.
  4898. 12F7 SCF Set carry flag.
  4899. 12F8 ROTATE RLA Set a bit in the correct position.
  4900. 12F9 DJNZ 12F8,ROTATE
  4901. 12FB LD B,A Exit with B holding that bit.
  4902. 12FC AND (HL) Set zero flag as required.
  4903. 12FD RET Finished.
  4904.  
  4905. THE 'RESET BIT IN MAP AREA' SUBROUTINE
  4906. This subroutine is used to reset the bit in the map area corresponding to the sector HDNUMB.
  4907.  
  4908. 12FE RES-B-MAP CALL 12DF,CHECK-MAP Set B and HL registers with position
  4909. and map address.
  4910. 1301 LD A,B Pass bit to be reset to A.
  4911. 1302 CPL Reset only that bit and
  4912. 1303 AND (HL) leave other bits unchanged.
  4913. 1304 LD (HL),A Store new map byte.
  4914. 1305 RET Finished.
  4915.  
  4916. THE 'CHECK "PSEUDO-MAP" BIT STATE' SUBROUTINE
  4917. This subroutine is apparently equal to the CHECK-MAP subroutine at 12DA, however it does not refer to the standard \
  4918. 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 \
  4919. to mark the sectors to be erased,
  4920.  
  4921. 1306 TEST-PMAP PUSH IX Make HL point to the start of the
  4922. 1308 POP HL buffer. I.e. to the start of
  4923. 1309 LD DE,+0052 the 'pseudo-map' area.
  4924. 130C ADD HL,DE
  4925. 130D LD E,(HDNUMB) Fetch sector number.
  4926. 1310 JR 12E8,ENTRY-2 Continue into CHECK-MAP.
  4927.  
  4928. THE 'DECREASE SECTOR NUMBER' SUBROUTINE
  4929. This short subroutine is frequently called to decrease the content of the system variable SECTOR, used to count a \
  4930. given number of sectors during microdrive operations. The zero flag is returned set when SECTOR reaches zero.
  4931.  
  4932. 1312 DEC-SECT LD BC,(SECTOR) Decrease (SECTOR).
  4933. 1316 DEC BC
  4934. 1317 LD (SECTOR),BC
  4935. 131B LD A,B Set zero flag if SECTOR has reached
  4936. 131C OR C zero.
  4937. 131D RET Finished.
  4938.  
  4939. THE 'CHECK-NAME' SUBROUTINE
  4940. Whenever a 'filename' is to be compared against the channel name CHNAME, this subroutine is called. On entry, HL must \
  4941. point to the filename to be compared, while C must contain its length. If the comparison is successful, the zero flag \
  4942. is returned set.
  4943.  
  4944. 131E CHK-NAME PUSH IX Save start of channel.
  4945. 1320 LD B,+0A Length of CHNAME.
  4946. 1322 ALL-CHARS LD A,(HL) Fetch a byte from name.
  4947. 1323 CP (IX+14) Compare it against CHNAME.
  4948. 1326 JR NZ,133E,CKNAM-END Jump if it does not match.
  4949. 1328 INC HL Point to next character.
  4950. 1329 INC IX
  4951. 132B DEC B Decrease 'lengths'.
  4952. 132C DEC C
  4953. 132D JR NZ,1322,ALL-CHARS Continue until the length of the name
  4954. reaches zero.
  4955. 132F LD A,B CHNAME remaining length.
  4956. 1330 OR A Exit if successful (CHNAME length has
  4957. 1331 JR Z,133E,CKNAM-END reached zero).
  4958. 1333 ALLCHR-2 LD A,(IX+14) Otherwise check that the following
  4959. 1336 CP +20 characters of CHNAME are spaces.
  4960. 1338 JR NZ,133E,CKNAM-END Signal 'unsuccessful' if not spaces.
  4961. 133A INC IX Continue until the whole CHNAME has
  4962. 133C DJNZ 1333,ALCCHR-2 been examined.
  4963. 133E CKNAM-END POP IX Restore channel start address.
  4964. 1340 RET Finished.
  4965.  
  4966. THE 'CALCULATE/COMPARE CHECKSUMS' ROUTINE
  4967. This routine is used to calculate HDCHK, DESCHK and DCHK checksums, or to compare the previous checksum against the \
  4968. current one; the zero flag is returned set if the checksums match. The entry point is CHKS-HD-R for HDCHK or DESCHK, \
  4969. or CHKS-BUFF for DCHK checksum. In both cases HL must contain on entry the start address of the block for which the \
  4970. checksum is to be obtained.
  4971.  
  4972. 1341 CHKS-HD-R LD BC,+000E The block length.
  4973. 1344 JR 1349,CHKS-ALL Skip next instruction.
  4974. 1346 CHKS-BUFF LD BC,+0200 The block length.
  4975. 1349 CHKS-ALL PUSH HL Save the start address.
  4976. 134A LD E,+00 Start with E cleared.
  4977. 134C NXT-BYTE LD A,E Add the current byte to the
  4978. 134D ADD A,(HL) previous sum.
  4979. 134E INC HL Point to next location.
  4980. 134F ADC A,+01 Include also the carry.
  4981. 1351 JR Z,1354,STCHK Jump when A reaches zero.
  4982. 1353 DEC A Otherwise balance the ADD above.
  4983. 1354 STCHK LD E,A Update sum.
  4984. 1355 DEC BC Decrement counter.
  4985. 1356 LD A,B Repeat until the counter reaches 0.
  4986. 1357 OR C
  4987. 1358 JR NZ,134C,NXT-BYTE
  4988. 135A LD A,E Move checksum into A.
  4989. 135B CP (HL) Compare with previous checksum.
  4990. 135C LD (HL),A Store new checksum.
  4991. 135D POP HL Restore start address.
  4992. 135E RET Finished.
  4993.  
  4994. THE 'RESTORE STREAM DATA' SUBROUTINE
  4995. This subroutine is entered with BC holding the length of a reclaimed channel, and HL holding the 'stream displacement' \
  4996. for that channel, The stream that refers to this displacement (i.e. the stream attached to the reclaimed channel) is \
  4997. closed. The other stream displacements are updated if they refer to channels moved down after the reclaiming.
  4998.  
  4999. 135F REST-STRM PUSH HL Save stream displacement.
  5000. 1360 LD A,+10 Counts 16 streams.
  5001. 1362 LD HL,+5C16 Start with STRMS-0 address.
  5002. 1365 NXT-STRM LD (X-PTR),HL Save current address into X-PTR.
  5003. 1368 LD E,(HL) Fetch stream displacement for the
  5004. 1369 INC HL current stream.
  5005. 136A LD D,(HL)
  5006. 136B POP HL Restore displacement of stream to be
  5007. 136C PUSH HL closed.
  5008. 136D OR A Clear carry.
  5009. 136E SBC HL,DE Jump if this is not the stream to be
  5010. 1370 JR NZ,1377,NOTRIGHT closed.
  5011. 1372 LD DE,+0000 Close the stream by storing a
  5012. 1375 JR 137E,STO-DISP displacement = 0.
  5013. 1377 NOTRIGHT JR NC,1384,UPD-POINT Jump if the stream data does not need
  5014. to be updated.
  5015. 1379 EX DE,HL HL holds the current displacement.
  5016. 137A OR A Clear carry.
  5017. 137B SBC HL,BC Obtain new displacement.
  5018. 137D EX DE,HL Move it into DE.
  5019. 137E STO-DISP LD HL,(X-PTR) Store the new displacement for
  5020. 1381 LD (HL),E the current stream.
  5021. 1382 INC HL
  5022. 1383 LD (HL),D
  5023. 1384 UPD-POINT LD HL,(X-PTR) Fetch pointer of current stream data.
  5024. 1387 INC HL Advance to data for next stream.
  5025. 1388 INC HL
  5026. 1389 DEC A Jump back until all 16 streams have
  5027. 138A JR NZ,1365,NXT-STRM been examined.
  5028. 138C LD (X-PTR-lo),A Clear X-PTR.
  5029. 138F POP HL Restore displacement.
  5030. 1390 RET Finished.
  5031.  
  5032. THE 'RESTORE MAP ADDRESSES' SUBROUTINE
  5033. When a map has been deleted, the addresses of the other 'higher' maps have to be updated. The 'REST-MAP' subroutine \
  5034. does this. HL should hold on entry the address of the deleted map.
  5035.  
  5036. 1391 REST-MAP LD BC,+0020 Length of map.
  5037. 1394 LD IX,(CHANS) Point to the first channel other than
  5038. 1398 LD DE,+0014 'standard' one.
  5039. 139B ADD IX,DE
  5040. 139D LCHAN LD A,(IX+0) Return if the CHANS area is finished.
  5041. 13A0 CP +80
  5042. 13A2 RET Z
  5043. 13A3 PUSH HL Save 'start' of map.
  5044. 13A4 LD A,(IX+4) Fetch channel specifier.
  5045. 13A7 AND +7F No distinction between 'temporary'
  5046. and 'permanent' channels is made.
  5047. 13A9 CP +4D Jump if this is not an "m" channel.
  5048. 13AB JR NZ,13C1,LPEND
  5049. 13AD LD E,(CHMAP-lo) Fetch address of map.
  5050. 13B0 LD D,(CHMAP-hi)
  5051. 13B3 SBC HL,DE Jump if this map has not been moved.
  5052. 13B5 JR NC,13C1,LPEND
  5053. 13B7 EX DE,HL HL = old map address.
  5054. 13B8 OR A Clear carry.
  5055. 13B9 SBC HL,BC Calculate actual start address and
  5056. 13BB LD (CHMAP-lo),L store it.
  5057. 13BE LD (CMMAP-hi),H
  5058. 13C1 LPEND POP HL Restore 'start' of deleted map.
  5059. 13C2 LD E,(IX+9) Fetch channel length.
  5060. 13C5 LD D,(IX+10)
  5061. 13C8 ADD IX,DE Point to next channel.
  5062. 13CA JR 139D,LCHAN Loop again.
  5063.  
  5064. THE '"M" CHANNEL DATA' TABLE
  5065. The '25' bytes that compose the initial part of an "M" channel are as follows:
  5066.  
  5067. 13CC DEFW +0008 Main ROM 'output' routine.
  5068. 13CE DEFW +0008 Main ROM 'input' routine.
  5069. 13D0 DEFB +CD "M"+80H (channel specifier).
  5070. 13D1 DEFW +11D8 Shadow ROM 'output' routine.
  5071. 13D3 DEFW +1122 Shadow ROM 'input' routine.
  5072. 13D5 DEFW +0253 Channel length.
  5073. 13D7 DEFW +0000 Default for CHBYTE.
  5074. 13D9 DEFB +00 Default for CHREC.
  5075. 13DA DEFM " (10 spc) " Default for CHNAME.
  5076. 13E4 DEFB +FF Default for CHFLAG ('write' channel).
  5077.  
  5078. THE 'PREAMBLE DATA' TABLE
  5079. The header and the data block preambles are made by the following bytes:
  5080.  
  5081. 13E5 DEFB +00,+00,+00
  5082. 13E8 DEFB +00,+00,+00
  5083. 13EB DEFB +00,+00,+00
  5084. 13EE DEFB +00,+FF,+FF
  5085.  
  5086. Each preamble is used to fetch the start of a block of data when reading from the Microdrive unit.
  5087.  
  5088. THE 'MOVE' COMMAND SUBROUTINE
  5089. The actual MOVE command involves the 'reading' of a byte from the required stream or channel, and then the 'writing' \
  5090. of that byte onto the 2nd stream or channel. The operation is repeated until the 'end of file' condition occurs. Note \
  5091. 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 \
  5092. reported.
  5093.  
  5094. 13F1 MOVE SET 4,(FLAGS3) See comment above.
  5095. 13F5 CALL 1455,OP-STRM Open the first channel.
  5096. 13F8 LD HL,(CHANS) Store current value 0f CHANS.
  5097.  
  5098. 13FB PUSH BC
  5099. 13FC CALL 14C7,EX-DSTR2 Exchange D-STR areas.
  5100. 13FF CALL 1455,OP-STRM Open second channel.
  5101. 1402 CALL 14C7,EX-DSTR2 Exchange D-STR areas again.
  5102. 1405 POP DE Initial start of CHANS.
  5103. 1406 LD HL,(CHANS) Current start of CHANS.
  5104. 1409 OR A Clear carry for a true subtraction.
  5105. 140A SBC HL,DE HL holds the length of the space
  5106. inserted after the 2nd opening
  5107. (possible maps inserted).
  5108. 140C LD DE,(N-STR1) Fetch start of first channel.
  5109. 1410 ADD HL,DE Calculate 'current' start.
  5110. 1411 LD (N-STR1),HL Store it.
  5111. 1414 M-AGAIN LD HL,(N-STR1) Make 'current' the 1st channel
  5112. 1417 LD (CURCHL),HL
  5113. 141A I-AGAIN RST 10,CAL8AS Call INPUT-A in the main ROM to
  5114. 141B DEFW +15E6 read a byte.
  5115. 141D JR C,1423,MOVE-OUT Jump with acceptable codes.
  5116. 141F JR Z,141A,I-AGAIN Repeat if no data has been read.
  5117. 1421 JR 142E,MOVE-EOF Jump when EOF has been reached.
  5118. 1423 MOVE-OUT LD HL,(N-STR2) Make 'current' the 2nd channel.
  5119. 1426 LD (CURCHL),HL
  5120. 1429 RST 10,CALBAS Use main ROM 'PRINT-A' restart to
  5121. 142A DEFW +0010 send the byte through the 2nd channel
  5122. 142C JR 1414,M-AGAIN Repeat the whole procedure.
  5123. 142E MOVE-EOF RES 4,(FLAGS3) Signal that the MOVE command is
  5124. finished.
  5125. 1432 LD HL,(CHANS) Store current CHANS address.
  5126. 1435 PUSH HL
  5127. 1436 CALL 14C7,EX-DSTR2 Exchange D-STR areas,
  5128. 1439 CALL 14A4,CL-CHAN Close the second channel.
  5129. 143C CALL 14C7,EX-DSTR2 Exchange D-STR areas again.
  5130. 143F POP DE Restore initial address of CHANS.
  5131. 1440 LD HL,(CHANS) Fetch current CHANS address.
  5132. 1443 OR A Calculate the amount of bytes
  5133. 1444 SBC HL,DE reclaimed after the deletion of the
  5134. second channel.
  5135. 1446 LD DE,(N-STR1) Calculate the new start address of
  5136. 144A ADD HL,DE first channel.
  5137. 144B LD (N-STR1),HL
  5138. 144E CALL 14A4,CL-CHAN Close the first channel.
  5139. 1451 CALL 17B9,RCL-T-CH Reclaim temporary channels and switch
  5140. off drive motors.
  5141. 1454 RET Finished.
  5142.  
  5143. THE 'USE STREAM OR TEMPORARY CHANNEL' SUBROUTINE
  5144. This subroutine is used from the MOVE command routine above to fetch the start address of the channel attached to a \
  5145. stream (if the command is of the type 'MOVE #N TO ...' ), or to open a temporary channel and fetch its start address \
  5146. if the
  5147. command is in the form 'MOVE "S";N (;"NAME") TO ...'. In both cases the start address of the channel is returned into \
  5148. N-STR1.
  5149.  
  5150. 1455 OP-STRM LD A,(S-STR1) Fetch stream number.
  5151. 1458 INC A If stream no. is +FF (i.e.
  5152. 1459 JR Z,1466,OP-CHAN nonexistent), jump to open a
  5153. temporary channel.
  5154. 145B DEC A A holds the stream number.
  5155. 145C RST 10,CAL8AS Call 'CHAN-OPEN' to select the stream.
  5156. 145D DEFW +1601
  5157. 145F LD HL,(CURCHL) Fetch channel start address.
  5158. 1462 LD (N-STR1),HL Store it.
  5159. 1465 RET Finished.
  5160. 1466 OP-CHAN LB A,(L-STR1) Fetch channel specifier
  5161. 1469 CP +4D Jump if not "m".
  5162. 146B JR NZ,147F,CHECK-N
  5163. 146D CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
  5164. 1470 XOR A Switch off drive motor.
  5165. 1471 CALL 17F7,SEL-DRIVE
  5166. 1474 LD (N-STR1),IX Store channel start address.
  5167. 1478 BIT 2,(RECFLG) Allow only PRINT-type files with the
  5168. 147C RET Z MOVE command.
  5169.  
  5170. 'Wrong file type'
  5171.  
  5172. 147D RST 28,SH-ERR Call the error handling routine.
  5173. 147E DEFB +16
  5174.  
  5175. 147F CHECK-N CP +4E Jump if not an "n" channel.
  5176. 1481 JR NZ,148B,CHECK-R
  5177. 1483 CALL 0EA9,OP-TEMP-N Open a temporary "n" channel.
  5178. 1486 LD (N-STR1),IX Store channel start address,
  5179. 148A RET Finished.
  5180. 148B CHECK-R CP +54 Jump with "t" channel.
  5181. 148D JR Z,1495,USE-R
  5182. 148F CP +42 Jump with "b" channel.
  5183. 1491 JR Z,1495,USE-R
  5184.  
  5185. 'Nonsense in BASIC'
  5186.  
  5187. 1493 RST 28,SH-ERR Call the error handling routine.
  5188. 1494 DEFB +00
  5189.  
  5190. 1495 USE-R CALL 0B13,OP-RS-CH Open a permanent "b" or "t" channel.
  5191. 1498 LD (N-STR1),DE Store channel start address.
  5192. 149C PUSH DE Make IX point to start of channel.
  5193. 149D POP IX
  5194. 149F SET 7,(IX+4) Make the channel 'temporary'.
  5195. 14A3 RET Finished.
  5196.  
  5197. THE 'CLOSE "MOVE" CHANNEL' SUBROUTINE
  5198. This is the opposite subroutine of the preceding one, and is used to CLOSE the channel used by the MOVE command \
  5199. routine. If S-STR1 denotes that a stream was used, no action is made.
  5200.  
  5201. 14A4 CL-CHAN LD A,(S-STR1) Fetch stream number.
  5202. 14A7 INC A Return if a stream has been used
  5203. (i.e. S-STR1<>+FF).
  5204. 14A8 RET NZ
  5205. 14A9 LD A,(L-STR1) Fetch channel specifier.
  5206. 14AC CP +4D Jump if not "m" channel.
  5207. 14AE JR NZ,14B8,CL-CHK-N
  5208. 14B0 LD IX,(N-STR1) Fetch channel start address.
  5209. 14B4 CALL 12A9,CLOSE-M2 Close the "m" channel.
  5210. 14B7 RET Finished.
  5211. 14B8 CL-CHK-N CP +4E Return with "b" and "t" channels.
  5212. 14BA RET NZ
  5213. 14BB LD IX,(N-STR1) Fetch channel start addreus.
  5214. 14BF LD (CURCHL),IX Make the "n" channel the 'current' one
  5215. 14C3 CALL 0EF5,SEND-NEOF Close the "n" channel.
  5216. 14C6 RET Finished.
  5217.  
  5218.  
  5219.  
  5220. THE 'EXCHANGE DSTR1 AND DSTR2 CONTENTS' SUBROUTINE
  5221. This subroutine performs exactly the same task as the EX-D-STR subroutine at 059F, even if it is slightly different. \
  5222. The D-STR1 area is copied into the
  5223. D-STR2 one, and vice-versa.
  5224.  
  5225. 14C7 EX-DSTR2 LD DE,+5CD6 Start of 1st area.
  5226. 14CA LD HL,+5CDE Start of 2nd area.
  5227. 14CD LD B,+08 Length of both areas.
  5228. 14CF ALL-BYT-2 LD A,(DE) Fetch byte from D-STR1.
  5229. 14D0 LD C,(HL) Fetch byte from D-STR2.
  5230. 14D1 EX DE,HL Exchange pointers.
  5231. 14D2 LD (HL),C Store into D-STR1.
  5232. 14D3 LD (DE),A Store into D-STR2.
  5233. 14D4 EX DE,HL Exchange pointers again.
  5234. 14D5 INC HL Advance pointers.
  5235. 14D6 INC DE
  5236. 14D7 DJNZ 14CE,ALL-BYT-2 Continue for all bytes in the
  5237. D-STR areas.
  5238. 14D9 RET Finished.
  5239.  
  5240. THE 'SAVE DATA BLOCK INTO MICRODRIVE' SUBROUTINE
  5241. This is the actual SAVE command referred to the Microdrive (see 082F). The '9' bytes that form the 'header \
  5242. information' are collected from the HD variables and passed to the channel data block; then the memory block, whose \
  5243. 'start' and 'length' are held in the system variables HD-0D and HD-0B, is written onto the Microdrive (provided that \
  5244. there is sufficient space available on cartridge).
  5245.  
  5246. 14DA SA-DRIVE LD A,(D-STR1) Fetch drive number.
  5247. 14DD CALL 17F7,SEL-DRIVE Turn on drive motor.
  5248. 14E0 IN A,(+EF) Continue only if the write-protect
  5249. 14E2 AND +01 tab was not removed.
  5250. 14E4 JR NZ,14E8,START-SA
  5251.  
  5252. 'Drive 'write' protected'
  5253.  
  5254. 14E6 RST 20,SH-ERR Call the error handling
  5255. 14E7 DEFB +0E routine.
  5256.  
  5257. 14E8 START-SA LD HL,(HD-0D) Fetch 'start' of data.
  5258. 14EB LD (5CE4),HL Store it into (N-STR2+2).
  5259. 14EE CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
  5260. 14F1 BIT 0,(CHFLAG) Continue only if this file does
  5261. 14F5 JR NZ,14FC,NEW-NAME not already exist in the cartridge.
  5262. l4F7 CALL 12A9,CLOSE-M2 Close the channel and report the error
  5263.  
  5264. 'Writing to a 'read' file'
  5265.  
  5266. 14FA RST 20,SH-ERR Call the error handling routine.
  5267. 14FB DEFB +0C
  5268.  
  5269. 14FC NEW-NAME SET 2,(RECFLG) Signal 'not a PRINT file'.
  5270. 1500 LD A,(CHDRIV) Fetch drive number.
  5271. 1503 CALL 17E7,SEL-DRIVE Start motor.
  5272. 1506 PUSH IX Make HL point to the buffer.
  5273. 1508 POP HL
  5274. 1509 LD DE,+0052
  5275. 150C ADD HL,DE
  5276. 150D EX DE,HL
  5277.  
  5278.  
  5279. 150E LD HL,+5CE6 Address of HD-00.
  5280. 1511 LD BC,+0009 Length of HD variables.
  5281. 1514 LD (CHBYTE-lo),C Current position is '9'.
  5282. 1517 LDIR Store header informations.
  5283. 1519 PUSH DbE Save address of 'first free byte'.
  5284. 151A LD HL,+0009 Add 9 to 'data length'.
  5285. 151D LD BC,(HD-0B)
  5286. 1521 ADD HL,BC
  5287. 1522 SRL H H holds INT(length/5l2), i.e. number
  5288. of sectors required.
  5289. 1524 INC H Allow for a further EOF sector.
  5290. 1525 PUSH HL Save H register.
  5291. 1526 CALL 1D38,FREESECT Calculate into E the number of 'free'
  5292. sectors.
  5293. 1529 POP HL Restore H.
  5294. 152A LD A,E Jump if there are sufficient
  5295. 152B CP H 'free' sectors.
  5296. 152D JR NC,1530,SA-DRI-2
  5297.  
  5298. 'Microdrive full'
  5299.  
  5300. 152E RST 20,SH-ERR Call the error handling routine.
  5301. 152F DEFB +0F
  5302.  
  5303. 1530 SA-BRI-2 POP DE Restore address of 'first free byte'
  5304. in the buffer.
  5305. 1531 LD HL,(5CE4) Fetch 'start' of block from
  5306. (N-STR2+2) (see 14EB).
  5307. 1534 LD BC,(HD-0B) Fetch 'length' of data.
  5308. 1538 SA-DRI-3 LD A,B Jump when it reaches zero.
  5309. 1539 OR C
  5310. 153A JR Z,155E,SA-DRI-4
  5311. 153D LD A,(CHBYTE-hi) Jump until the buffer space has been
  5312. 151E CP +02 filled.
  5313. 1541 JR NZ,1552,SA-DRI-WR
  5314. 1543 PUSH HL Save registers.
  5315. 1544 PUSH BC
  5316. 1545 CALL 123D,WRITE-PRC Write this data block onto cartridge.
  5317. 1548 POP BC Restore counter.
  5318. 1549 PUSH IX Make DE point to the start of the
  5319. 154B POP HL buffer.
  5320. 154C LD DE,+0052
  5321. 154E ADD HL,DE
  5322. 1550 EX DE,HL
  5323. 1551 POP HL Restore pointer.
  5324. 1552 SA-DRI-WR LDI Move a byte to the buffer.
  5325. 1554 INC (CHBYTE-lo) Increment CHBYTE and go back into the
  5326. 1557 JR NZ,SA-DRI-3 loop.
  5327. 1559 INC (CHBYTE-hi)
  5328. 155C JR 1538,SA-DRI-3
  5329. 155E SA-DRI-4 SET 1,(RECFLG) Mark as 'EOF' record.
  5330. 1562 CALL 120D,WRITE-PRC Write the last data block.
  5331. 1565 LD A,(COPIES) Decrease COPIES and exit if it has
  5332. 1568 DEC A reached zero.
  5333. 1569 JR Z,1579,END-SA-DR
  5334. 156B LD (COPIES),A Store new value.
  5335. 156E RES 1,(RECFLG) Signal 'not EOF'.
  5336. 1572 LD A,+00 Clear CHREC.
  5337. 1574 LD (CHREC),A
  5338. 1577 JR 14FC,NEW-NAME Make another copy.
  5339. 1579 END-SA-DR XOR A Turn off Microdrive motor.
  5340. 157A CALL 17F7,SEL-DRIVE
  5341. 157D JP 10C4,DEL-M-BUF Exit via the delete-channel
  5342. subroutine.
  5343.  
  5344. THE 'GET HEADER INFORMATION FROM MICRODRIVE' SUBROUTINE
  5345. This subroutine is used to collect the first nine bytes of the file into the "m" channel buffer, i.e. the 'header \
  5346. information' when handling files which have been written using the SAVE command (see 08C8). These bytes are copied \
  5347. into the HD system variables.
  5348.  
  5349. 1580 F-M-HEAD LD HL,(5CE1) Move 'start' of data into +5CE4.
  5350. 1583 LD (5CE4),HL
  5351. 1586 CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
  5352. 1589 BIT 0,(CHFLAG) Continue only if the file is found.
  5353. 158D JR Z,1591,F-HD-2
  5354.  
  5355. 'File not found'
  5356.  
  5357. 158F RST 20,SH-ERR Call the error handling routine.
  5358. 1590 DEFB +11
  5359.  
  5360. 1591 F-HD-2 BIT 2,(RECFLG) Continue only if it is not a
  5361. 1595 JR NZ,1599,F-HD-3 'PRINT-type' tile.
  5362.  
  5363. 'Wrong file type'
  5364.  
  5365. 1597 RST 20,SH-ERR Call the error handling routine.
  5366. 1598 DEFB +16
  5367.  
  5368. 1599 F-HD-3 PUSH IX Point to the start of the 512-byte
  5369. 159B POP HL buffer.
  5370. 159C LD DE,+0052
  5371. 159F ADD HL,DE
  5372. 15A0 LD DE,+5CE6 Address of HD-00 variable.
  5373. 15A3 LD BC,+0009 Length of 'header information'.
  5374. 15A6 LDIR Copy header into HD variables.
  5375. 15A8 RET Finished.
  5376.  
  5377. THE 'LOAD OR VERIFY BLOCK FROM MICRODRIVE' SUBROUTINE
  5378. This subroutine is called from the 'LOAD OR VERIFY' subroutine (see 0A66) to load or verify (depending upon the state \
  5379. of bit 7 of FLAGS3) a block of bytes in memory, starting from the address held in the HL register pair. The subroutine
  5380. initially calculates the number of records that composes the file; then starts to collect records and to LOAD or \
  5381. VERIFY the data coming in the 512-Byte buffer. When each record has been loaded or verified, the relevant map bit is \
  5382. set, so as to prevent the record to be used again. The map contents are restored to their initial values before \
  5383. returning. Note that the records may be collected from the Microdrive in a random order.
  5384.  
  5385. 15A9 LV-MCH LD (HD-0D),HL Store 'start'.
  5386. 15AC LD E,(IX+83) Get 'new' length directly from the
  5387. 15AF LD D,(IX+84) 'header information' held in the
  5388. buffer.
  5389. 15B2 LD HL,+0008 Increase 'length' by 8.
  5390. 15B5 ADD HL,DE
  5391. 15B6 SRL H The number of records that composes
  5392. the file is computed (INT(length/5l2))
  5393. 15B8 INC H Include the 'EOF' record.
  5394. 15B9 LD A,H Save this value into HD-0B.
  5395. 15BA LD (HD-0B),A
  5396. 15BD CALL 1613,SA-MAP Save the map into the stack.
  5397. 15C0 LD DE,+0009 Subtract the 'header length' from
  5398. 15C3 LD L,(RECLEN-lo) the 'block length'.
  5399. 15C6 LD H,(RECLEN-hi)
  5400. 15C9 OR A
  5401. 15CA SBC HL,DE
  5402. 15CC LD (RECLEN-lo),L Store actual data block length.
  5403. 15CF LD (RECLEN-hi),H
  5404. 15D2 PUSH IX Make HL point after the nine bytes of
  5405. 15D4 POP HL 'header information'.
  5406. 15D5 LD DE,+005B
  5407. 15D8 ADD HL,DE
  5408. 15D9 LD DE,(HD-0D) Fetch 'start' saved at 15A9.
  5409. 15DD JR 15F9,LOOK-MAP Jump forward.
  5410. 15DF USE-REC CALL 166C,F-REC2 Fetch a record.
  5411. 15E2 LD A,(RECNUM) Repeat if RECNUM is still zero.
  5412. 15E5 OR A
  5413. 15E6 JR Z,15DF,USE-REC
  5414.  
  5415. Now some calculation is performed to obtain into DE the address from which the data coming from the current record, \
  5416. will be loaded or verified. HL will point to the 512-byte buffer.
  5417.  
  5418. 15E8 RLA Now A = RECNUM*2.
  5419. 15E9 DEC A A=RECNUM*2-1.
  5420. 15EA LD D,A Use it as high byte.
  5421. 15EB LD E,+F7 Exclude nine bytes of initial header.
  5422. 15ED LD HL,(HD-0D) Fetch 'start'.
  5423. 15F0 ADD HL,DE Calculate 'start' to use with this
  5424. record.
  5425. 15F1 EX DE,HL Move it to DE.
  5426. 15F2 PUSH IX Make HL point to the start
  5427. 15F4 POP HL of the 512-byte buffer.
  5428. 15F5 LD BC,+0052
  5429. 15F8 ADD HL,BC
  5430. 15F9 LOOK-MAP EXX Use alternate registers.
  5431. 15FA CALL 12DA,CHK-MAP-2 Check bit state for the current
  5432. record.
  5433. 15FD JR NZ,15DF,USE-REC Repeat if this record has already
  5434. been fetched.
  5435. 15FF LD A,(HL) Set map bit to prevent the record
  5436. 1600 OR B from being fetched again.
  5437. 1601 LD (HL),A
  5438. 1602 EXX Restore initial register values.
  5439. 1603 CALL 1648,LD-VE-M Load or verify this record.
  5440. 1606 LD A,(HD-0B) Fetch number of records stored at
  5441. 15BA above.
  5442. 1609 DEC A Decrease it and repeat until all
  5443. 160A LD (ED-0B),A records have been collected.
  5444. 160D JR NZ,15DF,USE-REC
  5445. 160F CALL 162D,RE-MAP Restore map contents.
  5446. 1612 RET Finished.
  5447.  
  5448. THE 'SAVE MICRODRIVE MAP CONTENTS' SUBROUTINE
  5449. This subroutine, called from LV-MCH above, simply copies the '32' bytes that form the Microdrive map into the machine \
  5450. stack.
  5451.  
  5452. 1613 SA-MAP POP HL Store return address in a currently
  5453. 1614 LD (SECTOR),HL unused variable.
  5454. 1617 LD L,(CHMAP-lo) Fetch map start address.
  5455. 161A LD H,(CHMAP-hi)
  5456. 161D LD BC,+1000 B counts 16 passes (map length/2)
  5457. 1620 SA-MAP-LP LD E,(HL) Fetch a byte from the map.
  5458. 1621 LD (HL),C Then clear map byte.
  5459. 1622 INC HL Point to next location.
  5460. 1623 LD D,(HL) Fetch another map byte.
  5461. 1624 LD (HL),C Then clear map byte.
  5462. 1625 INC HL Point to next location.
  5463. 1626 PUSH DE Save the two collected bytes into
  5464. the stack.
  5465. 1627 DJNZ 1620,SA-MAP-LP Continue the loop.
  5466. 1629 LD HL,(SECTOR) Fetch return address.
  5467. 162C JP (HL) Make an indirect return.
  5468.  
  5469. THE 'RESTORE MICRODRIVE MAP CONTENTS' SUBROUTINE
  5470. Exactly the opposite of the subroutine above: the 32 bytes at the top of the
  5471. stack are collected and copied into the Microdrive map.
  5472.  
  5473. 162D RE-MAP POP HL Fetch return address.
  5474. 162E LD (SECTOR),HL Store it in a currently unused
  5475. variable.
  5476. 1631 LD L,(CHMAP-lo) Fetch map address.
  5477. 1634 LD H,(CHMAP-hi)
  5478. 1637 LD DE,+001F Advance to the last map location.
  5479. l63A ADD HL,DE
  5480. 163B LD B,+10 Counts 'map/2' bytes.
  5481. 163D RE-MAP-LP POP DE Fetch two bytes.
  5482. 163E LD (HL),D Store first byte in the map.
  5483. 163F DEC HL Previous location.
  5484. 1640 LD (HL),E Store second byte.
  5485. 1641 DEC HL Previous location.
  5486. 1642 DJNZ 163D,RE-MAP-LP Continue the loop.
  5487. 1644 LD HL,(SECTOR) Fetch return address.
  5488. 1647 JP (HL) Make an indirect return.
  5489.  
  5490. THE 'LD-VE-M' SUBROUTINE
  5491. This subroutine performs the actual LOAD or VERIFY operation. It is entered with HL holding the data start address, \
  5492. and with DE holding the address from which the data have to be loaded or verified.
  5493.  
  5494. 1648 LD-VE-M LD C,(RECLEN-lo) Fetch record length.
  5495. 164B LD B,(RECLEN-hi)
  5496. 164E LD A,(FLAGS3) Jump if VERIFYing.
  5497. 1651 BIT 7,A
  5498. 1653 JR NZ,1658,VE-M-E
  5499. 1655 LDIR LOAD the data.
  5500. 1657 RET Finished.
  5501. 1658 VE-M-E LD A,(DE) Fetch an existing byte.
  5502. 1659 CP (HL) Compare against loaded one.
  5503. 165A JR NZ,1664,VE-FAIL Jump if they do not match.
  5504. 165C INC HL Point to next locations.
  5505. 165D INC DE
  5506. 165E DEC BC Repeat until the block has been
  5507. 165F LD A,B verified.
  5508. 1660 OR C
  5509. 1661 JR NZ,1658,VE-M-E
  5510. 1663 RET Finished.
  5511.  
  5512. 'Verification has failed'
  5513.  
  5514. 1664 VE-FAIL RST 20,SH-ERR Call the error handling routine.
  5515. 1665 DEFB +15
  5516.  
  5517. THE 'FETCH A RECORD FROM MICRODRIVE' SUBROUTINE
  5518. This subroutine is used to read from the Microdrive unit, a record of the current file (saved with a SAVE command). An \
  5519. error occurs if no record is found after five passes of the cartridge tape. The entry point is F-REC2 when the \
  5520. Microdrive motor is already turned on.
  5521.  
  5522. 1666 F-REC1 LD A,(CHDRIV) Fetch drive number.
  5523. 1669 CALL 17E7,SEL-DRIVE Start drive motor.
  5524. 166C E-REC2 LD BC,+04FB Count five passes of the tape.
  5525. 166F LD (SECTOR),BC
  5526. 1673 UNTILFIVE CALL 11A5,G-HD-RC Fetch header and record.
  5527. 1676 JR C,168A,F-ERROR Jump with any error, or with
  5528. 1678 JR Z,168A,F-ERROR unused sectors.
  5529. 167A CALL 12DA,CHK-MAP-2 Check map bit.
  5530. 167D JR NZ,168A,F-ERROR Jump also with already fetched
  5531. records.
  5532. 167F PUSH IX Make HL point to the start of the
  5533. 1681 POP HL 512-byte buffer.
  5534. 1682 LD DE,+0052
  5535. 1685 ADD HL,DE
  5536. 1686 CALL 1346,CHKS-BUFF Return only with correct checksum.
  5537. 1689 RET Z
  5538. 168A F-ERROR CALL 1312,DEC-SECT Decrease SECTOR.
  5539. 168D JR NZ,1673,UNTILFIVE And continue until five passes of the
  5540. tape have been made.
  5541. 'File not found'
  5542.  
  5543. 168F RST 20,SH-ERR Call the error handling routine.
  5544. 1690 DEER +11
  5545.  
  5546. THE 'RESTORE ADDRESS OF "FILENAME"' ROUTINE
  5547. After the 'insertion' of some space, the 'filenames' whose start addresses are held into (N-STR1+2) and (N-STR2+2) \
  5548. have been moved up in the workspace area. This routine is entered with HL holding the channel start address, and with \
  5549. BC
  5550. holding the number of 'inserted' bytes. The addresses held into (N-STR1+2) and (N-STR2+2) are then updated, unless the \
  5551. filenames are stored into 'no-dynamic' areas (i.e. before the channel or after STKEND).
  5552.  
  5553. 1691 REST-N-AD PUSH HL Save 'start of channel' twice.
  5554. 1692 PUSH HL
  5555. 1693 LD DE,(N-STR2+2) Restore start address of the second
  5556. 1697 CALL 16AC,TST-PLACE filename.
  5557. 169A LD (N-STR2+2),DE
  5558. 169E POP HL Restore channel start address.
  5559. 169F LD DE,(N-STR1+2) Restore start address of the first
  5560. 16A3 CALL 16AC,TST-PLACE filename.
  5561. 16A6 LD (N-STR1+2),DE
  5562. l6AA POP HL Restore channel start address.
  5563. 16AB RET Finished.
  5564.  
  5565. The subroutine which calculates the new filename address is the following:
  5566.  
  5567. 16AC TST-PLACE SCF Allow for a further byte.
  5568. 16AD SBC HL,DE No action is made if the filename is
  5569. 16AF RET NC before the channel,
  5570. 16B0 LD HL,(STKEND) or if it is after STKEND.
  5571. 16B3 SBC HL,DE
  5572. 16B5 RET C
  5573. 16B6 EX DE,HL Add to DE the number of 'inserted'
  5574. 16B7 ADD HL,BC bytes, so returning the new filename
  5575. 16B8 EX DE,HL address.
  5576. 16B9 RET Finished.
  5577.  
  5578. 16BA...1707 Unused locations (all set to +FF).
  5579.  
  5580. THE 'CLOSE-STREAM' ROUTINE
  5581. The main ROM 'CLOSE' routine at +16E5 is rather inadequate to deal with Interface's channels:
  5582. First, it has a bug that may crash the system when attempting to CLOSE an unopened stream. This is because the CLOSE-2 \
  5583. routine at +1701 does not check whether the displacement data (found by STR-DATA, +171E) is +0000 (signalling a
  5584. CLOSEd stream). Thus a channel specifier is loaded from a wrong location (CHANS+3), and finally a call to the INDEXER \
  5585. routine is made to search for the (wrong) specifier into the 'stream look-up table', this will result in a system \
  5586. crash.
  5587.  
  5588. Secondly, that routine will only clear the stream data in STRMS area and is not able to manipulate and reclaim the \
  5589. interface's channels as required. So the shadow ROM is paged-in by an instruction fetch at the address +1708 (i.e., \
  5590. the middle of the CLOSE-2 routine in the main ROM). The following routine is then used.
  5591.  
  5592. 1708 CLOSE-CL INC HL The 'INC HL' at +1708 in main ROM.
  5593. 1709 RST 30,NEWVARS Create new variables if required.
  5594. 170A SRL A Range of stream number is +03..+12.
  5595. 170C SUB +03 And now +00..+0F.
  5596. 170E RES 1,(FLAGS3) Signal 'unsent bytes in the buffer
  5597. have to be sent'.
  5598. 1712 CALL 1718,CLOSE Close the stream.
  5599. 1715 JP 05C1,END1 Finished.
  5600.  
  5601. THE 'CLOSE' COMMAND SUBROUTINE
  5602. Any stream +00 to +0F may be CLOSEd by loading the stream number into A and then calling this subroutine. The unsent \
  5603. bytes in 'write'-type files are sent or lost depending upon whether bit 1 of FLAGS3 is reset or set. First a call to
  5604. 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 \
  5605. first of the two data bytes.
  5606.  
  5607. 1718 CLOSE RST 10,CALBAS Call STR-DATA1.
  5608. 1719 DEFW +1727
  5609. 171B LD A,C Return if the stream is already
  5610. 171C OR B CLOSEd (i.e. stream data = 0).
  5611. 171D RET Z
  5612. 171E PUSH BC
  5613. 171F PUSH HL
  5614. 1720 LD HL,(CHANS) Make HL point to the start of the
  5615. 1723 DEC HL channel attached to the stream to
  5616. 1724 ADD HL,BC be closed.
  5617. 1725 EX (SP),HL HL now holds the address of the
  5618. stream data.
  5619. 1726 RST 20,CALBAS A call in the middle of the main ROM
  5620. 1727 DEFW +16EB 'CLOSE' routine is made to update
  5621. STRMS contents.
  5622. 1729 LD HL,(CHANS) Make HL point to the first of the
  5623. l72C LD DE,+0014 'new' channels,
  5624. 172F ADD HL,DE
  5625. 1730 POP DE Restore channel start address.
  5626. 1731 SCF Return if the channel is not
  5627. 1732 SBC HL,DE a 'new' one.
  5628. 1734 POP BC
  5629. 1735 RET NC
  5630. 1736 PUSH BC Save stream data, and
  5631. 1737 PUSH DE channel start address.
  5632. 1738 EX DE,HL Move start of channel to HL.
  5633. 1739 LD (CURCHL),HL Make the channel 'current'.
  5634. 173C INC HL Advance HL to the channel specifier.
  5635. 173D INC HL
  5636. 173E INC HL
  5637. 173F INC HL
  5638. 1740 LD A,(HL) Fetch channel specifier.
  5639. 1741 LD DE,+0005 Points to channel length.
  5640. 1744 ADD HL,DE
  5641. 1745 LD E,(HL) Fetch channel length.
  5642. 1746 INC HL
  5643. 1747 LD D,(HL)
  5644. 1748 PUSH DE Save the 'length'.
  5645. 1749 CP +42 Jump with "b" channel.
  5646. 174B JR Z,1751,CL-RS-CH
  5647. 174D CP +54 Jump with "n" and "m" channels.
  5648. 174F JR NZ,175E,CL-N-CH
  5649.  
  5650. Now follows the CLOSE routine for the "t" and "b" channels.
  5651.  
  5652. 1751 CL-RS-CH BIT 1,(FLAGS3) Jump if doing a CLEAR#.
  5653. 1755 JR NZ,177F,RCLM-CH (i.e. do not send any data).
  5654. 1757 LD A,+0D Send a carriage return over RS232.
  5655. 1759 CALL 0C5A,BCHAN-OUT
  5656. 175C JR 177F,RCLM-CH Jump to reclaim the channel.
  5657. 175E CL-N-CH CP +4E Jump with "m" channel.
  5658. 1760 JR NZ,176D,CL-M-CH
  5659.  
  5660. This is the CLOSE routine for the "n" channel,
  5661.  
  5662. 1762 BIT 1,(FLAGS3) Jump if doing a CLEAR#.
  5663. 1766 JR NZ,177F,RCLM-CH
  5664. 1768 CALL 0EF5,SEND-NEOF Send remaining contents of "n"
  5665. buffer.
  5666. 176B JR 177F,RCLM-CH
  5667.  
  5668. Finally the CLOSE routine for the "m" channel.
  5669.  
  5670. 176D CL-M-CH CP +4D Jump if not "m" channel.
  5671. 176F JR NZ,177F,RCLM-CH
  5672. 1771 POP DE Remove 'channel length'.
  5673. 1772 POP IX Start of channel.
  5674. 1774 POP DE Stream data.
  5675. 1775 BIT 1,(FLAGS3) Send the EOF record on microdrive if
  5676. 1779 JP Z,12A9,CLOSE-M2 not using CLEAR#.
  5677. l77C JP 10C4,DEL-M-BUF Reclaim "m" channel.
  5678.  
  5679. 177F RCLM-CH POP BC Channel length.
  5680. 1780 POP HL Channel start address.
  5681. 1781 PUSH BC Save 'length' again.
  5682. 1782 RST 10,CALBAS Call RECLAIM-2 to delete the channel.
  5683. 1783 DEFW +19E8
  5684.  
  5685. NOTE: If the BREAK key is pressed while the buffer is sent as EOF block, the routine does not reach RCLM-CH or \
  5686. DEL-M-BUF, and it is impossible to delete the channel from BASIC unless using the NEW command. The bug should be \
  5687. eliminated by making the channel 'temporary', by setting bit 7 of channel specifier (at 1740..1741), so the channel \
  5688. will be deleted when any error occurs.
  5689.  
  5690. Now all data referring to the stream attached to the channels moved down are updated.
  5691.  
  5692. 1785 XOR A Start with stream 0.
  5693. 1786 LD HL,+5C16 Address of data for stream 0.
  5694. 1789 UPD-STRM LD E,(HL) Fetch stream data.
  5695. 178A INC HL
  5696. 178B LD D,(HL)
  5697. 178C DEC HL Point to the first byte.
  5698. 178D LD (X-PTR),HL Store address into X-PTR.
  5699. 1790 POP BC Length of channel.
  5700. 1791 POP HL Stream data for closed channel.
  5701. 1792 PUSH HL
  5702. 1793 PUSH BC
  5703. 1794 AND A Jump if the stream data found is
  5704. 1795 SBC HL,DE lower than that of the closed stream
  5705. 1797 JR NC,17A4,UPD-NXT-S (i.e. channel has not been moved).
  5706. 1799 EX DE,HL HL holds the fetched Stream data.
  5707. 179A AND A Calculate into DE the new stream data
  5708. 179B SBC HL,BC to be stored.
  5709. 179D EX DE,HL
  5710. 179E LD HL,(X-PTR) Restore stream data address.
  5711. 17A1 LD (HL),E Store new stream data.
  5712. 17A2 INC HL
  5713. 17A3 LD (HL),D
  5714. 17A4 UPD-NXT-S LD HL,(X-PTR) Make HL point to next stream data.
  5715. 17A7 INC HL
  5716. 17A8 INC HL
  5717. 17A9 INC A Increment stream number.
  5718. 17AA CP +10 Loop for all 16 streams.
  5719. 17AC JR C,1789,UPD-STRM
  5720. 17AE LD (X-PTR-hi),+00 Clear X-PTR.
  5721. 17B2 POP HL Remove 'channel length' and
  5722. 17B3 POP HL 'stream data'.
  5723. 17B4 RES 1,(FLAGS3) Clear 'CLEAR/CLOSE' flag.
  5724. 17B8 RET Finished.
  5725.  
  5726. THE 'RECLAIM TEMPORARY CHANNELS' SUBROUTINE
  5727. This subroutine is called to reclaim from the CHANS area all 'temporary' channels (i.e. with bit 7 of channel \
  5728. specifier set). Also the drive motors are turned off. The routine is always called when any error report occurs, and \
  5729. on some other occasions.
  5730.  
  5731. 17B9 RCL-T-CH LD IX,(CHANS) Make IX point to first 'non-standard'
  5732. 17BD LD DE,+0014 channel.
  5733. 17C0 ADD IX,DE
  5734. 17C2 EX-CHANS LD A,(IX+3) Jump if the CHANS area is not
  5735. 17C5 CP +80 finished.
  5736. 17C7 JR NZ,17D2,CHK-TEMPM
  5737. 17C9 LD A,+EE Send a signal to the interface.
  5738. 17CB OUT (+EF),A
  5739. 17CD XOR A Return via SEL_DRIVE to turn off
  5740. 17CE JP 17F7,SEL-DRIVE drive motors.
  5741. 17D1 RET Never executed.
  5742.  
  5743. 17D2 CHK-TEMPM LD A,(IX+4) Fetch channel specifier.
  5744. 17D5 CP +CD Jump if not a temporary "m" channel.
  5745. 17D7 JR NZ,17DE,CHK-TEMPN
  5746. 17D9 CALL 10C4,DEL-M-BUF Reclaim "m" channel.
  5747. 17DC JR 17B9,RCL-T-CH Loop again.
  5748. 17DE CHK-TEMPN CP +CE Jump if not a temporary "n" channel.
  5749. 17E0 JR NZ,17ED,PT-N-CHAN
  5750. 17E2 LD BC,+0114 Length of "n" channel.
  5751. 17E5 PUSH IX Make HL point to start of channel.
  5752. 17E7 POP HL
  5753. 17E8 RST 10,CALBAS Call RECLAIM-2 to reclaim channel.
  5754. 17E9 DEFW +19E8
  5755. 17EB JR 17B9,RCL-T-CH Loop again.
  5756. 17ED PT-N-CHAN LD E,(IX+9) Fetch channel length.
  5757. l7F0 LD D,(IX+10)
  5758. 17F3 ADD IX,DE Point to next channel.
  5759. 17F5 JR 17C2,EX-CHANS Loop for the whole CHANS area.
  5760.  
  5761. THE 'SELECT DRIVE MOTOR' SUBROUTINE
  5762. This subroutine is also called by using 'hook code' +21. On entry, A must hold a drive number in the range 1. .8; the \
  5763. appropriate drive motor is turned on, and an error occurs if the specified drive is not present (or if it contains no \
  5764. cartridge, or
  5765. contains an unformatted cartridge). If A holds zero, all motors are turned off. Note that this subroutine returns with \
  5766. interrupts disabled if a motor has been switched on.
  5767.  
  5768. 17F7 SEL-DRIVE PUSH HL Save HL register pair.
  5769. 17F8 CP +00 Jump if a drive motor is to be turned
  5770. 17FA JR NZ,1802,TURN-ON on.
  5771. 17FC CALL 182A,SW-MOTOR Otherwise switch off all motors.
  5772. 17FF EI Enable interrupts.
  5773. 1800 POP HL Restore HL.
  5774. 1801 RET Finished.
  5775. 1802 TURN-ON DI Disable interrupts.
  5776. 1803 CALL 182A,SW-MOTOR Switch motors as required.
  5777. 1806 LD HL,+1388 First wait about 40 ms.
  5778. 1809 TON-DELAY DEC HL Decrease counter.
  5779. 180A LD A,H Has the counter reached zero?
  5780. 180B OR L
  5781. 180C JR NZ,1809,TON-DELAY Repeat if not.
  5782. 180E LD HL,+1388 Repeat 5000 times the following test:
  5783. 1811 REPTEST LD B,+06 Set a counter.
  5784. 1813 CMK-PRES CALL 18E9,TEST-BRK Give an error if BREAK is pressed.
  5785. 1816 IN A,(+EF) Repeat until 'GAP' signal is found low
  5786. 1818 AND +04
  5787. 181A JR NZ,1820,NOPRES
  5788. 181C DJNZ 1813,CHK-PRES Repeat 6 times.
  5789. 181E POP HL Restore HL.
  5790. 181F RET Finished.
  5791. 1820 NOPRES DEC HL Becrease counter.
  5792. 1821 LD A,H Has the counter reached zero?
  5793. 1822 OR L
  5794. 1823 JR NZ,1811,REPTEST Repeat if not.
  5795. 1825 CALL 17F7,SEL-DRIVE Send 'switch off' signals and enable
  5796. interrupts.
  5797. 'Microdrive not present'
  5798.  
  5799. 1828 RST 20,SH-ERR Call the error handling routine.
  5800. 1829 DEFB +10
  5801.  
  5802. The following subroutine does the actual switching' of the motors, and the selection of the required drive. It is \
  5803. entered with drive number 1...8 (or 0 to switch all motors off) in the A register. The required drive motor is \
  5804. selected, its motor started, while others are disabled.
  5805.  
  5806. 182A SW-MOTOR PUSH DE Save DE register pair.
  5807. 182B LB DE,+0100
  5808. 182E NEG A = 0 - drive number.
  5809. 1830 ADD A,+09 A = 9 - drive number.
  5810. 1832 LD C,A Move counter to C.
  5811. 1833 LD B,+08 Loop for 8 microdrives.
  5812. 1835 ALL-NOTRS DEC C Switch off this microdrive if it is
  5813. 1836 JR NZ,184B,OFF-MOTOR not the required one.
  5814. 1838 LD A,D Otherwise switch on the motor.
  5815. 1839 OUT (+F7),A
  5816. 183B LD A,+EE
  5817. 183D OUT (+EF),A
  5818. 183F CALL 1867,DEL-S-1 Wait about 1 ms.
  5819. 1842 LD A,+EC
  5820. 1844 OUT (+EF),A
  5821. 1846 CALL 1867,DEL-S-1 Wait about 1 ms.
  5822. 1849 JR 185C,NXT-MOTOR Continue with next microdrive.
  5823. 184B OFF-MOTOR LD A,+EF The drive motor Is turned off.
  5824. 184D OUT (+EF),A
  5825. 184F LD A,E
  5826. 1850 OUT (+F7),A
  5827. 1852 CALL 1867,DEL-S-1 Wait about 1 ms.
  5828. 1855 LD A,+ED
  5829. 1857 OUT (+EF),A
  5830. 1859 CALL 1867,DEL-S-1 Wait about 1 ms,
  5831. 185C NXT-NOTOR DJNZ 1835,ALL-MOTRS Loop for 8 microdrives.
  5832. 185E LD A,D End of drive selection.
  5833. 185F OUT (+F7),A
  5834. 1861 LD A,+EE
  5835. 1863 OUT (+EF),A
  5836. 1865 POP DE Restore DE register pair.
  5837. 1866 RET Finished.
  5838.  
  5839. THE '1 MILLISECOND DELAY' SUBROUTINE
  5840. This subroutine inserts a delay of about 3600 T cycles. It is called from
  5841. SW-MOTOR above.
  5842.  
  5843. 1867 DEL-S-1 PUSH BC Save BC register pair.
  5844. 1868 PUSH AF Save accumulator.
  5845. 1869 LD BG,+0087 Inserts a delay of 3553 T cycles.
  5846. 186C CALL 18FA,DELAY-BC
  5847. 186F POP AF Restore registers.
  5848. 1870 POP BC
  5849. 1871 RET Finished.
  5850.  
  5851. THE 'SEND DATA BLOCK TO MICRODRIVE HEAD' SUBROUTINE
  5852. This subroutine is used for writing a block of bytes onto a Microdrive cartridge. On entry, HL must hold the start of \
  5853. the block to be written. The block is then sent to the Interface (provided that the write-protect tab is present) in a \
  5854. parallel form (the bytes are converted in a serial form by the hardware). The entry points OUT-M-HD and OUT-M-BUF are \
  5855. used respectively to write headers or data blocks (including preambles).
  5856.  
  5857. 1872 OUT-M-HD PUSH HL Save block start address.
  5858. 1873 LD DE,+001E Block length.
  5859. 1876 JR 187C,0UT-M-BLK Jump forward.
  5860. 1878 OUT-M-BUF PUSH HL Save block start address.
  5861. 1879 LD DE,+021F Block length.
  5862. 187C OUT-N-ELK IN A,(+EF) Check write-protect tab.
  5863. 187E AND +01 Only bit 0.
  5864. 1880 JR NZ,1884,NOT-PROT Jump if tab is present.
  5865.  
  5866. 'Drive 'write' protected'
  5867.  
  5868. 1882 RST 20,SH-ERR Call the error handling routine.
  5869. 1883 DEFB +0E
  5870.  
  5871. 1884 NOT-PROT LD A,(IOBORD) Fetch border colour.
  5872. 1887 OUT (+FE),A Change border colour.
  5873. 1889 LD A,+E2 Start writing.
  5874. 188B OUT (+EF),A
  5875. 188D INC D Increment high counter and copy it
  5876. 188E LD A,D into A.
  5877. 188F LD B,E Low counter.
  5878. 1890 LD C,+E7 Output port.
  5879. 1892 NOP Wait 12 T cycles.
  5880. 1893 NOP
  5881. 1894 NOP
  5882. 1895 OUT-M-BYT OTIR Write first block.
  5883. 1897 DEC A Repeat until the whole block has been
  5884. 1898 JR NZ,1895,OUT-M-BYT written.
  5885. 189A LD A,+E6 Stop writing.
  5886. 189C OUT (+EF),A
  5887. 189E CALL 0CA9,BORD-REST Restore border colour.
  5888. 18A1 POP HL Restore block start address.
  5889. 18A2 RET Finished.
  5890.  
  5891. THE 'RECEIVE BLOCK FROM MICRODRIVE HEAD' SUBROUTINE
  5892. This is the opposite routine to the preceding one. On entry, HL must hold the start address of the header block or of \
  5893. the data block (AFTER the preamble). The bytes are collected from Microdrive head and stored In the appropriate block. \
  5894. 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 \
  5895. block.
  5896.  
  5897. 18A3 GET-M-HD PUSH HL Save start address.
  5898. 18A4 LD DE,+000F Block length.
  5899. 18A7 JR 18AD,GET-M-BLK Jump forward.
  5900. 18A9 GET-M-BUF PUSH HL Save start address.
  5901. 18AA LD DE,+0210 Block length.
  5902. 18AD GET-M-BLK LD B,E Copy 'length' into BC in
  5903. 18AE LD C,D a reversed form.
  5904. 18AF INC C Increment high byte of 'length'.
  5905. 18B0 PUSH BC
  5906. 18B1 CHK-AGAIN LD B,+08 Loop 8 times.
  5907. 18B3 CHKLOOP CALL 18E9,TEST-BRK Give an error if BREAK pressed.
  5908. 18B6 IN A,(+EF) The GAP line is read repeatedly;
  5909. 18B8 AND +04 it must be found 'low' after a 'high'
  5910. 18BA JR Z,18B1,CHK-AGAIN period.
  5911. 18BC DJNZ 18B3,CHKLOOP
  5912. 18BE CHK-AG-2 LD B,+06
  5913. 18C0 CHK-LP-2 CALL 18E9,TEST-BRK
  5914. 18C3 IN A,(+EF)
  5915. 18C5 AND +04
  5916. 18C7 JR NZ,18BE,CHK-AG-2
  5917. 18C9 DJNZ 18C0,CHK-LP-2
  5918. 18CB POP BC Restore BC.
  5919. 18CC LD A,+EE Start reading.
  5920. 18CE OUT (+EF),A
  5921. 18D0 POP HL Restore 'start address'.
  5922. 18D1 PUSH HL
  5923. 18D2 DR-READY IN A,(+EF) Read SYNC line to synchronize the
  5924. 18D4 AND +02 reading with the start of the block.
  5925. 18D6 JR NZ,18D2,DR-READY Repeat until SYNC is found low.
  5926. 18D8 CALL 18E9,TEST-BRK Give an error if BREAK pressed.
  5927. 18DB LD A,C A holds the high counter.
  5928. 18DC LD C,+E7 Input port.
  5929. 18DE IN-M-BLK INIR Read first block.
  5930. 18E0 DEC A Repeat until the whole block has
  5931. 18E1 JR NZ,18DE,IN-M-BLK been read.
  5932. 18E3 LD A,+EE Finished.
  5933. 18E5 OUT (+EF),A
  5934. 18E7 POP HL Restore block start address.
  5935. 18E8 RET
  5936.  
  5937. TIlE 'TEST-BRK' SUBROUTINE
  5938. The BREAK key is checked and the error 'BREAK into program' is made if it is pressed.
  5939.  
  5940. 18E9 TEST-BRK LD A,+7F Read port +7FFE.
  5941. 18EB IN A,(+FE)
  5942. 18ED RRA Only bit 0.
  5943. 18EE RET C Return if SPACE not being pressed.
  5944. 18EF LD A,+FE Read port +FEFE.
  5945. 18F1 IN A,(+FE)
  5946. 18F3 RRA Only bit 0.
  5947. 18F4 RET C Return if CAPS SHIFT not being pressed
  5948. 18F5 LD (ERR-NR),+14 Store error code.
  5949. 18F9 RST 28,ROMERR Report the error.
  5950.  
  5951. THE 'DELAY-BC' SUBROUTINE
  5952. This subroutine is called to insert delays in the program execution, depending upon the value of BC. The exact delay \
  5953. is (BC * 26 - 43) T cycles.
  5954.  
  5955. 18FA DELAY-BC PUSH AF Save accumulator.
  5956. 18FB DELAY-BC1 DEC BC Decrease counter.
  5957. 1BFC LD A,B Repeat until the counter reaches 0.
  5958. 18FD OR C
  5959. 18FE JR NZ,18FB,DELAY-BC1
  5960. 1900 POP AF Restore accumulator.
  5961. 1901 RET Finished.
  5962.  
  5963. The following are two subroutines that are never called from the Shadow ROM code. These subroutines operate evidently \
  5964. on the buffer's contents of a Microdrive channel.
  5965.  
  5966. 1902 UNKN-1 PUSH HL
  5967. 1903 PUSH IX
  5968. 1905 POP HL
  5969. 1906 LD BC,+0052
  5970. 1909 ADD HL,BC
  5971. 190A LD B,H
  5972. 190B LD C,L
  5973. 190C LD HL,+0000
  5974. 190F LD DE,+0000
  5975. 1912 EXX
  5976. 1913 LD BC,+0200
  5977. 1916 LD HL,+0000
  5978.  
  5979. 1919 LD DE,+0000
  5980. 191C UNKN-2 EXX
  5981. 191D LD A,(BC)
  5982. 191E INC BC
  5983. 191F ADD A,E
  5984. 1920 LD E,A
  5985. 1921 JR NC,1929,UNKN-3
  5986. 1923 INC D
  5987. 1924 JR NZ,1929,UNKN-3
  5988. 1928 EXX
  5989. 1929 UNKN-3 ADD HL,DE
  5990. 192A EXX
  5991. 192B ADC HL,DE
  5992. 192D DEC BC
  5993. 192E LD A,B
  5994. 192F OR C
  5995. 1930 JR NZ,191C,UNKN-2
  5996. 1932 LD D,E
  5997. 1933 EXX
  5998. 1934 LD A,D
  5999. 1935 LD E,+00
  6000. 1937 SLA D
  6001. 1939 EXX
  6002. 193A LD E,A
  6003. 193B RL E
  6004. 193D RL D
  6005. 193F EXX
  6006. 1940 ADD HL,DE
  6007. 1941 EXX
  6008. 1942 ADC HL,DE
  6009. 1944 PUSH HL
  6010. 1945 EXX
  6011. 1946 PUSH HL
  6012. 1947 PUSH BC
  6013. 1948 POP HL
  6014. 1949 POP BC
  6015. 194A LD E,+00
  6016. 194C LD A,C
  6017. 194D CP (HL)
  6018. 194E JR Z,1952,UNKN-4
  6019. 1950 INC E
  6020. 1951 LD (HL),A
  6021. 1952 UNKN-4 INC HL
  6022. 1953 LD A,B
  6023. 1954 CP (HL)
  6024. 1955 JR Z,1959,UNKN-5
  6025. 1957 INC E
  6026. 1958 LD (HL),A
  6027. 1959 UNKN-5 INC HL
  6028. 195A POP BC
  6029. 195B LD A,C
  6030. 195C CP (HL)
  6031. 195D JR Z,1961,UNKN-6
  6032. 195F INC E
  6033. 1960 LD (HL),A
  6034. 1961 UNKN-6 INC HL
  6035. 1962 LD A,B
  6036. 1963 CP (HL)
  6037. 1964 JR Z,1968,UNKN-7
  6038. 1966 INC E
  6039. 1967 LD (HL),A
  6040. 1968 UNKN-7 LD A,E
  6041. 1969 OR A
  6042. 196A POP HL
  6043. 196B RET
  6044. l96C UNKN-8 PUSH IX
  6045. 196E POP HL
  6046. 196F LD DE,+0052
  6047. 1972 ADD HL,DE
  6048. 1973 LD BC,+0200
  6049. 1976 UNKN-9 LD A,(HL)
  6050. 1977 XOR +55
  6051. 1979 LD (HL),A
  6052. 197A INC HL
  6053. 197B DEC BC
  6054. 197C LD A,B
  6055. 197D OR C
  6056. 197E JR NZ,1976,UNKN-9
  6057. 1980 RET
  6058.  
  6059. The 'Hook code' routines
  6060.  
  6061. THE 'HOOK-CODE' ROUTINE
  6062. This routine is entered from 00EB with the A register holding a 'hook code', or an invalid error code. The routine \
  6063. calls a set of subroutines in the shadow ROM, and is intended to help the machine-code user. Only the value held in \
  6064. the accumulator may be passed to the called subroutine.
  6065.  
  6066. 1981 HOOK-CODE CP +18 Continue with 'hook' codes.
  6067. 1983 JR C,1987,CLR-ERR
  6068.  
  6069. 'Hook code error'
  6070.  
  6071. 1985 RST 20,SH-ERR Call the error handling routine.
  6072. 1986 DEFB +12
  6073.  
  6074. 1987 CLR-ERR LD (ERR-NR),+FF The 'error' is cleared.
  6075. 198B SET 2,(FLAGS)
  6076. 198F INC HL Advance return address past the
  6077. error code.
  6078. 1990 EX (SP),HL Store new return address; the initial
  6079. value of A goes into H.
  6080. 1991 PUSH HL Save this value.
  6081. 1992 ADD A,A Multiply code by two.
  6082. 1993 LD D,+00 Pass offset into DE.
  6083. 1995 LD E,A
  6084. 1996 LD HL,+19A9 Start of 'hook code addresses' table.
  6085. 1999 ADD HL,DE Index into this table.
  6086. 199A LD E,(HL) Fetch low byte of the address.
  6087. 199B INC HL
  6088. 199C LD D,(HL) Fetch high byte.
  6089. 199D POP AF Restore initial value of A.
  6090. 199E LD HL,+0700 Return address is UNPAGE.
  6091. 19Al PUSH HL
  6092. 19A2 EX DE,HL Move address to HL.
  6093. l9A3 JP (HL) Jump to the 'hook code' routine.
  6094.  
  6095. THE 'HOOK CODE +32' ROUTINE
  6096. This 'hook code' is designed to call (when the main ROM is paged in) any subroutine held in the shadow ROM. The \
  6097. address of the subroutine to be called is taken from HD-11.
  6098.  
  6099. 19A4 HOOK-32 LD HL,(HD-11) Fetch address of the routine.
  6100. 19A7 JP (HL) Jump to the routine.
  6101.  
  6102. THE 'HOOK CODE +31' ROUTINE
  6103. This 'hook code' has the task of creating the new system variables if nonexistent. Note that the routine is made by a \
  6104. single RET instruction, because the variables have been created on entry to the shadow RON.
  6105.  
  6106. 19A8 HOOK-3l RET Jump indirectly to UNPAGE.
  6107.  
  6108. THE 'HOOK CODE ADDRESSES' TABLE
  6109. This jump table is made by the 24 addresses of the routines called by using the various 'hook codes'. Note that hook \
  6110. code +2B jumps incorrectly to the same routine as hook code +22. The correct address seems to be +1AF0.
  6111.  
  6112. 19A9 DEFW +19D9,CONS-IN Hook code +1B.
  6113. 19AB DEFW +19EC,CONS-OUT Hook code +1C.
  6114. 19AD DEFW +0B81,BCHAN-IN Hook code +1D.
  6115. 19AF DEFW +0C5A,BCHAN-OUT Hook code +1E.
  6116. 1981 DEFW +19FC,PRT-OUT Hook code +1F.
  6117. 1983 DEFW +1A01,KBD-TEST Hook code +20.
  6118. 1985 DEFW +17F7,SEL-DRIVE Hook code +21.
  6119. 1987 DEFW +1B29,OP-TEMP-M Hook code +22.
  6120. 1989 DEFW +12A9,CLOSE-M2 Hook code +23.
  6121. 198B DEFW +1D6E,ERASE Hook code +24.
  6122. 198D DEFW +1A09,READ-SEQ Hook code +25.
  6123. 198F DEFW +11FF,WR-RECD Hook code +26.
  6124. 19C1 DEFW +1A17,RD-RANDOM Hook code +27.
  6125. 19C3 DEFW +1A4B,RD-SECTOR Hook code +28.
  6126. 19C5 DEFW +1A86,RD-NEXT Hook code +29.
  6127. 19C7 DEFW +1A91,WR-SECTOR Hook code +2A.
  6128. 19C9 DEFW +1B29,OP-TEMP-M Hook code +2B.
  6129. 19CB DEFW +10C4,DEL-M-BUF Hook code +2C.
  6130. 19CD DEFW +0EA9,OP-TEMP-N Hook code +2D.
  6131. 19CF DEFW +1A24,CLOSE-NET Hook code +2E.
  6132. 19D1 DEFW +1A31,GET-PACK Hook code +2F.
  6133. 19D3 DEFW +0DB2,SEND-PACK Hook code +30.
  6134. 19D5 DEFW +19A8,HOOK-31 Hook code +31.
  6135. 19D7 DEFW +19A4,HOOK-32 Hook code +32.
  6136.  
  6137. THE 'CONSOLE INPUT' SUBROUTINE
  6138. This subroutine is called by using 'hook code' +1B. It simply waits until a key is pressed and returns the character \
  6139. code in the A register. This 'hook code' has been included because the keyboard is not scanned when the main ROM is \
  6140. paged-in.
  6141.  
  6142. 19D9 CONS-IN EI Enable interrupts.
  6143. 19DA RES 5,(FLAGS) Signal 'ready for a new key'.
  6144. 19DE WTKEY HALT Wait 1/50th of second.
  6145. 19DF RST 10,CALBAS Call the keboard scan routine
  6146. 19E0 DEFW +02BF in the main ROM.
  6147. 19E2 BIT 5,(FLAGS) Repeat the scan if no key has been
  6148. 19E6 JR Z,19DE,WTKEY pressed.
  6149. 19E8 LD A,(LAST-K) Fetch character code.
  6150. 19EB RET Finished.
  6151.  
  6152. THE 'CONSOLE OUTPUT' SUBROUTINE
  6153. This subroutine is called by using 'hook code' +1C. The character held in the A register is printed on the screen, \
  6154. with scroll suppressed.
  6155.  
  6156. 19EC CONS-OUT PUSH AF Save character to be printed.
  6157. 19ED LD A,+FE Use stream '-2' (Screen).
  6158. 19EF OUT-CODE LU HL,+5C8C This is SCR-CT.
  6159. 19F2 LD (HL),+FF Set scroll counter.
  6160. 19F4 RST 10,CALBAS Call CHAN-OPEN in the main ROM to
  6161. 19F5 DEFW +1601 select the stream.
  6162. 1SF7 POP AF Restore character.
  6163. 19F8 RST 10,CALBAS Call 'PRINT-A' restart to print the
  6164. 19F9 DEFW +0010 character.
  6165. 19FB RET Finished.
  6166.  
  6167. THE 'PRINTER OUTPUT' SUBROUTINE
  6168. This subroutine is called by using hook code +1F. This is identical to the preceding one, but the output is directed \
  6169. to the stream +03 (normally the ZX
  6170. Printer).
  6171.  
  6172. 19FC PRT-OUT PUSH AF Save character to be printed.
  6173. 19FD LD A,+03 Select stream 3.
  6174. 19FF JR 196F,OUT-CODE Jump back.
  6175.  
  6176. THE 'KEYBOARD TEST' SUBROUTINE
  6177. This is called by using 'hook code' +20. The keyboard is scanned and the zero flag returned reset if any key has been \
  6178. pressed.
  6179.  
  6180. 1A01 KBD-TEST XOR A Clear A, allowing for the whole
  6181. keyboard to be examined.
  6182. 1A02 IN A,(+FE) Read the keyboard.
  6183. 1A04 AND +1F Only 5 less significant bits.
  6184. 1A06 SUB +1F Return with sign negative and zero
  6185. 1A08 RET flag reset if any key has been
  6186. pressed.
  6187.  
  6188. THE 'READ SEQUENTIAL' SUBROUTINE
  6189. This is called by using 'hook code' +25. The subroutine reads into the datablock of the current "m" channel, the next \
  6190. record of a named PRINT-type file. On entry IX must hold the "m" channel start address, and CHREC the number of the \
  6191. current record. CHREC will be automatically incremented. CHDRIV must hold the drive number and CHNAME must hold the \
  6192. file name.
  6193.  
  6194. 1A09 READ-SEQ BIT 1,(RECFLG) Jump if the current record is not
  6195. 1A0D JR Z,1A14,INCREC the EOF one.
  6196. 1A0F LD (ERR-NR),+07 Otherwise signal 'end of file'.
  6197. 1A13 RST 28,ROMERR Report the error.
  6198. 1A14 INCREC INC (CHREC) Increment record number and continue
  6199. into RD-RANDOM.
  6200.  
  6201. THE 'READ RANDOM' SUBROUTINE
  6202. This subroutine is called by using 'hook code' +27. The record number CHREC of a PRINT-type file is loaded into the \
  6203. data block. The other variables are to be set as for READ-SEQ above.
  6204.  
  6205. 1A17 RD-RANDOM CALL 1177,GET-RECD Load CHREC record.
  6206. 1A1A BIT 2,(RECFLG) Return only if this is a PRINT-type
  6207. 1A1E RET Z file.
  6208. 1A1F CALL 10C4,DEL-M-BUF Otherwise reclaim the channel, and
  6209. report the error.
  6210. 'Wrong file type'
  6211.  
  6212. 1A22 RST 20,SH-ERR Call the error handling routine.
  6213. 1A23 DEFB +16
  6214.  
  6215. THE 'CLOSE NETWORK CHANNEL' SUBROUTINE
  6216. This is called by using 'hook code' +2E. First, the remaining bytes in the "n" channel buffer whose base address is \
  6217. held in the CURCHL system variable, are sent as EOF block (if the channel is opened for writing). The channel is then \
  6218. reclaimed.
  6219.  
  6220. 1A24 CLOSE-NET CALL 0EF5,SEND-NEOF Send the EOF block if required.
  6221. 1A27 PUSH IX Move channel start address to HL.
  6222. 1A29 POP HL
  6223. 1A2A LD BC,+0114 Length of "n" channel.
  6224. 1A2D RST 10,CALBAS Call RECLAIM-2 to delete the channel.
  6225. 1A2E DEFW +19E8
  6226. 1A30 RET Finished.
  6227.  
  6228. THE 'GET PACKET FROM NETWORK' SUBROUTINE
  6229. This is called by using 'hook code' +2F. Unfortunately the subroutine is unusable, because the carry flag (that \
  6230. signals if an error has occurred) is corrupted by exit via the BORD-REST subroutine. You may use GET-N-BUF at 03DF to \
  6231. read a packet.
  6232.  
  6233. 1A31 GET-PACK LD A,(IOBORD) Fetch border colour.
  6234. 1A34 OUT (+FE),A Change border colour.
  6235. 1A36 DI Disable interrupts.
  6236. 1A37 CALL 0F1E,WT-SCOUT Wait for a 'scout' leader.
  6237. 1A3A JR NC,1A46,GP-ERROR Jump if 'time-out' occurs.
  6238. 1A3C CALL 0E18,GET-NBLK Wait for header and data block.
  6239. 1A3F JR NZ,1A46,GP-ERROR Jump with any error.
  6240. 1A41 EI Enable interrupts.
  6241. 1A42 AND A Reset carry to signal 'successful'.
  6242. 1A43 JP 0CA9,BORD-REST But it is corrupted into BORD-REST.
  6243. 1A46 CF-ERROR SCF Signal 'error'
  6244. 1A47 EI Enable interrupts.
  6245. 1A48 JP 0CA9,BORD-REST Again the carry flag will be
  6246. corrupted.
  6247.  
  6248. THE 'READ SECTOR' SUBROUTINE
  6249. This is called by using 'hook code' +28. Before using this, you must start the required drive motor, and store a \
  6250. sector number into CHREC. The data block stored into the given sector is then read in the channel area (pointed by \
  6251. IX), and used if it is a PRINT-type record. The carry flag is returned reset if the reading is successful.
  6252.  
  6253. 1A4B RD-SECTOR LD HL,+00F0 Counts through 240 sectors.
  6254. 1A4E LD (SECTOR),HL
  6255. 1A51 NO-GOOD CALL 12C4,GET-M-HD2 Get a header.
  6256. 1A54 LD A,(HDNUM) Fetch current sector number.
  6257. 1A57 CP (CHREC) Compare with given sector number.
  6258. 1A5A JR Z,1A63,USE-C-RC Jump if found the required sector.
  6259. 1A5C CALL 1312,DEC-SECT Otherwise decrease SECTOR.
  6260. 1A5E JR NZ,1A51,NO-G00D Jump until 240 sectors have been
  6261. examined.
  6262. 'File not found'
  6263.  
  6264. 1A61 RST 20,SH-ERR Call the error handling routine.
  6265. 1A62 DEFB +11
  6266.  
  6267. 1A63 USE-C-RC PUSH IX Make HL point to RECFLG (i.e. sTart
  6268. 1A65 POP HL of data block.
  6269. 1A66 LD DE,+0043
  6270. 1A69 ADD HL,DE
  6271. 1A6A CALL 18A9,GET-M-BUF Read data block.
  6272. 1A6D CALL 1341,CHKS-HD-R Calculate current checksum.
  6273. 1A70 JR NZ,1A81,DEL-B-CT Jump if it does not match with old
  6274. checksum.
  6275. 1A72 LD DE,+000F Make HL point to start of buffer.
  6276. 1A75 ADD HL,DE
  6277. 1A76 CALL 1346,CHKS-BUFF Calculate checksum of buffer.
  6278. 1A79 JR NZ,1A81,DEL-B-CT Jump if it does not match with old
  6279. checksum.
  6280. 1A7B OR A Return with carry flag reset if
  6281. 1A7C BIT 2,(RECFLG) this is a PRINT-type file.
  6282. 1A80 RET Z
  6283. 1A81 DEL-B-CT CALL 1AE0,CLR-BUFF Otherwise clear buffer contents.
  6284. 1A84 SCF Return with carry flag set to signal
  6285. 1A85 RET the error.
  6286.  
  6287. THE 'READ NEXT SECTOR' SUBROUTINE
  6288. This is used by using 'hook code' +29. The first header and data block that pass through the Microdrive head are \
  6289. copied into the channel area pointed by IX. As with the previous subroutine, the drive motor is to be started before \
  6290. calling it.
  6291.  
  6292. 1A86 RD-NEXT LD HL,+00F0 Initialise SECTOR to 240.
  6293. 1A89 LD (SECTOR),HL
  6294. 1A8C CALL 12C4,GET-M-HD2 Fetch the first header.
  6295. 1A8F JR 1A63,USE-C-RC Continue back.
  6296.  
  6297. THE 'WRITE SECTOR' SUBROUTINE
  6298. This is used by using 'hook code' +2A. It is the opposite routine of 'RD-SECTOR' above. The Microdrive unit is to be \
  6299. started before calling the routine. The current data block in the "m" channel pointed by the IX register is written \
  6300. onto the sector whose number is specified by CHREC. Other channel variables, such as CHNAME, are to be set as required.
  6301.  
  6302. 1A91 WR-SECTOR LD HL,+00F0 Pass through 240 sectors.
  6303. 1A94 CD (SECTOR),HL
  6304. 1A97 PUSH IX Make HL point to the data block
  6305. 1A99 POP HL preamble.
  6306. 1A9A LD DE,+0037
  6307. 1A9D ADD HL,DE
  6308. 1A9E PUSH HL Save this address.
  6309. 1A9F LD DE,+000C Now point to RECFLG.
  6310. 1AA2 ADD HL,DE
  6311. 1AA3 CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
  6312. 1AA6 LD DE,+000F Now point to the buffer.
  6313. 1AAA CALL 1346,CHKS-BUFF Calculate DCHK checksum.
  6314. 1AAD WR-S-l CALL 12C4,GET-M-HD2 Get a header.
  6315. 1AB0 LD A,(HDNUMB) Fetch current sector number.
  6316. 1AB3 CP (CHREC) See whether it is the expected one.
  6317. 1AB6 JR Z,1ABF,WR-S-2 Jump if so.
  6318. 1AB8 CALL 1312,DEC-SECT Otherwise decrease SECTOR.
  6319. 1ABB JR NZ,1AAD,WR-S-l Loop until 240 sectors have been
  6320. examined.
  6321. 'File not found'
  6322.  
  6323. 1ABD RST 20,SH-ERR Call the error handling routine.
  6324. 1ABE DEFB +11
  6325.  
  6326. 1ABF WR-S-2 IN A,(+EF) Continue if the write-protect tab
  6327. 1AC1 AND +01 is present.
  6328. 1AC3 JR NZ,1AC7,WR-S-3
  6329.  
  6330. 'Drive write protected'
  6331.  
  6332. 1AC5 RS-SH RST 20,SH-ERR Call the error handling routine.
  6333. 1AC6 DEFB +0E
  6334.  
  6335. 1AC7 WR-S-3 LD A,+E6 Start writing.
  6336. 1AC9 OUT (+EF),A
  6337. 1ACB LD BC,+0168 Wait until the first gap is finished.
  6338. 1ACE CALL 18FA,DELAY-BC
  6339. 1AD1 POP HL Restore address of data block preamble
  6340. 1AD2 CALL 1878,OUT-M-BUF Write data block onto cartridge.
  6341. 1AD5 LD A,+EE Stop writing.
  6342. 1AD7 OUT (+EF),A
  6343. 1AD9 CALL 12DF,CHECK-MAP Finally set the appropriate map bit.
  6344. 1ADC LD A,B
  6345. 1ADD OR (HL)
  6346. 1ADE LD (HL),A
  6347. 1ADF RET Finished.
  6348.  
  6349. THE 'CLEAR BUFFER CONTENTS' SUBROUTINE
  6350. This subroutine is called from RD-SECTOR and RD-NEXT subroutines to clear the data received into the "m" buffer, if \
  6351. they are not part of a PRINT-type file.
  6352.  
  6353. 1AE0 CLR-BUFF PUSH IX Make HL point to the start of the
  6354. 1AE2 POP HL "m" buffer.
  6355. 1AE3 LD DE,+0052
  6356. 1AE6 ADD HL,DE
  6357. 1AE7 LD D,H Copy this address into DE.
  6358. 1AE8 LD E,L
  6359. 1AE9 INC DE 'Destination' is next byte.
  6360. 1AEA LD BC,+01FF Buffer length - 1.
  6361. 1AED LDIR Clear the buffer.
  6362. 1AEF RET Finished.
  6363.  
  6364. THE 'OPEN A PERMANENT "M" CHANNEL' SUBROUTINE
  6365. This is the actual OPEN corinnand referred to the "m" channel. A permanent "m" channel is opened, and it is attached \
  6366. to the stream held into S-STR1 (provided that the file is a PRINT-type file).
  6367.  
  6368. 1AF0 OP-M-STRM LD A,(S-STR1) Fetch stream number.
  6369. 1AF3 ADD A,A Multiply by two.
  6370. 1AF4 LD HL,+5Cl6 Address of data for stream 0.
  6371. 1AF7 LD E,A Use (stream*2) as offset.
  6372. 1AF8 LD D,+00
  6373. 1AFA ADD HL,DE Index into STRMS area.
  6374. 1AFB PUSH HL Save address of data for the required
  6375. stream.
  6376. 1AFC CALL 1B29,OP-TEMP-M Open a temporary "m" channel.
  6377. 1AFF BIT 0,(CHFLAG) Jump if this is a 'read' file.
  6378. 1B03 JR Z,1B0D,MAKE-PERM
  6379. 1B05 IN A,(+EF) Jump if the write-protect tab is
  6380. 1B07 AND +01 present.
  6381. 1B09 JR NZ,1B0D,MAKE-PERM
  6382.  
  6383. 'Drive 'write' protected'
  6384.  
  6385. 1B0B RST 20,SH-ERR Call the error handling routine.
  6386. 1B0C DEFB +0E
  6387.  
  6388. 1B0D MAKE-PERN RES 7,(IX+4) Make the channel permanent.
  6389. 1B11 XOR A Switch off drive motors.
  6390. 1B12 CALL 17F7,SEL-DRIVE
  6391. 1B15 BIT 0,(CHFLAG) Jump with 'write' files.
  6392. 1B19 JR NZ,1B23,STORE-DSP
  6393. 1B1B BIT 2,(RECFLG) Jump with PRINT-type 'read' files.
  6394. 1B1F JR Z,1B23,STORE-DSP
  6395.  
  6396. 'Wrong file type'
  6397.  
  6398. 1B21 RST 20,SH-ERR Call the error handling routine.
  6399. 1B22 DEFB +16
  6400.  
  6401. 1B23 STORE-DSP EX DE,HL DE holds new stream data.
  6402. 1B24 POP HL Restore stream address.
  6403. 1B25 LD (HL),E Store stream data into STRMS area.
  6404. 1B26 INC HL
  6405. 1B27 LD (HL),D
  6406. 1B28 RET Finished.
  6407.  
  6408. THE 'OPEN TEMPORARY "M" CHANNEL' SUBROUTINE
  6409. This fundamental subroutine is used to open a temporary "m" channel in the CHANS area. First a temporary "m" channel \
  6410. is created. Then the drive whose number is held into D-STR1 is started, and searched for a file whose name is held into
  6411. N-STR1. A map area is created (unless it already exists), and its contents are setup according to the cartridge \
  6412. contents (the bits reset indicate 'free for use' sectors). Various flags are returned as follows:
  6413. - bit 0 of CHFLAG set with 'write' files.
  6414. - bit 1 of RECFLG set with EOF block.
  6415. - bit 2 of RECFLG set with PRINT-type files.
  6416.  
  6417. On exit, HL holds a 'stream data' displacement that may be used to attach the channel to a stream. The drive motor \
  6418. will not be switched off. Note that H'L' is corrupted and the user must preserve its value when using this routine \
  6419. from BASIC.
  6420.  
  6421. 1B29 OP-TEMP-M CALL 0FE8,SET-T-MCH Create a temporary "m" channel.
  6422. 1B2C PUSH HL Save 'stream displacement'
  6423. 1B2D LD A,(CHDRIV) Fetch drive number.
  6424. 1B30 CALL 17F7,SEL-DRIVE Turn on drive motor.
  6425. 1B33 LD BC,+00FF Count 255 sectors.
  6426. 1B36 LD (SECTOR),BC
  6427. 1B3A OP-F-1 CALL 11A5,G-HD-RC Get header and data block.
  6428. 1B3D JR C,1B5F,OP-F-4 Jump with any error.
  6429. 1B3F JR Z,1B5C,OP-F-3 Jump with 'free' sectors.
  6430. 1B41 RES 0,(CHFLAG) Signal 'read file' if the file is
  6431. already present on cartridge.
  6432. 1B45 LD A,(RECNUM) Jump if this is not the 1st record.
  6433. 1B48 OR A
  6434. 1B49 JR NZ,1B57,OP-F-2
  6435. 1B4B PUSH IX Make HL point to the data buffer.
  6436. 1B4D POP HL
  6437. 1B4E LD DE,+0052
  6438. 1B51 ADD HL,DE
  6439. 1B52 CALL 1346,CHKS-BUFF Calculate new DCHK checksum.
  6440. 1B55 JR Z,1B6C,OF-F-5 Jump it it is equal to the old one.
  6441. 1B57 OP-F-2 CALL 117D,GET-R-2 Fetch first record of file.
  6442. 1B5A JR 1B6C,OP-F-5 Jump forward.
  6443. 1B5C OP-F-3 CALL 12FE,RES-B-MAP Reset map bit to signal 'free sector'
  6444. 1B5F OP-F-4 CALL 1312,DEC-SECT Decrease SECTOR.
  6445. 1B62 JR NZ,1B3A,OP-F-1 Consider all 255 sectors.
  6446. 1B64 RES 1,(RECFLG) 'No EOF'.
  6447. 1B68 RES 2,(RECFLG) 'PRINT-type file' (opened for writing)
  6448. 1B6C OP-F-5 POP HL Restore stream 'stream data'.
  6449. 1B6D RET Finished.
  6450.  
  6451. The Microdrive command routines
  6452.  
  6453. THE 'FORMAT' COMMAND ROUTINE
  6454. The action of FORMATting a new cartridge is performed by this subroutine. It is entered with the drive number into \
  6455. D-STR1, the cartridge name address and length into N-STR1.
  6456.  
  6457. 1B6E FORMAT CALL 0FE8,SET-T-MCH Create channel and map.
  6458. 1B71 LD A,(CHDRIV) Fetch drive number.
  6459. 1B74 CALL 182A,SW-MOTOR Turn on the motor.
  6460. 1B77 LD BC,+32C8 Wait before checking the write-
  6461. 1B7A CALL 18FA,DELAY-BC protect tab.
  6462. 1B7D DI Disable interrupts.
  6463. 1B7E IN A,(+EF) Continue only if the tab is
  6464. 1B80 AND +01 present.
  6465. 1B82 JR NZ,1B86,FORMAT-1
  6466.  
  6467. 'Drive 'write' protected'
  6468.  
  6469. 1B84 RST 20,SH-ERR Call the error handling routine.
  6470. 1B85 DEFB +0E
  6471.  
  6472. 1B86 FORMAT-1 LD A,+E6 Start writing.
  6473. 1B88 OUT (+EF),A
  6474. 1B8A LD BC,+00FF Pass through 255 sectors.
  6475. 1B8D LD (SECTOR),BC
  6476. 1B91 PUSH IX Make DE point to HDNAHE.
  6477. 1B93 POP HL
  6478. 1B94 LD DE,+002C
  6479. 1B97 ADD HL,DE
  6480. 1B98 EX DE,HL
  6481. 1B99 LD HL,+FFE2 Now make HL point to CHNAME
  6482. 1B9C ADD HL,DE (i.e. cartridge name).
  6483. 1B9D LD BC,+000A Name length.
  6484. 1BA0 LDIR Copy cartridge name into HDNAME.
  6485. 1BA2 XOR A Use 'invisible' name by storing zero
  6486. 1BA3 LD (RECNAM),A as first character of the record name.
  6487. 1BA6 SET 0,(HDFLAG) Mark the header block.
  6488. 1BAA RES 0,(RECFLG) Mark the data block.
  6489. 1BAE SET 1,(RECFLG) Mark as 'EOF' block.
  6490. 1BB2 PUSH IX Make HL point to the start of the
  6491. 1BB4 POP HL data buffer.
  6492. 1BB5 LD DE,+0052
  6493. 1BB8 ADD HL,DE
  6494.  
  6495. Now the data buffer is filled with bytes +FC; and the checksums are calculated.
  6496.  
  6497. 1BB9 LD B,+00 Counts 256 bytes.
  6498. 1BBB LD A,+FC The byte to be stored.
  6499. 1BBD FILL-B-F LD (HL),A Fill 256 bytes.
  6500. 1BBE INC HL
  6501. 1BBF BJNZ 1BBD,FILL-B-F
  6502. 1BC1 FILL-B-F2 LD (HL),A Fill next 256 bytes.
  6503. 1BC2 INC HL
  6504. 1BC3 DJNZ 1BC1,FILL-B-F2
  6505. 1BC5 PUSH IX Point to start of data block
  6506. 1BC7 POP DE workspace (i.e. RECFLG).
  6507. 1BC8 LD HL,+0043
  6508. 1BCB ADD HL,DE
  6509. 1BCC CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
  6510. 1BCF LD DE,+000F Make HL point to the data buffer.
  6511. 1BD2 ADD HL,DE
  6512. 1BD3 CALL 1346,CHKS-BUFF
  6513.  
  6514. Now this data block is written in all sectors with HDNUMB numbered from 254 to 1
  6515.  
  6516. 1BD6 WR-F-TEST CALL 1312,DEC-SECT Decrease SECTOR.
  6517. 1BD9 JR Z,1C0A,TEST-SCT Jump when SECTOR has reached zero.
  6518. 1BDB LD (HDNUMB),C Take HDNUMB from SECTOR.
  6519. 1BDE PUSH IX Make HL point to the start of the
  6520. 1BE0 POP HL header workspace, i.e. HDFLAG.
  6521. 1BE1 LD DE,+0028
  6522. 1BE4 ADD HL,DE
  6523. 1BE5 CALL 1341,CHKS-HD-R Calculate HDCHK checksum.
  6524. 1BE8 LD DE,+FFF4 Make HL point to the header block
  6525. 1BEB ADD HL,DE preamble.
  6526. 1BEC CALL 1872,OUT-M-HD Write the header onto the cartridge.
  6527. 1BEF LD BC,+01B2 Wait to create part of the first gap.
  6528. 1BF2 CALL 18FA,DELAY-BC
  6529. 1BF5 PUSH IX Make HL point to data block preamble.
  6530. 1BF7 POP HL
  6531. 1BF8 LD DE,+0037
  6532. 1BFB ADD HL,DE
  6533. 1BFC CALL 1878,OUT-M-BUF Write the data block.
  6534. 1BFF LD BC,+033F Part of the second gap is created.
  6535. 1C02 CALL 1BFA,DELAY-BC
  6536. 1C05 CALL 18E9,TEST-BRK Give an error if BREAK has been
  6537. pressed.
  6538. 1C08 JR 18D6,WR-F-TEST Continue with next sector.
  6539. 1C0A TEST-SCT LD A,+EE Stop writing.
  6540. 1C0C OUT (+EF),A
  6541. 1C0E LD A,(CHDRIV) Fetch drive number.
  6542. 1C11 CALL 17F7,SEL-DRIVE Start motor.
  6543.  
  6544. Now the sectors contain 'test data', and are to be read back to see if they are usable. If the checksums are correct, \
  6545. the appropriate map bit is reset to signal 'free for use' sectors.
  6546.  
  6547. 1C14 LD BC,+00FF Pass through 255 sectors,
  6548. 1C17 LD (SECTOR),BC
  6549. 1C1B CHK-SCT CALL 12C4,GET-H-HD2 Fetch a header.
  6550. 1C1E CALL 12DF,CHECK-MAP Check map bit and jump with
  6551. 1C21 JR Z,1C3E,CHK-NSECT examined sectors.
  6552. 1C23 PUSH IX Make HL point to start of data block
  6553. 1C25 POP HL workspace (i.e. RECFLG).
  6554. 1C26 LD DE,+0043
  6555. 1C29 ADD HL,DE
  6556. 1C2A CALL 18A9,GET-M-BF Fetch data block.
  6557. 1C2D CALL 1341,CHKS-HD-R Calculate DESCHK checksum.
  6558. 1C30 JR NZ,1C3E,CHK-NSECT Jump with faulty sectors.
  6559. 1C32 LD DE,+000F Make HL point to the data buffer.
  6560. 1C35 ADD HL,DE Start of data buffer.
  6561. 1C36 CALL 1346,CHKS-BUFF Calculate DCHK checksum.
  6562. 1C39 JR NZ,1C3E,CHK-NSECT Jump with faulty sectors.
  6563. 1C3B CALL 12FE,RES-B-MAP Reset map bit with usable sectorS.
  6564. 1C3E CHK-NSECT CALL 1312,DEC-SECT Decrease SECTOR.
  6565. 1C41 JR NZ,1C1B,CHK-SCT Check all sectors.
  6566. 1C43 CALL 1E3E,IN-CHK Initialise RECFLG, BECLEN, and DESCHK.
  6567.  
  6568. At this point all sectors that have been found 'usable' (marked with a reset bit in the map) are written with RECFLG \
  6569. and RECLEN zeroed, as to mark them 'working' for future use.
  6570.  
  6571. 1C46 MARK-FREE CALL 1264,CHK-FULL Jump until all bits in the map
  6572. 1C49 JR NZ,1C53,MK-BLK are made set.
  6573. 1C48 XOR A Turn off drive motors.
  6574. 1C4C CALL 17F7,SEL-DRIVE
  6575. 1C4F CALL 10C4,DEL-M-BUF Reclaim "m" channel and map.
  6576. 1C52 RET Finished.
  6577. 1C53 MK-BLK CALL 1275,SEND-BLK Write data block in the next 'free'
  6578. sector.
  6579. 1C56 JR 1C46,MARK-FREE Jump back.
  6580.  
  6581. THE 'CAT' COMMAND ROUTINE
  6582. This subroutine makes a CATalogue of the cartridge inserted in the drive whose number must be specified by D-STR1. \
  6583. S-STR1 must hold the stream to which the catalogue is to be directed.
  6584.  
  6585. 1C58 CAT LD A,(S-STR1) Fetch stream number.
  6586. 1C5B RST 10,CALBAS Call CHAN-OPEN to select the
  6587. 1C5C DEFW +1601 specified stream.
  6588. 1C5E CALL 0FE8,SET-T-MCH Set a temporary "m" channel.
  6589. 1C61 LD A,(CHDRIV) Fetch drive number.
  6590. 1C64 CALL 17F7,SEL-DRIVE Turn on drive motor.
  6591. 1C67 LD BC,+00FF Pass through 255 sectors.
  6592. 1C6A LD (SECTOR),BC
  6593. 1C6E CAT-LP CALL 12C4,GET-M-HD2 Fetch a header.
  6594. 1C71 CALL 1E53,G-RDES Fetch record descriptor.
  6595. 1C74 JR NZ,1C6E,CAT-LP Repeat until data is correct.
  6596. 1C76 LD A,(RECFLG) The sector is 'free for use' when
  6597. 1C79 OR (RECLEN-hi) bit 1 of both RECFLG and RECLEN-hi
  6598. 1C7C AND +02 are reset (see comment after 1C43).
  6599. 1C7E JR NZ,1C85,IN-NAME Jump if not a 'free' sector.
  6600. 1C80 CALL 12FE,RES-B-MAP Reset map bit if it is a 'free'
  6601. sector.
  6602. 1C83 JR 1CEE,F-N-SCT Continue with next sector.
  6603.  
  6604. If the current sector is not 'free', then the name of the file held in it is to be collected and inserted in \
  6605. alphabetical order into the data buffer of the "m" channel. Names starting with CHR$ 0 are refused.
  6606.  
  6607. 1C85 IN-NAME LD A,(RECNAM) Fetch first character of file name.
  6608. 1C88 OR A Continue with next sector if this is
  6609. 1C89 JR Z,1CEE,F-N-SCT CHR$ 0.
  6610. 1C8B PUSH IX Make HL point to the data buffer.
  6611. 1C8D POP HL
  6612. 1C8E LD DE,+0052
  6613. 1C91 ADD HL,DE
  6614. 1C92 LD DE,+000A Length of filename.
  6615. 1C95 LD B,+00 B is initiallly cleared.
  6616. 1C97 LD C,(CHREC) Start with 'file count' cleared.
  6617.  
  6618. The following loop tests to make sure that the name of the current record is not already stored in the buffer.
  6619.  
  6620. 1C9A SE-NAME LD A,C Jump forward when all existing names
  6621. 1C9B OR A have been examined.
  6622. 1C9C JR Z,1CD4,INS-NAME
  6623. 1C9E PUSH HL Save registers.
  6624. 1C9F PUSH IX
  6625. 1CA1 PUSH BC
  6626. 1CA2 LD B,+0A Counts characters in a name.
  6627. 1CA4 T-NA-1 LD A,(HL) Fetch a character from buffer.
  6628. 1CA5 CF (RECNAM) Compare against RECNAM.
  6629. 1CA8 JR NZ,1CAF,T-NA-2 Jump if they do not match.
  6630. 1CAA INC HL Point to next character,
  6631. 1CAB INC IX
  6632. 1CAD DJNZ 1CA4,T-NA-1 Loop until all the names have been
  6633. compared.
  6634. 1CAF T-NA-2 POP BC Restore registers.
  6635. 1CB1 POP IX
  6636. 1CB2 POP HL
  6637. 1CB3 JR Z,1CEE,F-N-SCT Continue with next sector if the name
  6638. is already stored.
  6639. 1CB5 JR NC,1CBB,ORD-NAM Jump if the name is surely not in the
  6640. buffer (i.e. 'lower' than the current
  6641. one).
  6642. 1CB7 ADD HL,DE Otherwise point to next name.
  6643. 1CB8 DEC C Decrease number of names to be
  6644. examined.
  6645. 1CB9 JR 1C9A,SE-NAME Loop back.
  6646.  
  6647. The address at which the name is to be inserted has been calculated; the following names are moved down to create the \
  6648. space for storing the new name.
  6649.  
  6650. 1CBB ORD-NAM PUSH HL Save registers.
  6651. 1CBC PUSH DE
  6652. 1CBD PUSH BC
  6653. 1CBE PUSH HL
  6654. 1CBF SLA C Multiply by two the number of names
  6655. to be moved down.
  6656. 1CC1 LD H,B Move result into HL (B holds 0).
  6657. 1CC2 LD L,C
  6658. 1CC3 ADD HL,BC Multiply this by 5, to get in HL the
  6659. 1CC4 ADD HL,BC number of bytes to be moved down
  6660. 1CC5 ADD HL,BC (i.e. number of names * 10).
  6661. 1CC6 ADD HL,BC
  6662. 1CC7 LD B,H Move into BC the length of the block
  6663. 1CC8 LD C,L to be moved.
  6664. 1CC9 POP HL Restore address where the current
  6665. name is to be inserted.
  6666. 1CCA DEC HL Make HL point to the last character
  6667. 1CCB ADD HL,BC of the last name.
  6668. 1CCC EX DE,HL Calculate into DE the address 'HL+10'.
  6669. 1CCD ADD HL,DE
  6670. 1CCE EX DE,HL
  6671. 1CCF LDIR Move down the required names (leaving
  6672. 10 bytes for the current name).
  6673. 1CD1 POP BC Restore registers.
  6674. 1CD2 POP DE
  6675. 1CD3 POP HL
  6676. 1CD4 INS-NAME PUSH IX Save channel start address.
  6677. 1CD6 LD B,+0A Ten characters in a name.
  6678. 1CD8 MOVE-NA LD A,(IX+RECNAM) Fetch a character from the name.
  6679. 1CDB LD (HL),A Store in the buffer.
  6680. 1CDC INC IX Point to next location.
  6681. 1CDE INC HL
  6682. 1CDF DJNZ 1CB8,MOVE-NA Loop until the whole name has been
  6683. transferred.
  6684. 1CE1 POP IX Restore channel start address.
  6685. 1CE3 LD A,(CHREC) Fetch number of names in the buffer.
  6686. 1CE6 INC A Include current name in the count.
  6687. 1CE7 LD (CHREC),A Store new number.
  6688. 1CEA CP +32 Jump if 50 names have been collected
  6689. 1CEC JR Z,1CF4,BF-FILLED
  6690. 1CEE F-N-SCT CALL 1312,BEC-SECT Decrease SECTOR.
  6691. 1CF1 JP NZ,1C6E,CAT-LP Repeat for all 255 sectors.
  6692.  
  6693. Now the file names are in the data buffer. CHREC holds the number of names stored. First the cartridge name is printed \
  6694. onto the selected stream.
  6695.  
  6696. 1CF4 BF-FILLED PUSH IX Save channel base address.
  6697. 1CF6 XOR A Switch off drive motor.
  6698. 1CF7 CALL 17F7,SEL-DRIVE
  6699. 1CFA PUSH IX Make HL point to HDNAME.
  6700. 1CFC POP HL
  6701. 1CFD LD DE,+002C
  6702. 1D00 ADD HL,DE
  6703. 1D01 CALL 1D50,PRNAME Print cartridge name.
  6704. 1D04 LD A,+0D Print a carriage return.
  6705. 1D06 CALL 1D66,PRCHAR
  6706. 1D09 PUSH IX Make HL point to the data buffer.
  6707. 1D0B POP HL
  6708. 1D0C LD DE,+0052
  6709. 1D0F ADD HL,DE
  6710. 1D11 LD B,(CHREC) Fetch number of stored names.
  6711. 1D13 LD A,B Jump forward if no names have been
  6712. 1D14 OR A stored.
  6713. 1D15 JR Z,1D1C,NONAMES
  6714. 1D17 OT-NAMS CALL 1D53,PRNAME Print all filenames.
  6715. 1D1A DJNZ 1D17,OT-NAMS
  6716. 1D1C NONAMES CALL 1D38,FREESECT Calculate number of 'free' sectors
  6717. 1D1F LD A,E into A.
  6718. 1D20 SRL A Divide by two, giving the kilobytes
  6719. left.
  6720. 1D22 RST 10,CALBAS Call STACK-A to store this value on
  6721. 1D23 DEFW +2D28 the calculator stack.
  6722. 1D25 LD A,+0D Print a carriage return.
  6723. 1D27 CALL 1D66,PRCHAR
  6724. 1D2A RST 10,CALBAS Call PRINT-FP to print the number of
  6725. 1D2B DEFW +2DE3 kilobytes left.
  6726. 1D2D LD A,+0D Print the final carriage return.
  6727. 1D2F CALL 1D66,PRCHAR
  6728. 1D32 POP IX Restore channel start address.
  6729. 1D34 CALL 10C4,DEL-M-BUF Reclaim the channel.
  6730. 1D37 RET Finished.
  6731.  
  6732. THE 'FREESECT' SUBROUTINE
  6733. This subroutine is called to calculate the number of 'free sectors' (I...> bits reset in the map). The number is \
  6734. returned in the I register.
  6735.  
  6736. 1D38 FREESECT LD L,(CHMAP-lo) Fetch address of map.
  6737. 1D3B LD H,(CHMAP-hi)
  6738. 1D3E LD E,+00 Start with E cleared.
  6739. 1D40 LD C,+20 Length of map.
  6740. 1D42 FR-SC-LP LD A,(HL) Fetch a byte from the map.
  6741. 1D43 INC HL Advance the pointer.
  6742. 1D44 LD B,+08 Loop for 8 bits.
  6743. 1D46 FR-S-LPB RRA Jump if this bit is set,
  6744. 1D47 JR C,14DA,FR-S-RES
  6745. 1D49 INC E Otherwise increment counter.
  6746. 1D4A FR-S-RES DJNZ 1D46,FR-S-LPB Repeat for all 8 bits.
  6747. 1D4C DEC C Repeat for all bytes in the map.
  6748. 1D4D JR NZ,1D42,FR-SC-LP
  6749. 1D4F RET Finished.
  6750.  
  6751. THE 'PRNAME' SUBROUTINE
  6752. This is used from the CAT command routine to print a file-name starting from the address held into the HL register.
  6753.  
  6754. 1D50 PRNAME PUSH BC Save BC register.
  6755. 1D51 LD B,+0A Counts 10 characters.
  6756. 1D53 PRNM-LP LD A,(HL) Fetch a character.
  6757. 1D54 CALL 1D66,PRCHAR Print it.
  6758. 1D57 INC HL Increment pointer.
  6759. 1D58 DJNZ 1D53,PRNM-LP Loop until the whole name has been
  6760. printed.
  6761. 1D5A LD A,+0D Print a carriage return.
  6762. 1D5C CALL 1D66,PRCHAR
  6763. 1D5F PUSH HL Save the pointer.
  6764. lD60 RST 10,CALBAS Call main ROM 'TEMPS' subroutine.
  6765. 1D61 DEFW +0D4D
  6766. 1D63 POP HL Restore registers.
  6767. 1D64 POP BC
  6768. 1D65 RET
  6769.  
  6770. THE 'PRCHAR' SUBROUTINE
  6771. The character whose code is held in the A register is sent over the currently selected stream.
  6772.  
  6773. 1D66 PRCHAR PUSH IX Save channel base address.
  6774. 1D68 RST 10,CALBAS Call restart 'PRINT-A' to print the
  6775. 1D69 DEFW +0010 character.
  6776. 1D6B POP IX Restore channel base address.
  6777. 1D6D RET Finished.
  6778.  
  6779. THE 'ERASE' COMMAND SUBROUTINE
  6780. This is also called by using 'hook code' +24. The subroutine is entered with
  6781. D-STR1 holding the drive number and N-STR1 holding the length and the start of the filename, Note that H'L' is \
  6782. corrupted.
  6783.  
  6784. 1D6E ERASE CALL 0FE8,SET-T-MCH Set a temporary "m" channel.
  6785. 1D71 LD A,(CHDRIV) Fetch drive number.
  6786. 1D74 CALL 17F7,SEL-DRIVE Turn on drive motor.
  6787. 1D77 IN A,(+EF) Continue only if the write-nrotect
  6788. 1D79 AND +01 tab is present.
  6789. 1D7B JR NZ,107F,ERASE-1
  6790.  
  6791. 'Drive write protected'
  6792.  
  6793. 1D7D RST 20,SH-ERR Call the error handling routine.
  6794. 1D7E DEFB +0E
  6795.  
  6796. 1D7F ERASE-1 PUSH IX Point to the data buffer.
  6797. 1D81 POP HL
  6798. 1D82 LD DE,+0052
  6799. 1D85 ADD HL,DE
  6800. 1D86 PUSH HL Copy this address into DE.
  6801. 1D87 POP DE
  6802.  
  6803. Now the first 32 locations in the data buffer are cleared. These locations act as a 'pseudo-map', used to mark the \
  6804. sectors to be erased,
  6805.  
  6806. 1D88 INC DE Point to next location.
  6807. 1D89 LD BC,+001F Gap length - 1.
  6808. 1D8C XOR A Clear the first location.
  6809. 1D8D LD (HL),A
  6810. 1D8E LDIR Clear all locations.
  6811. lD90 LD A,+FF CHREC is made holding 255.
  6812. 1D92 CD (CHREC),A
  6813. 1D95 LD BC,+04FB SECTOR is initialised to 'five passes
  6814. 1D98 LD (SECTOR),BC of the tape'.
  6815.  
  6816. The cartridge is searched for the sectors to be erased, and when any such sector is found, the relevant 'pseudo-map' \
  6817. bit is set. A 'normal' map is also set-up.
  6818.  
  6819. 1D9C ERASE-LP CALL 1312,DEC-SECT Decrease SECTOR.
  6820. 1D9F JR Z,1DF8,ERASE-MK Make the ERASE when it reaches 0.
  6821. 1DA1 CALL 12C4,GET-M-HD2 Fetch a header.
  6822. 1DA4 CALL 1E53,G-RDES Fetch record descriptor.
  6823. 1DA7 JR NZ,1DDA,TST-NUM Jump with any error.
  6824. 1DA9 LD A,(RECFLG) Jump it this record is not 'tree'.
  6825. 1DAC OR (RECLEN-hi)
  6826. lDAF AND +02
  6827. 1DB1 JR NZ,1DB8,ERASE-2
  6828. 1DB3 CALL 12FE,RES-B-MAP Otherwise reset map bit to indicate
  6829. 'free sector'.
  6830. 1DB6 JR 1DDA,TST-NUM Jump forward.
  6831.  
  6832. The name of the current record is compared against that of the file to be erased. If the comparison is successful, the \
  6833. 'pseudo-map' bit is set to mark the sector.
  6834.  
  6835. 1DB8 ERASE-2 PUSH IX MAke HL point to RECNAM.
  6836. 1DBA POP HL
  6837. 1DBB LD DE,+0047
  6838. 1DBE ADD HL,DE
  6839. 1DBF LD BC,+000A Counts ten characters in a name.
  6840. 1DC2 CALL 131E,CHK-NAME Compare against CHNAME.
  6841. 1DC5 JR NZ,1DDA,TST-NUM Jump if it does not equal.
  6842. 1DC7 CALL 1306,TEST-PMAP Get position of pseudo-map bit.
  6843. 1DCA LD A,B Fetch bit position.
  6844. 1DCB OR (HL) Set the pseudo-map bit.
  6845. 1DCC LD (HL),A
  6846. 1DCD BIT 1,(RECFLG) Jump if this is not the EOF block.
  6847. 1DD1 JR Z,1DDA,TST-NUN
  6848. 1DD3 LD A,(RECNUM) Otherwise increment record number
  6849. 1DD6 INC A and store it into CHMREC, giving the
  6850. 1DD7 LD (CHREC),A number of sectors that composes the
  6851. file.
  6852. 1DDA TST-NUM PUSH IX Make HL point to the 'pseudo-map'.
  6853. 1DDC POP HL
  6854. 1DDD LD DE,+0052
  6855. 1DE0 ADD HL,DE
  6856. 1DE1 LD E,+00 Clear E register.
  6857. 1DE3 LD C,+20 Length of the pseudo-map.
  6858. IDE5 LP-P-MAP LD A,(HL) Fetch pseudo-map byte.
  6859. 1DE6 INC HL Advance the pointer.
  6860. 1DE7 LD B,+08 Counts 8 bits.
  6861. 1DE9 LP-B-MAP RRA Jump if this bit is reset.
  6862. 1DEA JR NC,1DED,NOINC-C
  6863. 1DEC INC E Otherwise increment counter.
  6864. 1DED NOINC-C DJNZ 1DE9,LP-B-MAP Loop for all 8 bits.
  6865. 1DEF DEC C Decrement map length.
  6866. 1DF0 JR NZ,1DE5,LP-P-MAP Loop until the whole map has been
  6867. examined.
  6868. 1DF2 LD A,(CHREC) Fetch number of records that composes
  6869. the file.
  6870. 1DF5 CP E Compare with number of records found.
  6871. 1DF6 JR NZ,1D9C,ERASE-LP Continue until all records have been
  6872. found (or five passes of the tape
  6873. have been made).
  6874.  
  6875. A 'free' sector descriptor is written in all records of the file to be erased.
  6876.  
  6877. 1DF8 ERASE-MK CALL 1E3E,IN-CHK Set 'free record' attributes.
  6878. 1DFB ERASE-MK2 CALL 12C4,GET-M-HD2 Fetch a header.
  6879. 1DFE CALL 1306,TEST-PMAP Jump if this is not the header of a
  6880. 1E01 JR Z,1E26,T-OTHER record to be erased.
  6881. 1E03 PUSH HL Save map bit address and position.
  6882. 1E04 PUSH BC
  6883. 1E05 LD A,+E6 Start writing.
  6884. 1E07 OUT (+EF),A
  6885. 1E09 LD BC,0168 Wait to insert part of the first gap.
  6886. 1E0C CALL 18FA,DELAY-BC
  6887. 1E0F PUSH IX Make HL point to the data block
  6888. 1E11 POP HL preamble.
  6889. 1E12 LD DE,+0037
  6890. 1E15 ADD HL,DE
  6891. 1E16 CALL 1878,OUT-M-BUF Write the 'free record' descriptor.
  6892. 1E19 LD A,+EE Stop writing.
  6893. 1E1B OUT (+EF),A
  6894. 1E1D CALL 12FE,RES-B-MAP Reset map bit.
  6895. 1E20 POP BC Restore pseudo-map bit position and
  6896. 1E21 POP HL address.
  6897. 1E22 LD A,B Reset the appropriate bit.
  6898. 1E23 CPL
  6899. 1E24 AND (HL)
  6900. 1E25 LD (HL),A
  6901.  
  6902. If the pseudo-map contains at least one bit set, there are other records to be erased.
  6903.  
  6904. 1E26 T-OTHER PUSH IX Make HL point to the pseudo-map.
  6905. 1E28 POP HL
  6906. 1E29 LD DE,+0052
  6907. 1E2C ADD HL,DE
  6908. 1E2D LD B,+20 Length of pseudo-map.
  6909. 1E2F CHK-W-MAP LD A,(HL) Fetch a byte.
  6910. 1E30 OR A Jump back if the byte is not zero
  6911. 1E31 JR NZ,1DFB,ERASE-MK2 (i.e. there are other records to be
  6912. erased).
  6913. 1E33 INC HL Next location.
  6914. 1E34 DJNZ 1E2F,CHK-W-MAP Loop for the whole map.
  6915. 1E36 XOR A Switch off drive motor.
  6916. 1E37 CALL 17F7,SEL-DRIVE
  6917. 1E3A CALL 10C4,DEL-M-BUF Reclaim channel and map.
  6918. 1E3D RET Finished.
  6919.  
  6920. THE 'SIGNAL "FREE SECTOR"' SUBROUTINE
  6921. This subroutine is called from the FORMAT and ERASE command routines to mark the current record descriptor as 'free \
  6922. sector' identifier.
  6923.  
  6924. 1E3E IN-CHK XOR A Clear RECFLG and RECLEN.
  6925. 1E3F LD (RECFLG),A
  6926. 1E42 LD (RECLEN-lo),A
  6927. 1E45 LD (RECLEN-hi),A
  6928. 1E48 PUSH IX Make HL point to RECFLG.
  6929. 1E4A POP HL
  6930. 1E4B LD DE,+0043
  6931. 1E4E ADD HL,DE
  6932. 1E4F CALL 1341,CMKS-HD-R Restore DESCHK checksum.
  6933. 1E52 RET Finished.
  6934.  
  6935. THE 'OBTAIN A RECORD DESCRIPTOR' SUBROUTINE
  6936. This subroutine is used from the FORMAT and ERASE coamnand routines to fetch from the current Microdrive unit the \
  6937. record descriptor held in the current sector (i.e. RECFLG...DESCHK). The zero flag is returned reset with any error.
  6938.  
  6939. 1E53 G-RDES PUSH IX Make HL point to RECFLG.
  6940. 1E55 POP HL
  6941. 1E56 LD DE,+0043
  6942. 1E59 ADD HL,DE
  6943. 1E5A CALL 18A3,GET-M-HD Fetch record descriptor.
  6944. 1E5D CALL 1341,CHKS-MD-R Calculate new checksum.
  6945. 1E60 RET NZ Return if it is wrong.
  6946. 1E61 BIT 0,(RECFLG) Return with zero flag reset if this
  6947. 1E65 RET is a header.
  6948.  
  6949. THE 'CALLS TO THE COMMAND ROUTINES'
  6950. The six following calls are entered from the appropriate command syntax routine; on return from the command routine, \
  6951. the control returns to END1.
  6952.  
  6953. 1E66 ERASE-RUN CALL 1D6E,ERASE
  6954. 1E69 JR 1E84,ENDC
  6955. 1E6B MOVE-RUN CALL 13F1,MOVE
  6956. 1E6E JR 1E84,ENDC
  6957. 1E70 CAT-RUN CALL 1C58,CAT
  6958. 1E73 JR 1E84,ENDC
  6959. 1E75 FOR-RUN CALL 1B6E,FORMAT
  6960. 1E78 JR 1E84,ENDC
  6961. 1E7A OP-RUN CALL 1AF0,OP-M-STRM
  6962. 1E7D JR 1E84,ENDC
  6963. 1E7F SAVE-RUN CALL 14DA,SA-DRIVE
  6964. 1E82 JR 1E84,ENDC
  6965. 1E84 ENDC JP 05Cl,END1
  6966.  
  6967. The 'not used' routines
  6968.  
  6969. The following are four subroutines that are never called from the shadow ROM code; these routines are however \
  6970. described below as they may be useful to the programmer.
  6971.  
  6972. THE 'DISP-HEX' SUBROUTINE
  6973. The contents of the A register are displayed on the screen in hexadecimal. All registers are preserved, excluding A.
  6974.  
  6975. 1E87 DISP-HEX PUSH AF Save A register.
  6976. 1E88 RRA Shift left nibble to right.
  6977. 1E89 RRA
  6978. 1E8A RRA
  6979. 1E8B RRA
  6980. 1E8C CALL 1E90,DISP-NIB Print the first digit.
  6981. 1E8F POP AF Restore value.
  6982. 1E90 DISP-NIB AND +0F Clear left nibble.
  6983. 1E92 CP +0A Jump if the value is lower than 9.
  6984. 1E94 JR C,1E98,CONV-1
  6985. 1E96 ADD A,+07 Otherwise add +07 to reach the code of
  6986. A..F.
  6987. 1E98 CONV-1 ADD A,+30 Add offset for ASCII code.
  6988. 1E9A CALL 1EA9,DISP-CH Print the digit.
  6989. 1E9D RET Finished.
  6990.  
  6991. THE 'DISP-HEX2' SUBROUTINE
  6992. This performs the same task as the preceding one, but the hex number is followed by a space. All registers are \
  6993. preserved.
  6994.  
  6995. 1E9E DISP-HEX2 PUSH AF Save A register.
  6996. 1E9F CALL 1E87,DISP-HEX Print the hex number.
  6997. 1EA2 LD A,+20 Follow with a space.
  6998. 1EA4 CALL 1EA9,DISP-CH
  6999. 1EA7 POP AF Restore A.
  7000. 1EA8 RET Finished.
  7001.  
  7002. THE 'DISP-CH' SUBROUTINE
  7003. This subroutine prints on the screen the character held in the accumulator. All registers are preserved.
  7004.  
  7005. 1EA9 DISP-CH PUSH HL Save registers.
  7006. 1EAA PUSH DE
  7007. 1EAB PUSH BC
  7008. 1EAC PUSH AF
  7009. 1EAD EXX Save alternate registers.
  7010. 1EAE PUSH HL
  7011. 1EAF PUSH DE
  7012. 1EB0 PUSH BC
  7013. 1EB1 PUSH AF
  7014. 1EB2 LD HL,(CURCHL) Save also current channel address.
  7015. 1EB5 PUSH HL
  7016. 1EB6 PUSH AF Save character to be printed.
  7017. 1EB7 LD A,+02 Select stream 2 (screen).
  7018. 1EB9 RST 10,CALBAS Call CHAN-OPEN to select the stream.
  7019. 1EBA DEFW +1601
  7020. 1EBC POP AF Restore character.
  7021. 1EBD RST 10,CALBAS Call PRINT-A restart to print the
  7022. 1EBE DEFW +0010 character.
  7023. 1EC0 POP HL Restore old channel address.
  7024. 1EC1 LD (CURCHL),A
  7025. 1EC4 POP AF Restore alternate registers.
  7026. 1EC5 POP BC
  7027. 1EC6 POP DE
  7028. 1EC7 POP HL
  7029. 1EC8 EXX Restore normal registers.
  7030. 1EC9 POP AF
  7031. 1ECA POP BC
  7032. 1ECB POP DE
  7033. 1ECC POP HL
  7034. 1ECD RET
  7035.  
  7036. THE 'HEX-LINE' SUBROUTINE
  7037. This subroutine displays the values of the ten bytes from the location passed in the HL register. Again all registers \
  7038. are preserved.
  7039.  
  7040. 1ECE HEX-LINE PUSH HL Save registers.
  7041. 1ECF PUSH BC
  7042. 1ED0 PUSH AF
  7043. 1ED1 LD B,+0A Counts 10 bytes.
  7044. 1ED3 HEX-LINE2 LD A,(HL) Fetch a byte.
  7045. 1ED4 CALL 1E9E,DISP-HEX2 Display it in hex and follow with a
  7046. space.
  7047. 1ED7 INC HL Point to next byte.
  7048. 1ED8 DJNZ 1ED3,HEX-LINE2 Loop for all l0 bytes.
  7049. 1EDA LD A,+0D Finally print a carriage return.
  7050. 1EDC CALL 1EA9,DISP-CH
  7051. 1EDF POP AF Restore registers.
  7052. 1EE0 POP BC
  7053. 1EEl POP HL
  7054. 1EE2 RET Finished.
  7055.  
  7056. 1EE3...1FFF Unused locations (all set to +FF).
  7057. APPENDIX 1
  7058.  
  7059. Labels sorted by address value
  7060. (For edition 1 Shadow ROM)
  7061.  
  7062. 0000 MAIN-ROM 0008 ST-SHADOW 0010 CALBAS 0018 CHKSYNTAX
  7063. 0020 SH-ERR 0028 ROMERR 0030 NEWVARS 0038 INT-SERV
  7064. 003A TEST-SP 0040 RMERR-2 0066 NMINT-SRV 0068 ST-ERROR
  7065. 0077 CHECK-SP 0081 CALBAS-2 009A START-2 00A5 START-3
  7066. 00BC START-4 00E7 NREPORT-0 00E9 TEST-CODE 00FB COPYCHADD
  7067. 011B RUNTIME 0130 PROG-LINE 0133 SC-L-LOOP 0139 NREPORT-1
  7068. 013B TEST-LOW 0144 LINE-LEN 014E SKIP-NUN 0152 EACH-ST
  7069. 015D CHKEND 0165 CHKEVEN 0169 CHKEND-L 016F S-STAT
  7070. 0182 RCLM-NUM 01A3 NXT-1 01A5 NEXTNUM 01AA CL-WORK
  7071. 01EC ERR-V 01F0 ERR-6 01F7 CRT-VARS 0224 DEFAULT
  7072. 0235 VAR-EXIST 024D RES-VARS 0252 EACH-VAR 0258 REP-MSG
  7073. 026E FETCH-ERR 029F PR-REP-LP 02AC END-PR-MS 0486 CAT-SYN
  7074. 0494 MISSING-D 04A6 CAT-SCRN 04B2 OREPORT-1 04B4 FRTM-SYN
  7075. 04BF NO-FOR-M 04CD FOR-B-T 04D3 NOT-FOR-B 04E7 FOR-M
  7076. 04ED OPEN-SYN 0500 NOT-OP-M 051C OPEN-RS 051F NOT-OP-B
  7077. 0529 OP-M-C 052F NREPORT-C 0531 ERASE-SYN 053D MOVE-SYN
  7078. 0559 CLS#-SYN 057F CLR#-SYN 0584 NONSENSE 058E ALL-STRMS
  7079. 059F EX-D-STR 05A7 ALL-BYTES 05B1 SEPARATOR 05B7 ST-END
  7080. 05BF TEST-RET 05C1 END1 05DD RETAD-RUN 05E0 RETAD-SYN
  7081. 05E2 BREAK-PGM 05E7 EXPT-STR 05F2 EXPT-SPEC 05F5 EXP-SPEC2
  7082. 060C TEST-NEXT 061E EXPT-NUM 062D NREPORT-3 062F EXPT-NAME
  7083. 064C NREPORT-4 064E EXPT-STRM 0663 NREPORT-2 0665 CHECK-H
  7084. 066D CHECK-M-2 0681 NREPORT-5 0683 NREPORT-9 0685 TEST-MNAM
  7085. 068F TEST-STAT 06A1 NREPORT-8 06A3 EXPT-EXPR 06B0 TEST-BAUD
  7086. 06B9 EXPT-EXP1 06CC ENDHERE 0700 UNPAGE 0701 EXPT-PRMS
  7087. 0716 NO-NAME 0722 NOT-NET 073C OREP-1-2 073E LINE
  7088. 0750 END-EXPT 0753 PROC 0771 SCREEN$ 0789 CODE
  7089. 079A DEFLT-0 079F PAR-1 07A7 TEST-SAVE 07B2 PAR-2
  7090. 07B8 END-CODE 07D2 DATA 07DA NO-M-ARR 07F2 EXISTING
  7091. 07F4 NONS-BSC 07F6 G-TYPE 0803 VR-DATA 080E LD-DATA
  7092. 0819 NUM-ARR 081C END-DATA 082F SAVE-SYN 0849 SAVE-M
  7093. 084F SA-HEADER 0854 HD-LOOP 086E SA-BLOCK 0872 SA-BLK-LP
  7094. 087D S-BLK-END 0880 SA-BYTE 088E SA-NET 0891 SA-B-END
  7095. 0894 LOAD-SYN 089E VERIF-SYN 08A8 MRG-SYN 08AF LD-VF-MR
  7096. 08CD TS-L-NET 08D3 TS-L-RS 08D8 LD-HEADER 08E0 LD-HD-NET
  7097. 08E7 LD-HD-RS 08EC LD-HDR-2 08F2 TEST-TYPE 0902 NREPORT-H
  7098. 0904 TST-MERGE 0911 T-M-CODE 0919 LD-BLOCK 0930 NREPORT-L
  7099. 0932 LD-BLK-2 0941 LD-BLK-3 0952 LD-BLK-4 0959 LD-BLK-5
  7100. 0962 LD-NO-PGM 0967 MERGE-BLK 0973 NO-AUTOST 0988 TST-MR-M
  7101. 0994 TST-MR-N 09A0 MERGE-END 09A3 LD-PR-AR 09B5 LD-PROG
  7102. 09BE TST-SPACE 09C7 TST-TYPE 09DE T-LD-NET 09E8 RCLM-OLD
  7103. 09F3 CRT-NEW 0A0F END-LD-PR 0A15 SET-PROG 0A4E NO-AUTO
  7104. 0A5C LV-ANY 0A6A LV-BN 0A72 LV-N 0A79 LV-B
  7105. 0A7E LV-BN-E 0A8A VR-BN 0A8F LVBN-END 0A95 LOAD-RUN
  7106. 0AC9 SET-BAUD 0AD0 NXT-ENTRY 0AE4 END-SET 0813 OP-RS-CH
  7107. 0B47 OP-RSCHAN 0B4A OP-STREAM 0B6F T-INPUT 0B75 B-INPUT
  7108. 0B7B TCHAN-IN 0B81 BCHAN-IN 0B8E REC-BYTE 0B9A REC-PROC
  7109. 0BB1 READ-RS 0BC5 TST-AGAIN 0BD1 START-BIT 0BD8 SERIAL-IN
  7110. 0BDA BD-DELAY 0BF0 WAIT-1 0BF1 WAIT-2 0BF9 T-FURTHER
  7111. 0C1D SER-IN-2 0C1F BD-DELAY2 0C36 END-RS-IN 0C3C TCHAN-OUT
  7112. 0C46 NOT-TOKEN 0C4C NOT-GRAPH 0C57 NOT-CR 0C5A BCHAN-OUT
  7113. 0C6F BD-DEL-1 0C74 TEST-DTR 0C88 SER-OUT-L 0C8E BD-DEL-2
  7114. 0CA4 BD-DEL-3 0CA9 BORD-REST 0CB4 BRK-INOUT 0CBD CALL-INP
  7115. 0CDB IN-AGAIN 0CE1 INPUT-END 0CE5 OREPORT-8 0CEA NO-READ
  7116. 0CED ACC-CODE 0CF7 END-INPUT 0CFB INKEY$ 0D01 INK$-END
  7117. 0D0C N-INPUT 0D12 NCHAN-IN 0D1E TEST-BUFF 0D38 TST-N-EOF
  7118. 0D3F GET-N-BUF 0D45 TRY-AGAIN 0D5F TIME-OUT 0D6C NCHAN-OUT
  7119. 0D7A TEST-OUT 0D88 ST-BF-LEN 0D93 OUT-BLK-N 0DAB S-PACK-1
  7120. 0DB2 SEND-PACK 0DC5 CHKS1 0DD4 CHKS2 0DDA SENDSCOUT
  7121. 0DF6 SP-DL-1 0DFD INC-BLKN 0E05 SP-N-END 0E0F BR-DELAY
  7122. 0E12 DL-LOOP 0E18 GET-NBLK 0E27 CHKS3 0E40 BRCAST
  7123. 0E45 TEST-BLKN 0E62 GETNB-END 0E65 GET-NBUFF 0E87 CHKS4
  7124. 0E93 STORE-LEN 0EA1 GETNBF-END 0EA3 OPEN-N-ST 0EA9 OP-TEMP-N
  7125. 0EB5 OP-PERN-N 0EF5 SEND-NEOF 0F03 NET-STATE 0F0E CHK-REST
  7126. 0F15 MAKESURE 0F1E WT-SCOUT 0F21 CLAIMED 0F35 WT-SYNC
  7127. 0F4D E-READ-N 0F56 SCOUT-END 0F58 LP-SCOUT 0F5D DELAY-SC
  7128. 0F61 SEND-SC 0F72 ALL-BITS 0F7D S-SC-DEL 0F8F END-S-DEL
  7129. 0F92 INPAK 0F94 N-ACTIVE 0F9D INPAK-2 0F9E INPAK-L
  7130. 0FAE UNTIL-MK 0FBE SEND-RESP 0FC5 OUTPAK 0FCA DEL-D-1
  7131. 0FCC OUTPAK-L 0FD2 UNT-MARK 0FE8 SET-T-MCH 0FF6 CHK-LOOP
  7132. 102A NEXT-CHAN 1034 CHAN-SPC 1061 T-CH-NAME 106F TEST-MAP
  7133. 108A ST-MAP-AD 1094 FILL-MAP 10C4 DEL-M-BUF 10F5 TEST-MCHL
  7134. 110A NXTCHAN 1114 RCLM-MAP 1122 M-INPUT 112C MCHAN-IN
  7135. 1132 RWF-ERR 1134 TEST-M-BF 1158 CHK-M-EOF 1162 NEW-BUFF
  7136. 1177 GET-RECD 117D GET-R-2 1184 GET-R-LP 119E NXT-SCT
  7137. 11A3 RS-SH2 11A5 G-HD-RC 11D6 G-REC-ERR 11D8 MCHAN-OUT
  7138. 11E6 NOREAD 11FF WR-RECD 120D WRITE-PRC 121B NOFULL
  7139. 121F CP-NAME 1264 CHK-FULL 126C NXT-B-MAP 1275 SEND-BLK
  7140. 127D FAILED 128F NO-PRT 12A6 CLOSE-M 12A9 CLOSE-M2
  7141. 12B6 NOEMP 12BE ERR-RS 12C4 GET-M-HD2 12DA CHK-MAP-2
  7142. 12DF CHECK-MAP 12E2 ENTRY 12E8 ENTRY-2 12F8 ROTATE
  7143. 12FE RES-B-MAP 1306 TEST-PMAP 1312 DEC-SECT 131E CHK-NAME
  7144. 1322 ALL-CHARS 1333 ALLCHR-2 133E CHKNAM-END 1341 CHKS-HD-R
  7145. 1346 CHKS-BUFF 1349 CHKS-ALL 134C NXT-BYTE 1354 STCHK
  7146. 135F REST-STRM 1365 NXT-STRM 1377 NOTRIGHT 137E STO-DISP
  7147. 1384 UPD-POINT 1391 REST-MAP 139D LCHAN 13C1 LPEND
  7148. 13F1 MOVE 1414 M-AGAIN 141A I-AGAIN 1423 MOVE-OUT
  7149. 142E MOVE-EOF 1455 OP-STRM 1466 OP-CHAN 147F CHECK-N
  7150. 148B CHECK-R 1495 USE-R 14A4 CL-CHAN 14B8 CL-CHK-N
  7151. 14C7 EX-DSTR2 14CF ALL-BYT-2 14DA SA-DRIVE 14E8 START-SA
  7152. 14FC NEW-NAME 1530 SA-DRI-2 1538 SA-DRI-3 1552 SA-DRI-WR
  7153. 155E SA-DRI-4 1579 END-SA-DR 1580 F-M-HEAD 1591 F-HD-2
  7154. 1599 F-HD-3 15A9 LV-MCH 15DF USE-REC 15F9 LOOK-MAP
  7155. 1613 SA-MAP 1620 SA-MAP-LP 162D RE-MAP 163D RE-MAP-LP
  7156. 1648 LD-VE-M 1658 VE-M-E 1664 VE-FAIL 1666 F-REC1
  7157. 166C F-REC2 1673 UNTILFIVE 168A F-ERROR 1691 REST-N-AD
  7158. 16AC TST-PLACE 1708 CLOSE-CH 1718 CLOSE 1751 CL-RS-CH
  7159. 175E CL-N-CH 176D CL-M-CN 177F RCLM-CH 1789 UPD-STRM
  7160. 17A4 UPD-NXT-S 17B9 RCL-T-CH 17C2 EX-CHANS 17D2 CHK-TEMPM
  7161. 17DE CHK-TEMPN 17ED PT-N-CHAN 17F7 SEL-DRIVE 1802 TURN-ON
  7162. 1809 TON-DELAY 1811 REPTEST 1813 CHK-PRES 1820 NOPRES
  7163. 182A SW-MOTOR 1835 ALL-MOTRS 184B OFF-MOTOR 185C NXT-MOTOR
  7164. 1867 DEL-S-1 1872 OUT-M-HD 1878 OUT-M-BUF 187C OUT-M-BLK
  7165. 1884 NOT-PROT 1895 OUT-M-BYT 18A3 GET-M-HD 18A9 GET-M-BUF
  7166. 18AD GET-M-BLK 18B1 CHK-AGAIN 18B3 CHKLOOP 18BE CHK-AG-2
  7167. 18C0 CHK-LP-2 18D2 DR-READY 18DE IN-M-BLK 18E9 TEST-ERR
  7168. 1BFA DELAY-BC 18FB DELAY-BC1 1902 UNKN-1 191C UNKN-2
  7169. 1929 UNKN-3 1952 UNKN-4 1959 UNKN-5 1961 UNKN-6
  7170. 1968 UNKN-7 196C UNKN-8 1976 UNKN-9 1981 HOOK-CODE
  7171. 1987 CLR-ERR 19A4 HOOK-32 19A8 HOOK-31 19D9 CONS-IN
  7172. 19DE WTKEY 19EC CONS-OUT 19EF OUT-CODE 19FC PRT-OUT
  7173. 1A01 KBD-TEST 1A09 READ-SEQ 1A14 INCREC 1A17 RD-RANDOM
  7174. 1A24 CLOSE-NET 1A31 GET-PACK 1A46 GP-ERROR 1A4B RD-SECTOR
  7175. 1A51 NO-GOOD 1A63 USE-C-RC 1A81 DEL-B-CT 1A86 RD-NEXT
  7176. 1A91 WR-SECTOR 1AAD WR-S-1 1ABF WR-S-2 1AC5 RS-SH
  7177. 1AC7 WR-S-3 1AE0 CLR-BUFF 1AF0 OP-M-STRM 1B0D MAKE-PERM
  7178. 1B23 STORE-DSP 1B29 OP-TEMP-M 1B3A OP-F-1 1B57 OP-F-2
  7179. 1B5C OP-F-3 1B5F OP-F-4 1B6C OP-F-5 1B6E FORMAT
  7180. 1B86 FORMAT-1 1BBD FILL-B-F 1BC1 FILL-B-F2 1BD6 WR-F-TEST
  7181. 1C0A TEST-SCT 1C1B CHK-SCT 1C3E CHK-NSECT 1C46 MARK-FREE
  7182. 1C53 MK-BLK 1C58 CAT 1C6E CAT-LP 1C85 IN-NAME
  7183. 1C9A SE-NAME 1CA4 T-NA-1 1CAF T-NA-2 1CBB ORD-NAM
  7184. 1CD4 INS-NAME 1CD8 MOVE-NA 1CEE F-N-SCT 1CF4 BF-FILLED
  7185. 1D17 OT-NAMS 1D1C NONAMES 1D38 FREESECT 1D42 FR-SC-LP
  7186. 1D46 FR-S-LPB 1D4A FR-S-RES 1D50 PRNAME 1D53 PRNM-LP
  7187. 1D66 PRCHAR 1D6E ERASE 1D7F ERASE-1 1D9C ERASE-LP
  7188. 1DB8 ERASE-2 1DDA TST-NUM 1DE5 LP-P-MAP 1DE9 LP-B-MAP
  7189. 1DED NOINC-C 1DF8 ERASE-MK 1DFB ERASE-MK2 1E26 T-OTHER
  7190. 1E2F CHK-W-MAP 1E3E IN-CHK 1E53 G-RDES 1E66 ERASE-RUN
  7191. 1E6B MOVE-RUN 1E70 CAT-RUN 1E75 FOR-RUN 1E7A OP-RUN
  7192. 1E7F SAVE-RUN 1E84 ENDC 1E87 DISP-HEX 1E90 DISP-NIB
  7193. 1E98 CONV-1 1E9E DISP-HEX2 1EA9 DISP-CH 1ECE HEX-LINE
  7194. 1ED3 HEX-LINE2
  7195. APPENDIX 2
  7196.  
  7197. Labels sorted alphabetically
  7198. (For edition 1 Shadow ROM)
  7199.  
  7200. ACC-CODE 0CED ALL-BITS 0F72 ALL-BYT-2 14CF ALL-BYTES 05A7
  7201. ALL-CHARS 1322 ALL-MOTRS 1835 ALL-STRMS 058E ALLCHR-2 1333
  7202. B-INPUT 0B75 BCHAN-IN 0B81 BCHAN-OUT 0C5A BD-DEL-1 0C6F
  7203. BD-DEL-2 0C8E BD-DEL-3 0CA4 BD-DELAY 0BDA BD-DELAY2 0C1F
  7204. BF-FILLED 1CF4 BORD-REST 0CA9 BR-DELAY 0E0F BRCAST 0E40
  7205. BREAK-PGM 05E2 BRK-INOUT 0CB4 CALBAS 0010 CALBAS-2 0081
  7206. CALL-INP 0CBD CAT 1C58 CAT-LP 1C6E CAT-RUN 1E70
  7207. CAT-SCRN 04A6 CAT-SYN 0486 CHAN-SPC 1034 CHECK-H 0665
  7208. CHECK-M-2 066D CHECK-MAP 12DF CHECK-N 147F CHECK-R 148B
  7209. CHECK-SP 0077 CHK-AG-2 18BE CHK-AGAIN 18B1 CHK-FULL 1264
  7210. CHK-LOOP 0FF6 CHK-LP-2 18C0 CHK-M-EOF 1158 CHK-MAP-2 12DA
  7211. CHK-NAME 131E CHK-NSECT 1C3E CHK-PRES 1813 CHK-REST 0F0E
  7212. CHK-SCT 1C1B CHK-TEMPM 17D2 CHK-TEMPN 17DE CHK-W-MAP 1E2F
  7213. CHKEND 015D CHKEND-L 0169 CHKEVEN 0165 CHKLOOP 18B3
  7214. CHKNAM-END 133E CHKS-ALL 1349 CHKS-BUFF 1346 CHKS-HD-R 1341
  7215. CHKS1 0DC5 CHKS2 0DD4 CHKS3 0E27 CHKS4 0E87
  7216. CHKSYNTAX 0018 CL-CHAN 14A4 CL-CHK-N 14B8 CL-M-CN 176D
  7217. CL-N-CH 175E CL-RS-CH 1751 CL-WORK 01AA CLAIMED 0F21
  7218. CLOSE 1718 CLOSE-CH 1708 CLOSE-M 12A6 CLOSE-M2 12A9
  7219. CLOSE-NET 1A24 CLR#-SYN 057F CLR-BUFF 1AE0 CLR-ERR 1987
  7220. CLS#-SYN 0559 CODE 0789 CONS-IN 19D9 CONS-OUT 19EC
  7221. CONV-1 1E98 COPYCHADD 00FB CP-NAME 121F CRT-NEW 09F3
  7222. CRT-VARS 01F7 DATA 07D2 DEC-SECT 1312 DEFAULT 0224
  7223. DEFLT-0 079A DEL-B-CT 1A81 DEL-D-1 0FCA DEL-M-BUF 10C4
  7224. DEL-S-1 1867 DELAY-BC 1BFA DELAY-BC1 18FB DELAY-SC 0F5D
  7225. DISP-CH 1EA9 DISP-HEX 1E87 DISP-HEX2 1E9E DISP-NIB 1E90
  7226. DL-LOOP 0E12 DR-READY 18D2 E-READ-N 0F4D EACH-ST 0152
  7227. EACH-VAR 0252 END-CODE 07B8 END-DATA 081C END-EXPT 0750
  7228. END-INPUT 0CF7 END-LD-PR 0A0F END-PR-MS 02AC END-RS-IN 0C36
  7229. END-S-DEL 0F8F END-SA-DR 1579 END-SET 0AE4 END1 05C1
  7230. ENDC 1E84 ENDHERE 06CC ENTRY 12E2 ENTRY-2 12E8
  7231. ERASE 1D6E ERASE-1 1D7F ERASE-2 1DB8 ERASE-LP 1D9C
  7232. ERASE-MK 1DF8 ERASE-MK2 1DFB ERASE-RUN 1E66 ERASE-SYN 0531
  7233. ERR-6 01F0 ERR-RS 12BE ERR-V 01EC EX-CHANS 17C2
  7234. EX-D-STR 059F EX-DSTR2 14C7 EXISTING 07F2 EXP-SPEC2 05F5
  7235. EXPT-EXP1 06B9 EXPT-EXPR 06A3 EXPT-NAME 062F EXPT-NUM 061E
  7236. EXPT-PRMS 0701 EXPT-SPEC 05F2 EXPT-STR 05E7 EXPT-STRM 064E
  7237. F-ERROR 168A F-HD-2 1591 F-HD-3 1599 F-M-HEAD 1580
  7238. F-N-SCT 1CEE F-REC1 1666 F-REC2 166C FAILED 127D
  7239. FETCH-ERR 026E FILL-B-F 1BBD FILL-B-F2 1BC1 FILL-MAP 1094
  7240. FOR-B-T 04CD FOR-M 04E7 FOR-RUN 1E75 FORMAT 1B6E
  7241. FORMAT-1 1B86 FR-S-LPB 1D46 FR-S-RES 1D4A FR-SC-LP 1D42
  7242. FREESECT 1D38 FRTM-SYN 04B4 G-HD-RC 11A5 G-RDES 1E53
  7243. G-REC-ERR 11D6 G-TYPE 07F6 GET-M-BLK 18AD GET-M-BUF 18A9
  7244. GET-M-HD 18A3 GET-M-HD2 12C4 GET-N-BUF 0D3F GET-NBLK 0E18
  7245. GET-NBUFF 0E65 GET-PACK 1A31 GET-R-2 117D GET-R-LP 1184
  7246. GET-RECD 1177 GETNB-END 0E62 GETNBF-END 0EA1 GP-ERROR 1A46
  7247. HD-LOOP 0854 HEX-LINE 1ECE HEX-LINE2 1ED3 HOOK-31 19A8
  7248. HOOK-32 19A4 HOOK-CODE 1981 I-AGAIN 141A IN-AGAIN 0CDB
  7249. IN-CHK 1E3E IN-M-BLK 18DE IN-NAME 1C85 INC-BLKN 0DFD
  7250. INCREC 1A14 INK$-END 0D01 INKEY$ 0CFB INPAK 0F92
  7251. INPAK-2 0F9D INPAK-L 0F9E INPUT-END 0CE1 INS-NAME 1CD4
  7252. INT-SERV 0038 KBD-TEST 1A01 LCHAN 139D LD-BLK-2 0932
  7253. LD-BLK-3 0941 LD-BLK-4 0952 LD-BLK-5 0959 LD-BLOCK 0919
  7254. LD-DATA 080E LD-HD-NET 08E0 LD-HD-RS 08E7 LD-HDR-2 08EC
  7255. LD-HEADER 08D8 LD-NO-PGM 0962 LD-PR-AR 09A3 LD-PROG 09B5
  7256. LD-VE-M 1648 LD-VF-MR 08AF LINE 073E LINE-LEN 0144
  7257. LOAD-RUN 0A95 LOAD-SYN 0894 LOOK-MAP 15F9 LP-B-MAP 1DE9
  7258. LP-P-MAP 1DE5 LP-SCOUT 0F58 LPEND 13C1 LV-ANY 0A5C
  7259. LV-B 0A79 LV-BN 0A6A LV-BN-E 0A7E LV-MCH 15A9
  7260. LV-N 0A72 LVBN-END 0A8F M-AGAIN 1414 M-INPUT 1122
  7261. MAIN-ROM 0000 MAKE-PERM 1B0D MAKESURE 0F15 MARK-FREE 1C46
  7262. MCHAN-IN 112C MCHAN-OUT 11D8 MERGE-BLK 0967 MERGE-END 09A0
  7263. MISSING-D 0494 MK-BLK 1C53 MOVE 13F1 MOVE-EOF 142E
  7264. MOVE-NA 1CD8 MOVE-OUT 1423 MOVE-RUN 1E6B MOVE-SYN 053D
  7265. MRG-SYN 08A8 N-ACTIVE 0F94 N-INPUT 0D0C NCHAN-IN 0D12
  7266. NCHAN-OUT 0D6C NET-STATE 0F03 NEW-BUFF 1162 NEW-NAME 14FC
  7267. NEWVARS 0030 NEXT-CHAN 102A NEXTNUM 01A5 NMINT-SRV 0066
  7268. NO-AUTO 0A4E NO-AUTOST 0973 NO-FOR-M 04BF NO-GOOD 1A51
  7269. NO-M-ARR 07DA NO-NAME 0716 NO-PRT 128F NO-READ 0CEA
  7270. NOEMP 12B6 NOFULL 121B NOINC-C 1DED NONAMES 1D1C
  7271. NONS-BSC 07F4 NONSENSE 0584 NOPRES 1820 NOREAD 11E6
  7272. NOT-CR 0C57 NOT-FOR-B 04D3 NOT-GRAPH 0C4C NOT-NET 0722
  7273. NOT-OP-B 051F NOT-OP-M 0500 NOT-PROT 1884 NOT-TOKEN 0C46
  7274. NOTRIGHT 1377 NREPORT-0 00E7 NREPORT-1 0139 NREPORT-2 0663
  7275. NREPORT-3 062D NREPORT-4 064C NREPORT-5 0681 NREPORT-8 06A1
  7276. NREPORT-9 0683 NREPORT-C 052F NREPORT-H 0902 NREPORT-L 0930
  7277. NUM-ARR 0819 NXT-1 01A3 NXT-B-MAP 126C NXT-BYTE 134C
  7278. NXT-ENTRY 0AD0 NXT-MOTOR 185C NXT-SCT 119E NXT-STRM 1365
  7279. NXTCHAN 110A OFF-MOTOR 184B OP-CHAM 1466 OP-F-1 1B3A
  7280. OP-F-2 1B57 OP-F-3 1B5C OP-F-4 1B5F OP-F-5 1B6C
  7281. OP-M-C 0529 OP-M-STRM 1AF0 OP-PERN-N 0EB5 OP-RS-CH 0813
  7282. OP-RSCHAN 0B47 OP-RUN 1E7A OP-STREAM 0B4A OP-STRM 1455
  7283. OP-TEMP-M 1B29 OP-TEMP-N 0EA9 OPEN-N-ST 0EA3 OPEN-RS 051C
  7284. OPEN-SYN 04ED ORD-NAM 1CBB OREP-1-2 073C OREPORT-1 04B2
  7285. OREPORT-8 0CE5 OT-NAMS 1D17 OUT-BLK-N 0D93 OUT-CODE 19EF
  7286. OUT-M-BLK 187C OUT-M-BUF 1878 OUT-M-BYT 1895 OUT-M-HD 1872
  7287. OUTPAK 0FC5 OUTPAK-L 0FCC PAR-1 079F PAR-2 07B2
  7288. PR-REP-LP 029F PRCHAR 1D66 PRNAME 1D50 PRNM-LP 1D53
  7289. PROC 0753 PROG-LINE 0130 PRT-OUT 19FC PT-N-CHAN 17ED
  7290. RCL-T-CH 17B9 RCLM-CH 177F RCLM-MAP 1114 RCLM-NUM 0182
  7291. RCLM-OLD 09E8 RD-NEXT 1A86 RD-RANDOM 1A17 RD-SECTOR 1A4B
  7292. RE-MAP 162D RE-MAP-LP 163D READ-RS 0BB1 READ-SEQ 1A09
  7293. REC-BYTE 0B8E REC-PROC 0B9A REP-MSG 0258 REPTEST 1811
  7294. RES-B-MAP 12FE RES-VARS 024D REST-MAP 1391 REST-N-AD 1691
  7295. REST-STRM 135F RETAD-RUN 05DD RETAD-SYN 05E0 RMERR-2 0040
  7296. ROMERR 0028 ROTATE 12F8 RS-SH 1AC5 RS-SH2 11A3
  7297. RUNTIME 011B RWF-ERR 1132 S-BLK-END 087D S-PACK-1 0DAB
  7298. S-SC-DEL 0F7D S-STAT 016F SA-B-END 0891 SA-BLK-LP 0872
  7299. SA-BLOCK 086E SA-BYTE 0880 SA-DRI-2 1530 SA-DRI-3 1538
  7300. SA-DRI-4 155E SA-DRI-WR 1552 SA-DRIVE 14DA SA-HEADER 084F
  7301. SA-MAP 1613 SA-MAP-LP 1620 SA-NET 088E SAVE-M 0849
  7302. SAVE-RUN 1E7F SAVE-SYN 082F SC-L-LOOP 0133 SCOUT-END 0F56
  7303. SCREEN$ 0771 SE-NAME 1C9A SEL-DRIVE 17F7 SEND-BLK 1275
  7304. SEND-NEOF 0EF5 SEND-PACK 0DB2 SEND-RESP 0FBE SEND-SC 0F61
  7305. SENDSCOUT 0DDA SEPARATOR 05B1 SER-IN-2 0C1D SER-OUT-L 0C88
  7306. SERIAL-IN 0BD8 SET-BAUD 0AC9 SET-PROG 0A15 SET-T-MCH 0FE8
  7307. SH-ERR 0020 SKIP-NUN 014E SP-DL-1 0DF6 SP-N-END 0E05
  7308. ST-BF-LEN 0D88 ST-END 05B7 ST-ERROR 0068 ST-MAP-AD 108A
  7309. ST-SHADOW 0008 START-2 009A START-3 00A5 START-4 00BC
  7310. START-BIT 0BD1 START-SA 14E8 STCHK 1354 STO-DISP 137E
  7311. STORE-DSP 1B23 STORE-LEN 0E93 SW-MOTOR 182A T-CH-NAME 1061
  7312. T-FURTHER 0BF9 T-INPUT 0B6F T-LD-NET 09DE T-M-CODE 0911
  7313. T-NA-1 1CA4 T-NA-2 1CAF T-OTHER 1E26 TCHAN-IN 0B7B
  7314. TCHAN-OUT 0C3C TEST-BAUD 06B0 TEST-BLKN 0E45 TEST-BUFF 0D1E
  7315. TEST-CODE 00E9 TEST-DTR 0C74 TEST-ERR 18E9 TEST-LOW 013B
  7316. TEST-M-BF 1134 TEST-MAP 106F TEST-MCHL 10F5 TEST-MNAM 0685
  7317. TEST-NEXT 060C TEST-OUT 0D7A TEST-PMAP 1306 TEST-RET 05BF
  7318. TEST-SAVE 07A7 TEST-SCT 1C0A TEST-SP 003A TEST-STAT 068F
  7319. TEST-TYPE 08F2 TIME-OUT 0D5F TON-DELAY 1809 TRY-AGAIN 0D45
  7320. TS-L-NET 08CD TS-L-RS 08D3 TST-AGAIN 0BC5 TST-MERGE 0904
  7321. TST-MR-M 0988 TST-MR-N 0994 TST-N-EOF 0D38 TST-NUM 1DDA
  7322. TST-PLACE 16AC TST-SPACE 09BE TST-TYPE 09C7 TURN-ON 1802
  7323. UNKN-1 1902 UNKN-2 191C UNKN-3 1929 UNKN-4 1952
  7324. UNKN-5 1959 UNKN-6 1961 UNKN-7 1968 UNKN-8 196C
  7325. UNKN-9 1976 UNPAGE 0700 UNT-MARK 0FD2 UNTIL-MK 0FAE
  7326. UNTILFIVE 1673 UPD-NXT-S 17A4 UPD-POINT 1384 UPD-STRM 1789
  7327. USE-C-RC 1A63 USE-R 1495 USE-REC 15DF VAR-EXIST 0235
  7328. VE-FAIL 1664 VE-M-E 1658 VERIF-SYN 089E VR-BN 0A8A
  7329. VR-DATA 0803 WAIT-1 0BF0 WAIT-2 0BF1 WR-F-TEST 1BD6
  7330. WR-RECD 11FF WR-S-1 1AAD WR-S-2 1ABF WR-S-3 1AC7
  7331. WR-SECTOR 1A91 WRITE-PRC 120D WT-SCOUT 0F1E WT-SYNC 0F35
  7332. WTKEY 19DE
  7333. APPENDIX 3
  7334.  
  7335. 'Shadow' system variables
  7336.  
  7337. Notes Address Name Contents
  7338. X1 23734 5CB6 FLAGS3 Various flags:
  7339. bit 0 - set during execution of 'new' commands.
  7340. bit 1 - set during execution of CLEAR# command.
  7341. On entry to the shadow ROM, it is set
  7342. at the first 'paging' operation.
  7343. bit 2 - set if the main ROM error handler is to
  7344. be used. (Normally it is always reset).
  7345. bit 3 - set if using the network.
  7346. bit 4 - set during execution of LOAD and MOVE.
  7347. bit 5 - set during execution of SAVE conwsand.
  7348. bit 6 - set during execution of MERGE conmiand.
  7349. bit 7 - set during execution of VERIFY cormnand.
  7350. FLAGS3 may be addressed with (IY+124).
  7351.  
  7352. X2 23735 5CB7 VECTOR Normally points to +01F0 (ERR-6). You may modify this
  7353. address to point to a RAM routine.
  7354.  
  7355. X10 23737 5CB9 SBRT ROM paging subroutine as follows:
  7356.  
  7357. 5CB9 LD HL,nnnnn
  7358. 5CBC CALL nnnnn
  7359. 5CBF LD (H-L),HL
  7360. 5CC2 RET
  7361.  
  7362. H-L EQU +5CBA
  7363.  
  7364. Used to save the value of HL while calling 'main'
  7365. ROM routines.
  7366.  
  7367. 2 23747 5CC3 BAUD Timing constant used during RS232 i/o.
  7368. May be obtained with:
  7369. (3500000/(26*baud rate))-2
  7370.  
  7371. 1 23749 5CC5 NTSTAT Network own station number 1..64.
  7372.  
  7373. 1 23759 5CC6 IOBORD Border colour used during I/O; normally 0 (black)
  7374.  
  7375. N2 23751 5CC7 SER-FL Low byte may be 00 or 01; high byte holds a received
  7376. byte if low byte is 01.
  7377.  
  7378. N2 23753 5CC9 SECTOR Counter of sectors examined during Microdrive
  7379. operations.
  7380.  
  7381. N2 23755 5CCB CHADD- Temporary store for CH-ADD.
  7382.  
  7383. 1 23757 5CCD NTRESP Store for network response code +01.
  7384.  
  7385. 1 23758 5CCE NTDEST Start of network buffer; destination station number
  7386. for the current packet (0..64).
  7387.  
  7388. 1 23759 5CCF NTSRCE Station number of 'sending' Spectrum for the current
  7389. packet.
  7390.  
  7391. X2 23768 5CD0 NTNUMB Current packet block number (0..65535).
  7392.  
  7393. N1 23762 5CD2 NTTYPE Packet type (00 for normal packets, 01 for EOF).
  7394.  
  7395. X1 23763 5CD3 NTLEN Length of the data block being received, 1..255.
  7396.  
  7397. N1 23764 5CD4 NTDCS Current data block checksum.
  7398.  
  7399. N1 23765 5CD5 NTCHS Current header block checksum.
  7400.  
  7401. N2 23766 5CD6 D-STR1 Start of first 8-byte file specifier; drive number
  7402. 1..8, destination station number 0..64
  7403. or baud rate 75..19200.
  7404.  
  7405. N1 23768 5CD8 S-STR1 Stream number 0..15.
  7406.  
  7407. N1 23769 5CD9 L-STR1 Device specifier "m", "n", "t" or "b".
  7408.  
  7409. N2 23770 5CDA N-STR1 Filename length
  7410. N2 23772 5CDC Filename start address.
  7411.  
  7412. N2 23774 5CDE D-STR2 Start of 2nd 8-byte file specifier, used by MOVE
  7413. and LOAD commands.
  7414.  
  7415. N1 23776 5CE0 S-STR2 See S-STR1.
  7416.  
  7417. N1 23777 5CE1 L-STR2 See L-STR1.
  7418.  
  7419. N2 23778 5CE2 N-STR2 See N-STR1.
  7420. N2 23788 5CE4
  7421.  
  7422. N1 23782 5CE6 HD-00 Start of workspace used by LOAD, SAVE, VERIFY and
  7423. MERGE commands. File type, may be:
  7424. 00 - program 01 - numeric array
  7425. 02 - string array 03 - bytes
  7426.  
  7427. N2 23783 5CE7 HD-0B Data blocklength.
  7428.  
  7429. N2 23785 5CE9 HD-0D Data block start address.
  7430.  
  7431. N2 23787 5CEB HD-0F Program length (without variables), or array name.
  7432.  
  7433. N2 23789 5CED HD-11 Autostart line number (+FFFF if no autostart), or
  7434. address of the routine called by using 'hook code'
  7435. +32.
  7436. 1 23791 5CEF COPIES Number of copies made by SAVE. Reset to +01 after
  7437. the SAVE.
  7438. APPENDIX 4
  7439.  
  7440. Channels
  7441.  
  7442. 1. MICRODRIVE CHANNEL
  7443.  
  7444. This area is used to communicate with the Microdrive device; it is created in the CHANS area. The start address is \
  7445. pointed by the IX index register in the shadow ROM program.
  7446.  
  7447. 0 +0008 Main ROM 'output' routine.
  7448. 2 +0008 Main ROM 'input' routine.
  7449. 4 'M' Channel specifier ('M'+80H denotes a 'temporary' channel,
  7450. used by SAVE, MOVE, etc.).
  7451. 5 +11D8 Shadow ROM 'output' routine.
  7452. 7 +1122 Shadow ROM 'input' routine.
  7453. 9 +0253 Channel length.
  7454. 11 CHBYTE Position of the next byte to be received or stored in the
  7455. buffer (0..512).
  7456. 13 CHREC Record number 0..255. Also used as temporary store of sector
  7457. number.
  7458. 14 CHNAME 10-byte filename with trailing spaces.
  7459. 24 CHFLAG Bit 0 set indicates a 'write' channel.
  7460. Bit 0 reset indicates a 'read' channel.
  7461. 25 CHDRIV Drive number 1..8.
  7462. 26 CHMAP Address of microdrive map.
  7463. 28 - 12 bytes of header preamble (ten zeros and two +FF). Used to
  7464. mark the start of the header block.
  7465. 40 HDFLAG Bit 0 set indicates that the received block is a header.
  7466. 41 HDNUMB Sector number from which the header comes.
  7467. 42 - Unused
  7468. 44 HDNAME 10-byte cartridge name with trailing spaces.
  7469. 54 HDCHK Checksum from HDFLAG to HDCHK-1.
  7470. 55 - 12 bytes of data preamble, as for the header; used to mark the
  7471. start of the record descriptor.
  7472. 67 RECFLG Bit 0 reset indicates that the received block is a record
  7473. descriptor.
  7474. Bit 1 is set if the record is the EOF one.
  7475. Bit 2 is reset if the record is part of a PRINT-type file.
  7476. 68 RECNUM Record number 0..255.
  7477. 69 RECLEN Number of bytes in the record (0..512).
  7478. 71 RECNAM 10-byte record name with trailing spaces.
  7479. 81 DESCHK Checksum from RECFLG to DESCHK-l.
  7480. 82 CHDATA Start of 512-byte buffer.
  7481. 594 DCHK Buffer checksum.
  7482.  
  7483. Bytes 0..27 are used as 'channel descriptor' and are never transmitted; bytes 28..54 are the 'header block'; bytes \
  7484. 55..594 are the 'data block'.
  7485. Bytes 55..91 may be collected (or written) as 'record descriptor', without affecting the data buffer starting from \
  7486. CHDATA.
  7487.  
  7488. 2. NETWORK CHANNEL
  7489.  
  7490. As with the Microdrive channel, this area is addressed by using the IX index
  7491. register it is used to communicate through the Local Area Network.
  7492.  
  7493. 0 +0008 Main ROM 'Output' routine,
  7494. 2 +0008 Main ROM 'Input' routine.
  7495. 4 'N' Channel specifier ('N'+80H denotes a 'temporary' channel).
  7496. 5 +0D6C Shadow ROM 'Output' routine.
  7497. 7 +0D9C Shadow ROM 'Input' routine.
  7498. 9 +0114 Length of the channel.
  7499. 11 NCIRIS Destination station number 0..64.
  7500. 12 NCSELF Own station number 1..64.
  7501. 13 NCNUMB Current block bumber 0..65535.
  7502. 15 NCTYPE Packet type: 00 normal packet, 01 'end of file' packet.
  7503. 16 NCOBL Number of bytes held in the buffer during 'output' (holds 0 if
  7504. the channel is used for reading).
  7505. 17 NCDCS Checksum of the 255-byte buffer.
  7506. 18 NCHCS Checksum of block NCIRIS...NCDCS.
  7507. 19 NCCUR Position of the currently received byte (in the buffer).
  7508. 20 NCIBL Number of bytes in the buffer during 'output' (holds zero if
  7509. the channel is used for writing).
  7510. 21 NCB 255-byte data buffer.
  7511.  
  7512. While 'sending', the bytes 11.18 form the 'header block' (to be stored into the system variables NTDEST...NTCHS of the \
  7513. receiving Spectrum). Bytes 21..275 form the 'data block'.
  7514.  
  7515. 3. RS232 "T" CHANNEL
  7516.  
  7517. This channel is created only when the RS232 link is to be attached to a stream. 'Temporary' RS232 channels are never \
  7518. created, because the RS232 I/O does not require a buffer to store the data to be sent or received (the only \
  7519. 'workspace' is made by the SER-FL system variable).
  7520.  
  7521. 0 +0008 Main ROM 'output' routine.
  7522. 2 +0008 Main ROM 'input' routine.
  7523. 4 'T' Channel specifier.
  7524. 5 +0C3C Shadow ROM 'output' routine.
  7525. 7 +0B6F Shadow ROM 'input' routine.
  7526. 9 +000B Channel length.
  7527.  
  7528. 4. RS232 "B" CIANNEL
  7529.  
  7530. 0 +0008 Main ROM 'output' routine.
  7531. 2 +0008 Main ROM 'input' routine.
  7532. 4 'B' Channel specifier.
  7533. 5 +0C5A Shadow ROM 'output' routine.
  7534. 7 +0B75 Shadow ROM 'input' routine.
  7535. 9 +000B Channel length.
  7536. APPENDIX 5
  7537.  
  7538. Bibliography
  7539.  
  7540. S. Vickers, ZX SPECTRUM BASIC PROGRAMMING (Sinclair Research Ltd.)
  7541.  
  7542. MICRODRIVE AND INTERFACE I MANUAL (Sinclair Research Ltd.)
  7543.  
  7544. I. Logan, F. O'Hara, THE COMPLETE SPECTRUM ROM DISASSEMBLY (Melbourne House)
  7545.  
  7546. I. Logan, SPECTRUM MICRODRIVE BOOK (Melbourne House)
  7547.  
  7548. R. Zaks, PROGRAMMING THE Z80 (Sybex)
  7549. APPENDIX 6
  7550.  
  7551. Index to routines
  7552. (For edition 1 Shadow ROM)
  7553.  
  7554. 0000 Return to main ROM
  7555. 0008 Start
  7556. 0010 Call a main ROM routine
  7557. 0018 Test if syntax is being checked
  7558. 0020 Shadow error
  7559. 0028 Main ROM error restart
  7560. 0030 Create new system variables restart
  7561. 0038 Maskable interrupt
  7562. 003A TEST-SP
  7563. 0040 Main ROM error routine
  7564. 0066 Non-maskable interrupt
  7565. 0068 ST-ERROR
  7566. 0077 CHECK-SP
  7567. 0081 CALBAS-2
  7568. 009A Control routine
  7569. 01F7 Create new system variables routine
  7570. 023A System variables default values
  7571. 024D Reset new system variables
  7572. 0258 Shadow report printing
  7573. 0287 Shadow report messages
  7574. 0486 CAT command syntax routine
  7575. 04B4 FORMAT command syntax routine
  7576. 04ED OPEN command syntax routine
  7577. 0531 ERASE command syntax routine
  7578. 053D MOVE command syntax routine
  7579. 0559 CLS# command routine
  7580. 057F CLEAR# command routine
  7581. 059F Exchange file specifiers
  7582. 05B1 SEPARATOR
  7583. 05B7 End of statement
  7584. 05Cl Return to the main interpreter
  7585. 05E7 Evaluate string expression
  7586. 05F2 Evaluate channel expression
  7587. 061E Evaluate numeric expression
  7588. 062F Evaluate filename
  7589. 064E Evaluate stream number
  7590. 0665 Check "m" parameters
  7591. 0685 Check "m" parameters and filename
  7592. 068F Check station number
  7593. 06A3 Evaluate "x";n;"name"
  7594. 06B0 Check baud rate
  7595. 06B9 Evaluate stream or expression
  7596. 0700 UNPAGE
  7597. 0701 Evaluate parameters
  7598. 082F SAVE command syntax routine
  7599. 0880 Save a byte to network or RS232 link
  7600. 0894 LOAD command syntax routine
  7601. 089E VERIFY command syntax routine
  7602. 08A8 MERGE command syntax routine
  7603. 08AF LOAD-VERIFY-MERGE commands routine
  7604. 0A5C LOAD or VERIFY
  7605. 0A95 Load "run" program
  7606. 0AC9 Set "BAUD" system variable
  7607. 0AEF RS232 timing constants
  7608. 0B13 Open RS232 channel in CHANS area
  7609. 0B47 Attach channel to a stream
  7610. 0B64 "T" channel data
  7611. 0B6F "T" channel input
  7612. 0B75 "B" channel input
  7613. 0B7B "T" channel input service routine
  7614. 0B81 "B" channel input service routine
  7615. 0C3C "T" channel output
  7616. 0C5A "B" channel output
  7617. 0CA9 Border colour restore
  7618. 0CB4 Break into I/O operation
  7619. 0CBD CALL-INP
  7620. 0D0C "N" channel input
  7621. 0D12 "N" channel input service routine
  7622. 0D6C "N" channel output
  7623. 0D93 OUT-BLK-N
  7624. 0DAB S-PACK-1
  7625. 0DB2 SEND-PACK
  7626. 0E0F BR-DELAY
  7627. 0E18 Header and data block receiving
  7628. 0EA3 OPEN "N" channel command routine
  7629. 0EA9 Open temporary "n" channel
  7630. 0EB5 Open permanent "n" channel
  7631. 0EEA "N" channel data
  7632. 0EF5 Send EOF block to network
  7633. 0F03 Network state
  7634. 0F0E Check-resting
  7635. 0F1E Wait-scout
  7636. 0F61 Send-scout
  7637. 0F92 INPAK
  7638. 0FBE Send response byte
  7639. 0FC5 OUTPAK
  7640. 0FE8 Set a temporary "m" channel
  7641. 10C4 Reclaim "m" channel
  7642. 1122 "M" channel input
  7643. 112C "M" channel input service routine
  7644. 1177 Get a record
  7645. 11A5 Get header and data block
  7646. 11D8 "M" channel output
  7647. 11FF Write record onto Microdrive
  7648. 1264 CHK-FULL
  7649. 1275 SEND-BLK
  7650. 12A6 Close file
  7651. 12BE ERR-RS
  7652. 12C4 Fetch header from Microdrive
  7653. 12DA Check map bit state
  7654. 12FF Reset bit in map area
  7655. 1306 Check 'pseudo-map' bit state
  7656. 1312 Decrease sector counter
  7657. 131E CHECK-NAME
  7658. 1341 Calculate/compare checksums
  7659. 135F Restore stream data
  7660. 1391 Restore map addresses
  7661. 13CC "M" channel data
  7662. 13E5 Preamble data
  7663. 13F1 MOVE command
  7664. 1455 Use stream or temporary channel
  7665. 14A4 Close 'MOVE' channel
  7666. 14C7 Exchange DSTR1 and STR2 contents
  7667. 14DA Save data block into Mlcrodrive
  7668. 1580 Get header information from Microdrive
  7669. 15A9 Load or verify block from Microdrive
  7670. 1613 Save Microdrive Map contents
  7671. 162D Restore Microdrive Map contents
  7672. 1648 LD-VE-M
  7673. 1666 Fetch record from Microdrive.
  7674. 1691 Restore address of filename
  7675. 1708 CLOSE STREAM
  7676. 1718 CLOSE command
  7677. 17B9 Reclaim temporary channels
  7678. 17F7 Select drive motor
  7679. 1867 1 millisecond delay
  7680. 1872 Send data block to Microdrive Head
  7681. 18A3 Receive block from Microdrive Head
  7682. 18E9 TEST-BRK
  7683. 18FA DELAY-BC
  7684. 1902 UNKN-1
  7685. 196C UNKN-8
  7686. 1981 HOOK-CODE
  7687. 19A4 Hook code +32
  7688. 19A8 Hook code +31
  7689. 19A9 Hook code addresses
  7690. 19D9 Console input
  7691. 19EC Console output
  7692. 19FC Printer output
  7693. 1A01 Keyboard test
  7694. 1A09 Read sequential
  7695. 1A17 Read random
  7696. 1A24 Close network channel
  7697. 1A31 Get packet from network
  7698. 1A4B Read sector
  7699. 1A86 Read next sector
  7700. 1A91 Write sector
  7701. 1AE0 Clear buffer contents
  7702. 1AF0 Open a permanent "m" channel
  7703. 1B29 Open a temporary "m" channel
  7704. 1B6E FORMAT "m" command
  7705. 1C58 CAT command
  7706. 1D38 FREESECT
  7707. 1D59 PRNAME
  7708. 1D66 PRCHAR
  7709. 1D6E ERASE command
  7710. 1E3E Signal 'free sector'
  7711. 1E53 Obtain record descriptor
  7712. 1E66 Calls to the command routines
  7713. 1E87 DISP-HEX
  7714. 1E9E DISP-HEX2
  7715. 1EA9 DISP-CH
  7716. 1ECE HEX-LINE
  7717. APPENDIX 7
  7718.  
  7719. Shadow ROM issue 2
  7720.  
  7721. The new ZX Interface 1's with serial number greater than 87315 have been provided with a new shadow ROM, with some \
  7722. general improvements.
  7723.  
  7724. The Spectrums fitted with the 'new' interface will print '80' in response to the command 'PRINT PEEK 23729'.
  7725.  
  7726. The main changes may be summed up as follows:
  7727.  
  7728. The TCHAN-OUT subroutine ("t" channel output routine) has been remarkably improved; the TAB function now is supported, \
  7729. as well as the 'comma' control code, and the 'leading space' bug has been corrected. The whole subroutine is listed \
  7730. below.
  7731.  
  7732. 0C3A TCHAN-OUT CP +A5 Jump if the code is not a token
  7733. 0C3C JR C,0C44,NOT-TOKEN code.
  7734. 0C3E SUB +A5 Reduce range of token.
  7735. 0C40 RST 10,CALBAS And detokenise it by calling
  7736. 0C41 DEFW +0C18 recursively this routine via main
  7737. 0C43 RET ROM 'PO-TOKENS' routine.
  7738.  
  7739. 0C44 NOT-TOKEN LD HL,+5C3B This is FLAGS.
  7740. 0C47 RES 0,(HL) Reset 'leading space' flag.
  7741. 0C49 CP +20 Is the character a space?
  7742. 0C4B JR NZ,0C4F,NOT-LEAD Jump if it is not.
  7743. 0C4D SET 0,(HL) Otherwise set 'leading space' flag.
  7744. 0C4F NOT-LEAD CP +7F Jump if the character is not
  7745. 0C51 JR C,0C55,NOT-GRAPH a 'graphic' character.
  7746. 0C53 LD A,+3F Otherwise print a '?'
  7747. 0C55 NOT-GRAPH CP +20 Jump with codes lower than +20.
  7748. 0C57 JR C,0C78,CTRL-CD
  7749. 0C59 PUSH AF Save the character code.
  7750. 0C5A INC (IY+118) Increment current print position.
  7751. 0C5D LD A,(5CB1) Fetch line width.
  7752. 0C60 CP (IY+118) Jump if the position is lower than
  7753. 0C63 JR NC,0C6C,EMIT-CH or equal to the value of WIDTH.
  7754. 0C65 CALL 0C74,NEWLINE Send CR and LF codes when pos>width.
  7755. 0C68 LD (IY+118),+01 Reset 'print position' to +01.
  7756. 0C6C ENIT-CH POP AF Restore character to be printed.
  7757. 0C6D JP 0D07,BCHAN-OUT Print it.
  7758. 0C70 CTRL-CD CP +0D Jump if the character is not 'CR'.
  7759. 0C72 JR NZ,0C82,NOT-CR
  7760. 0C74 LD (IY+118),+00 Clear print position.
  7761. 0C78 LD A,+0D Print a CR code.
  7762. 0C7A CALL 0D07,BCHAN-OUT
  7763. 0C7D LD A,+0A Print a LF code.
  7764. 0C7F JP 0D07,BCHAN-OUT
  7765. 0C82 NOT-CR CP +06 Jump if the character is not the
  7766. 0C84 JR NZ,0CA5,NOT-CMM 'comma' control code.
  7767. 0C86 LD BC,(5CB0) Fetch width into B, and print
  7768. position into C.
  7769. 0C8A LD E,+00
  7770. 0C8C SPC-COUNT INC E Increment space counter.
  7771. 0C8D INC C Increment print position.
  7772. 0C8E LD A,C Jump if 'position' reaches the
  7773. 0C8F CP B right margin.
  7774. 0C90 JR Z,0C9A,PRINT-SPC
  7775. 0C92 CMM-LOOP SUB +08 Tabulate every 8 columns.
  7776. 0C94 JR Z,0C9A,PRINT-SPC Jump when reached the right column.
  7777. 0C96 JR NC,0C92,CMMLOOP Subtract again...
  7778. 0C98 JR 0C8C,SPC-COUNT Column not reached, jump back.
  7779. 0C9A PRINT-SPC PUSH DE Save space counter.
  7780. 0C9B LD A,+20 Print the required number of spaces
  7781. 0C9D CALL 0C3A,TCHAN-OUT by calling TCHAN-OUT recursively.
  7782. 0CA0 POP DE Restore space counter.
  7783. 0CA1 DEC E
  7784. 0CA2 RET Z
  7785. 0CA3 JR 0C9A,PRINT-SPC
  7786. 0CA5 NOT-CNN CP +16 Jump with AT control code.
  7787. 0CA7 JR Z,0CB5,TAB-PROC
  7788. 0CA9 CP +17 Jump with TAB control code.
  7789. 0CAB JR Z,0C5B,TAB-PROC
  7790. 0CAD CP +19 Return with codes lower than 16d
  7791. 0CAF RET C
  7792. 0CB0 LD DE,+0CD0 Service routine for INK, PAPER
  7793. 0CB3 JR 0CB8,STORE-COD ...control codes.
  7794. 0CB5 TAB-PROC LD DE,+0CC8 Service routine for AT and TAB
  7795. 0CB8 STORE-COD LD (TVDATA-lo),A Store first operand.
  7796. 0CBB ALTER-OUT LD HL,(CURCHL) Fetch current channel address.
  7797. 0CBE PUSH DE
  7798. 0CBF LD DE,+0005 Point to 'output address' pointer.
  7799. 0CC2 ADD HL,DE
  7800. 0CC3 POP DE
  7801. 0CC4 LD (HL),E Store new 'output' address.
  7802. 0CC5 INC HL
  7803. 0CC6 LD (HL),D
  7804. 0CC? RET
  7805. 0CC8 TAB-SERV LD DE,+0CD0 The new 'output' address.
  7806. 0CCB LD (TVDATA-hi),A Store second operand.
  7807. 0CCE JR 0CBB,ALTER-OUT Jump to change the 'output' address.
  7808. 0CD0 LD DE,+0C3A Restore the normal 'output' address.
  7809. 0CD3 CALL 0CBB,ALTER-OUT
  7810. 0CD6 LD D,A Pass 'second operand' to D.
  7811. 0CD7 LD A,(TVDATA-lo) Fetch first operand (code type).
  7812. 0CDA CP +16 Jump with AT.
  7813. 0CDC JR Z,0CE6,TST-WIDTH
  7814. 0CDE CP +17 Return unless the code is TAB.
  7815. 0CE0 CCF
  7816. 0CE1 RET NZ
  7817. 0CE2 LD A,(TVDATA-hi) Fetch TAB column.
  7818. 0CE5 LD D,A Move it into D.
  7819. 0CE6 TST-WIDTH LD A,(5CB1) Fetch line width.
  7820. 0CE9 CP D
  7821. 0CEA JR Z,0CEE,TAB-MOD Jump if TAB is at last column.
  7822. 0CFC JR NC,0CF4,TABZERO Jump if TAB is within range.
  7823. 0CEE TAB-MOD LD B,A Fetch column width.
  7824. 0CEF LD A,D Fetch TAB column.
  7825. 0CF0 SUB B A=TAB-WIDTH
  7826. 0CF1 LD D,A The new position.
  7827. 0CF2 JR 0CE6,TST-WIDTH Take (TAB pos.) MOD (width).
  7828. 0CF4 TABZERO LD A,D Fetch TAB column.
  7829. 0CF5 OR A New line with TAB 0.
  7830. 0CF6 JP Z,0C74,NEWLINE
  7831.  
  7832.  
  7833. 0CF9 TABLOOP LD A,(5CB0) Fetch current print position.
  7834. 0CFC CP D Return if already at the..
  7835. 0CFD RET Z ..TAB position.
  7836. 0CFE PUSH DE
  7837. 0CFF LD A,+20 Print the TAB spaces.
  7838. 0D01 CALL 0C3A,TCHAN-OUT
  7839. 0D04 POP DE
  7840. 0D05 JR 0CF9,TABLOOP
  7841.  
  7842. You should note that variable line width is allowed by POKEing the required value into the location 23729; the default \
  7843. value is 80.
  7844.  
  7845. Other important alterations concern with Microdrive reading operations (i.e. channel opening, CAT command); the number \
  7846. of sectors examined is not fixed to 255, but is given by 'maximum sector number + 3'; this prevents the routine from \
  7847. reading 'nonexistent' sectors, and reduces the time required in the command execution.
  7848.  
  7849. The checking operation done by the FORMAT command routine is now made directly with OUT instructions, without using \
  7850. the Microdrive channel to send/receive the blocks containing 'test data'.
  7851.  
  7852. Other minor changes are:
  7853.  
  7854. - The OP-RS-CH routine stores the "B" specifier into (IX+4) when opening a RS232 "b" channel.
  7855.  
  7856. - Most of the tests done to the BREAK key have been replaced by calls to the TEST-BRK subroutine at +163E.
  7857.  
  7858. - The carry flag is preserved when calling the BORD-REST subroutine at +0D4D; thus, the 'hook code' +2F works correctly.
  7859.  
  7860. - 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 \
  7861. sufficient memory to insert the new space.
  7862.  
  7863. - The GET-M-HD subroutine, returns (with bit 0 of HDFLAG or RECFLG inverted) when 'time-out' occurs during the reading \
  7864. operation.
  7865.  
  7866. - An instruction 'SET 7,(HL)' has been inserted at location +1741 (i.e. the middle of the CLOSE routine), to correct \
  7867. the bug present in the 'old' shadow ROM (see comment to the CLOSE routine).
  7868.  
  7869. - No CR code is sent when a RS232 'b" channel is closed.
  7870.  
  7871. - The 'hook code' +2B calls the SET-T-MCH subroutine.
  7872.  
  7873. - Two new 'hook codes', +33 and +34, are now available. Hook code +33 may be used to fetch a 'record descriptor' from \
  7874. the next sector; the microdrive motor must be turned on before calling the routine. The record descriptor is stored \
  7875. into the current microdrive channel (whose start address must be held into the IX index register), and the carry flag \
  7876. is returned set if any error occurs, or if the 'record descriptor' holds a filename starting wIth CHR$ 0. Hook code \
  7877. +34 opens a RS232 "b" channel by calling the OP-RS-CH subroutine. The channel base address is returned into the DE \
  7878. register pair.
  7879. APPENDIX 8
  7880.  
  7881. How to tell which edition Interface 1 you have
  7882.  
  7883. There are two different versions of the ZX Interface, each having a slightly different program in its ROM. It is \
  7884. important that you know which version of the ROM you have, and you can find this out in the fo5lowing manner:
  7885.  
  7886. Run the following line of BASIC:
  7887.  
  7888. CLOSE # 0: PRINT PEEK 23729
  7889.  
  7890. If this prints out a '0', then you have an edition 1 Interface 1. if it prints out '80', you have an edition 2 \
  7891. Interface 1.
  7892.  
  7893. There is the possibility that Sinclair Research may release a third edition of the Shadow ROM, with a few more \
  7894. changes. If you should get one of these, the extended BASIC commands may not work properly with it. The 'PRINT PEEK \
  7895. 23729'
  7896. test probably wont distinguish between the edition 2 and edition 3 Shadow ROMs, You can, however, upload the Shadow \
  7897. ROM into a higher area of RAM, disassemble it there, and compare the code to the listings given in this book. The \
  7898. following
  7899. program will load the Shadow ROM into RAM from 32768 to 48968:
  7900.  
  7901. ORG 34000
  7902. LD HL,LABEL
  7903. LD (23789),HL
  7904. RST 08
  7905. DEFB 32H
  7906. LABEL POP HL
  7907. POP HL
  7908. LD HL,0
  7909. LD DE,32768
  7910. LD BC,8192
  7911. LDIR
  7912. RST 0
  7913. RET
  7914.  
  7915. To do the same thing from BASIC, use the following program:
  7916.  
  7917. 10 CLEAR 26000
  7918. 20 FOR X=54000 TO 54022
  7919. 30 READ Y
  7920. 40 POKE X,Y
  7921. 50 NEXT X
  7922. 60 RAND USR 54000
  7923. 70 DATA 33,248,210,34,237,92,207,50,225,225
  7924. 80 DATA 33,0,0,17,0,128,1,0,32,237,176,199,201
  7925.  
  7926. For information on how to make the extended BASIC commands work with edition 3 or later Shadow ROMs, refer to Appendix \
  7927. 11, page 165.
  7928. APPENDIX 9
  7929.  
  7930. Basic loader program
  7931. for edition 2 Shadow ROM
  7932. (For owners of Interface 1s equipped with the edition 2 Shadow ROM.)
  7933.  
  7934. Here is the new BASIC loader program, changed to run with the new shadow ROM. To enter the new BASIC commands into \
  7935. your Spectrum without using an assembler, enter the following BASIC loader program.
  7936.  
  7937.  
  7938. 1 CLEAR 63743
  7939. 10 FOR A=63744 TO 65951 STEP 12
  7940. 20 PRINT "ADDRESS:";A'
  7941. 30 LET C=0
  7942. 40 FOR B=1 TO 12
  7943. 50 LET Z=A+B-1: IF Z<=65051 THEN INPUT X: PRINT X: POKE Z,X: LET C=C+X
  7944. 60 NEXT B
  7945. 70 PRINT '"CHECKSUM=";C
  7946. 80 INPUT "THIS IS WRONG ? (Y/N) "; LINE Y$: IF CODE Y$=80 OR CODE Y$=121 THEN PRINT "Retype from address ";A: PAUSE \
  7947. 100: CLS : GO TO 20
  7948. 90 IF CODE Y$<>78 AND CODE Y$<>110 THEN GO TO 80
  7949. 100 CLS: NEXT A
  7950. 110 PRINT "Saving the program"
  7951. 120 SAVE *"M";l;"SHADP" CODE 63744,1308
  7952.  
  7953.  
  7954. When you have finished typing this program into your Spectrum, you should 'RUN' it. You should then type from the \
  7955. listing on the next page, the 12 bytes from the address shown on the screen. When you have typed the first 12 bytes, a \
  7956. 'checksum' should be displayed on the screen; if it matches the one printed on the listing, at the right hand side of \
  7957. the line, then you have made no mistakes in typing the numbers, and you may enter 'N' or 'n' to continue with the next \
  7958. line. If the checksums do not match, you must enter 'Y' or 'y', and then retype the whole line.
  7959.  
  7960. When all numbers have been entered, the program will automatically be saved on Microdrive cartridge (there must be a \
  7961. cartridge with at least 2K free in Microdrive 1). If you wish to save the program on tape, line 120 of the listing \
  7962. should be modified appropriately. When at some 1ater time you wish to use the routines, you have simply to place the \
  7963. cartridge in Microdrive 1, and then to enter the following direct commands:
  7964.  
  7965. CLEAR 63743: LOAD *"M";1;"SHADP" CODE: RANDOMIZE USR 63744
  7966.  
  7967. and the new comnands should be available. Note that if you use the NEW command, you should then give the direct \
  7968. command 'RANDOMISE USR 63744' to reinitialise the VECTOR system variable.
  7969. Here is the data for the new Shadow ROM:
  7970.  
  7971. 63744: 207 49 33 9 249 34 183 92 201 215 24 0 1296
  7972. 63756: 254 244 202 45 249 254 42 202 114 249 254 215 2384
  7973. 63768: 202 11 250 254 227 202 188 251 254 229 202 12 2282
  7974. 63780: 252 254 224 202 175 252 195 240 1 215 32 0 2042
  7975. 63792: 254 42 194 75 249 215 121 28 205 183 5 215 1786
  7976. 63804: 153 30 197 215 153 30 197 225 193 113 35 112 1653
  7977. 63816: 195 193 5 215 130 28 254 44 194 240 1 215 1714
  7978. 63828: 32 0 215 140 28 205 183 5 215 241 43 197 1504
  7979. 63840: 213 215 153 30 80 89 223 193 120 177 202 193 1890
  7980. 63852: 5 237 176 195 193 5 215 32 0 254 207 202 1721
  7981. 63864: 102 250 246 32 254 108 194 197 249 215 32 0 1879
  7982. 63876: 215 130 28 205 183 5 215 153 30 96 105 124 1489
  7983. 63888: 205 214 20 125 205 214 20 62 32 205 248 20 1570
  7984. 63900: 229 6 6 197 126 205 237 20 35 16 249 193 1519
  7985. 63912: 225 126 230 127 254 32 56 6 254 128 48 2 1488
  7986. 63924: 24 2 62 32 205 248 20 35 16 235 62 13 954
  7987. 63936: 205 248 20 24 202 254 101 194 240 1 215 32 1736
  7988. 63948: 0 215 130 28 205 183 5 215 153 30 253 203 1620
  7989. 63960: 12 126 202 240 1 120 230 192 194 240 1 237 1795
  7990. 63972: 67 73 92 237 123 61 92 33 7 250 229 42 1306
  7991. 63984: 61 92 229 33 127 16 229 237 115 61 92 253 1545
  7992. 63996: 54 0 255 215 169 15 33 56 15 229 199 225 1465
  7993. 64008: 195 180 18 215 32 0 254 42 194 240 1 215 1586
  7994. 64020: 121 28 254 44 194 240 1 215 121 28 205 183 1634
  7995. 64032: 5 215 148 30 245 215 148 30 167 40 54 79 1376
  7996. 64044: 6 0 197 215 148 30 167 40 44 79 6 0 932
  7997. 64056: 197 215 153 30 197 205 0 7 225 209 193 241 1872
  7998. 64068: 229 245 197 229 213 205 181 3 209 225 193 241 2370
  7999. 64080: 167 237 66 48 240 61 225 32 235 33 193 5 1542
  8000. 64092: 34 237 92 207 50 253 54 0 0 239 215 32 1413
  8001. 64104: 0 205 30 6 205 183 5 205 109 6 62 2 1018
  8002. 64116: 215 1 22 205 165 16 221 126 25 205 50 21 1272
  8003. 64128: 205 169 19 33 9 251 17 24 0 205 5 251 1188
  8004. 64140: 205 38 20 32 239 33 9 251 203 70 32 232 1364
  8005. 64152: 58 9 251 33 12 251 182 230 2 194 169 250 1641
  8006. 64164: 205 227 19 24 215 58 13 251 183 40 209 58 1502
  8007. 64176: 10 251 183 32 203 221 126 41 221 190 13 40 1531
  8008. 64188: 22 205 33 251 205 0 251 221 126 13 183 194 1704
  8009. 64200: 128 250 221 126 41 221 119 13 195 128 250 221 1913
  8010. 64212: 229 175 205 50 21 205 0 251 221 229 225 17 1828
  8011. 64224: 44 0 25 205 178 251 205 0 251 205 67 29 1460
  8012. 64236: 123 203 63 215 40 45 215 227 45 205 0 251 1632
  8013. 64248: 221 225 205 159 17 195 193 5 62 13 195 113 1603
  8014. 64260: 29 229 195 242 21 0 0 0 0 0 0 0 716
  8015. 64272: 0 0 0 0 0 0 0 0 0 0 0 0 0
  8016. 64284: 0 0 0 0 0 33 140 92 54 255 33 13 620
  8017. 64296: 251 205 178 251 62 32 205 113 29 58 9 251 1644
  8018. 64308: 203 87 194 62 251 62 245 195 113 29 33 24 1498
  8019. 64320: 251 126 183 202 99 251 254 3 202 157 251 61 2040
  8020. 64332: 245 62 228 205 113 29 58 29 251 230 31 198 1679
  8021. 64344: 96 205 113 29 241 200 62 36 195 113 29 33 1352
  8022. 64356: 32 251 126 230 192 192 43 62 202 205 113 29 1677
  8023. 64368: 94 35 86 235 17 16 39 205 143 251 17 232 1370
  8024. 64380: 3 205 143 251 17 100 0 205 143 251 17 10 1345
  8025. 64392: 0 205 143 251 17 1 0 62 255 60 183 237 1414
  8026. 64404: 82 48 250 25 246 48 195 113 29 62 175 205 1478
  8027. 64416: 113 29 35 229 35 35 205 112 251 62 44 205 1355
  8028. 64428: 113 29 225 195 112 251 6 10 126 205 113 29 1414
  8029. 64440: 35 16 249 201 215 32 8 254 35 194 240 1 1472
  8030. 64452: 215 121 28 205 183 5 215 148 30 245 215 148 1758
  8031. 64464: 30 254 16 210 99 6 215 1 22 221 42 81 1197
  8032. 64476: 92 221 126 4 254 77 194 45 6 221 203 24 1467
  8033. 64488: 70 194 13 18 241 221 119 13 221 126 25 205 1466
  8034. 64500: 50 21 33 255 0 34 201 92 205 95 18 175 1179
  8035. 64512: 221 119 11 221 119 12 205 50 21 195 193 5 1372
  8036. 64524: 215 32 0 215 130 28 205 183 5 215 148 30 1406
  8037. 64536: 254 16 210 99 6 215 1 22 221 42 81 92 1259
  8038. 64548: 221 126 4 254 77 194 45 6 221 203 24 70 1445
  8039. 64560: 194 6 9 221 126 25 205 50 21 33 255 0 1145
  8040. 64572: 34 201 92 205 128 18 56 19 40 14 221 203 1231
  8041. 64584: 67 78 40 11 221 126 41 221 119 13 24 3 964
  8042. 64596: 205 227 19 205 247 19 32 227 219 239 230 1 1870
  8043. 64608: 202 185 31 205 63 31 218 126 18 221 110 69 1479
  8044. 64620: 221 102 70 221 117 11 221 116 12 221 203 24 1539
  8045. 64632: 198 205 73 30 205 169 19 221 126 13 221 190 1670
  8046. 64644: 41 32 245 62 230 211 239 1 104 1 205 82 1453
  8047. 64656: 22 221 229 225 17 55 0 25 205 179 21 62 1261
  8048. 64668: 238 211 239 205 227 19 221 126 68 221 119 13 1907
  8049. 64680: 175 205 50 21 195 193 5 215 32 0 254 33 1378
  8050. 64692: 40 11 254 47 40 33 254 63 40 54 195 240 1271
  8051. 64704: 1 215 121 28 205 183 5 215 148 30 167 202 1520
  8052. 64716: 250 253 50 21 254 215 148 30 61 50 20 254 1606
  8053. 64728: 195 193 5 215 121 28 205 183 5 215 148 30 1543
  8054. 64740: 50 22 254 215 148 30 50 23 254 175 50 27 1298
  8055. 64752: 254 195 193 5 215 32 0 215 130 28 205 183 1655
  8056. 64764: 5 215 148 30 254 1 40 12 62 3 253 203 1226
  8057. 64776: 124 142 205 24 23 195 193 5 62 3 215 39 1230
  8058. 64788: 23 33 17 0 167 237 66 218 47 5 205 23 1041
  8059. 64800: 11 213 33 5 0 25 17 53 253 115 35 114 874
  8060. 64812: 62 3 50 216 92 209 195 81 11 254 165 211 1548
  8061. 64824: 62 12 253 203 1 134 254 32 56 91 32 4 1134
  8062. 64836: 253 203 1 198 245 62 1 50 24 254 241 254 1786
  8063. 64848: 127 56 2 62 63 205 7 13 58 20 254 71 938
  8064. 64860: 58 19 254 184 48 5 60 50 19 254 201 205 1357
  8065. 64872: 111 253 175 50 24 254 201 62 1 50 24 254 1459
  8066. 64884: 61 50 19 254 58 25 254 167 196 7 13 58 1162
  8067. 64896: 26 254 167 196 7 13 58 23 254 71 58 27 1154
  8068. 64908: 254 60 184 32 0 58 22 254 167 196 7 13 1255
  8069. 64920: 175 50 27 254 201 254 13 32 12 58 24 254 1354
  8070. 64932: 167 62 1 50 24 254 200 24 194 254 6 32 1268
  8071. 64944: 33 42 19 254 58 21 254 71 14 0 12 44 822
  8072. 64956: 125 188 48 167 144 40 4 48 251 24 243 197 1479
  8073. 64968: 62 32 205 53 253 193 13 32 246 201 254 23 1567
  8074. 64980: 192 17 226 253 42 81 92 6 5 9 115 35 1073
  8075. 64992: 114 201 50 15 92 17 234 253 24 238 17 53 1308
  8076. 65004: 253 205 216 253 58 15 92 71 58 20 254 184 1679
  8077. 65016: 48 5 253 54 0 10 239 58 19 254 144 200 1284
  8078. 65028: 48 5 237 68 79 24 188 197 205 111 253 193 1608
  8079. 65040: 72 24 180 0 80 20 12 60 1 13 10 0 472
  8080. APPENDIX 10
  8081.  
  8082. Extended BASIC commands from assembler for edition 2 Shadow ROM
  8083. (For owners of Interface 1s equipped with the edition 2 Shadow ROM.)
  8084.  
  8085. To add the extended BASIC commands to your Spectrum, if you own an edition 2 Shadow ROM and an assembler, first enter \
  8086. the assembly program on pages 12 to 32 into your Spectrum. Do not enter the table of EQU statements that follows on \
  8087. page 33. These labels all refer to the edition 1 Shadow ROM, and are not relevant to edition 2. Instead, for each \
  8088. label given on page 33, enter the value given in the alphabetical list of Shadow ROM 2 labels which follow. When you \
  8089. have entered this program and assembled it, save it onto Microdrive or tape. To use the new BASIC commands, load the \
  8090. machine code file you have made into your Spectrum at 63744 (F900 Hex), and give the direct command 'RANDOMISE USR \
  8091. 63744'. The new commands should then be available.
  8092. Below is an alphabetical list of the labels related to the edition 2 shadow ROM.
  8093.  
  8094. ACC-CODE 0D8A ALL-BITS 102F ALL-BYTES 05A7 ALL-CHARS 1407
  8095. ALL-MOTRS 1570 ALL-STRMS 058E ALLCHR-2 1418 ALTER-OUT 0CBB
  8096. B-INPUT 0B7C BCHAN-IN 0B88 BCHAN-OUT 0D07 BD-DEL-1 0D1C
  8097. BD-DEL-2 0D32 BD-DEL-3 0D48 BD-DELAY 0BD8 BD-DELAY2 0C1D
  8098. BF-FILLED 1CFF BORD-REST 0D4D BR-DELAY 0EAC BRCAST 0EDD
  8099. BREAK-PGM 05E2 CALBAS 0010 CALBAS-2 0081 CALL-INP 0D5A
  8100. CAT 1C52 CAT-LP 1C68 CAT-LP-E 1C77 CAT-RUN 1AB5
  8101. CAT-SCRN 04A6 CAT-SYN 0486 CHAN-SPC 10F1 CHECK-M 0665
  8102. CHECK-M-2 066D CHECK-MAP 13C4 CHECK-N 1883 CHECK-R 188F
  8103. CHECK-SP 0077 CHK-AG-2 1608 CHK-AGAIN 15F6 CHK-FULL 1349
  8104. CHK-LOOP 10B3 CHK-LP-2 160F CHK-M-EOF 1233 CHK-MAP-2 13BF
  8105. CHK-NAME 1403 CHK-NSECT 1C1E CHK-PRES 154E CHK-REST 0FC7
  8106. CHK-SCT 1BF6 CHK-SCT2 1C05 CHK-TEMPM 17D0 CHK-TEMPN 17DC
  8107. CHK-W-MAP 1E3A CHKEND 015D CHKEND-L 0169 CHKEVEN 0165
  8108. CHKLOOP 15FD CHKS-ALL 142E CHKS-BUFF 142B CHKS-HD-R 1426
  8109. CHKS1 0E62 CHKS2 0E71 CHKS3 0EC4 CHKS4 0F24
  8110. CHKSYNTAX 0018 CKNAM-END 1423 CL-CHAN 18A8 CL-CHK-N 18BC
  8111. CL-M-CH 176B CL-N-CH 175C CL-WORK 01AA CLAIMED 0FD9
  8112. CLOSE 1718 CLOSE-CH 1708 CLOSE-M 138B CLOSE-M2 138E
  8113. CLOSE-NET 1F18 CLR#-SYN 057F CLR-BUFF 1FD4 CLR-ERR 1E77
  8114. CLS#-SYN 0559 CMM-LOOP 0C92 CODE 0789 CONS-IN 1ECD
  8115. CONS-OUT 1EE0 CONV-1 14E7 COPYCHADD 00FB CP-NAME 1300
  8116. CRT-NEW 09F7 CRT-VARS 01F7 CTRL-CD 0C70 DATA 07D2
  8117. DEC-SECT 13F7 DEFAULT 0224 DEFLT-0 079A DEL-B-CT 1F75
  8118. DEL-M-BUF 119F DEL-O-1 1087 DEL-S-1 15A2 DELAY-BC 1652
  8119. DELAY-BC1 1653 DELAY-SC 101A DISP-CH 14F8 DISP-HEX 14D6
  8120. DISP-HEX2 14ED DISP-NIB 14DF DL-LOOP 0EAF DR-READY 1620
  8121. E-READ-N 100A EACH-ST 0152 EACH-VAR 025A EMIT-CH 0C6C
  8122. END-CODE 07B8 END-DATA 081C END-EXPT 0750 END-INPUT 0D94
  8123. END-LD-PR 0A13 END-PR-MS 02B4 END-RS-IN 0C34 END-S-DEL 104C
  8124. END-SA-DR 196A END-SET 0AE8 END1 05C1 ENDC 1AC9
  8125. ENDHERE 06CC ENDRD 16AD ENTRY 13C7 ENTRY-2 17C0
  8126. ERASE 1D79 ERASE-1 1D8A ERASE-2 1DC3 ERASE-LP 1DA7
  8127. ERASE-MK 1E03 ERASE-MK2 1E06 ERASE-RUN 1AAB ERASE-SYN 0531
  8128. ERR-6 01F0 ERR-RS 13A3 ERR-V 01EC EX-CHANS 17C0
  8129. EX-D-STR 059F EXISTING 07F2 EXPT-EXP1 06B9 EXPT-EXPR 06A3
  8130. EXPT-NAME 062F EXPT-NUM 061E EXPT-PRMS 0701 EXPT-SPEC 05F2
  8131. EXPT-STR 05E7 EXPT-STRM 064E F-ERROR 1A7B F-HD-2 1982
  8132. F-HD-3 198A F-M-HEAD 1971 F-N-SCT 1CF4 F-REC1 1A57
  8133. F-REC2 1A5D FAILED 1362 FETCH-ERR 0276 FILL-MAP 1163
  8134. FOR-B-T 04CD FOR-M 04E7 FOR-RUN 1ABA FORMAT 185D
  8135. FORMAT-1 1B75 FR-S-LPB 1D51 FR-S-RES 1D55 FR-SC-LP 1D4D
  8136. FREESECT 1D43 FRMT-SYN 04B4 G-HD-RC 1280 G-RDES 1E5E
  8137. G-REC-ERR 12B1 G-TYPE 07F6 GET-DESC 1FE4 GET-M-BLK 15F2
  8138. GET-M-BUF 15EB GET-M-HD 15E2 GET-M-HD2 13A9 GET-N-BUF 0DDC
  8139. GET-NBLK 0EB5 GET-NBUFF 0F02 GET-PACK 1F25 GET-R-2 1258
  8140. GET-R-LP 125F GET-RECD 1252 GETBF-END 0F3E GETNB-END 0EFF
  8141. GP-ERROR 1F3A HD-LOOP 0854 HEX-LINE 151D HEX-LINE2 1522
  8142. HOOK-31 1E98 HOOK-32 1E94 HOOK-CODE 1E71 I-AGAIN 181E
  8143. IN-AGAIN 0D78 IN-CHK 1E49 IN-M-BLK 1633 IN-NAME 1C8B
  8144. INC-BLKN 0E9A INCREC 1F08 INKEY$ 0D98 INPAK 104F
  8145. INPAK-2 105A INPAK-L 105B INS-NAME 1CDA INT-SERV 0038
  8146. KBD-TEST 1EF5 LCHAN 1482 LD-BLK-2 0936 LD-BLK-3 0945
  8147. LD-BLK-4 0956 LD-BLK-5 095D LD-BLOCK 091D LD-DATA 080E
  8148. LD-HD-NET 08E4 LD-HD-RS 08EB LD-HDR-2 08F0 LD-HEADER 08DC
  8149. LD-NO-PGM 0966 LD-PR-AR 09A7 LD-PROG 09B9 LD-VE-M 1A39
  8150. LD-VF-MR 08B3 LINE 073E LINE-LEN 0144 LOAD-RUN 0A99
  8151. LOAD-SYN 0898 LOOK-MAP 19EA LP-B-MAP 1DF4 LP-P-MAP 1DF0
  8152. LP-SCOUT 1015 LPEND 14A6 LV-ANY 0A60 LV-B 0A7D
  8153. LV-BN 0A6E LV-BN-E 0A82 LV-MCH 199A LV-N 0A76
  8154. LVBN-END 0A93 M-AGAIN 1818 M-INPUT 11FD MAIN-ROM 0000
  8155. MAKE-PERM 1AE9 MAKESURE 0FCA MARK-FREE 1C40 MCHAN-IN 1207
  8156. MCHAN-OUT 12B3 MERGE-BLK 096B MERGE-END 09A4 MISSING-D 0494
  8157. MK-BLK 1C4D MOVE 17F5 MOVE-EOF 1832 MOVE-NA 1CDE
  8158. MOVE-OUT 1827 MOVE-RUN 1AB0 MOVE-SYN 053D MRG-SYN 08AC
  8159. N-ACTIVE 1051 N-INPUT 0DA9 NCHAN-IN 0DAF NCHAN-OUT 0E09
  8160. NET-STATE 0FBC NEW-BUFF 123D NEW-NAME 18ED NEWVARS 0030
  8161. NEXT-CHAN 10E7 NEXTNUM 01A5 NMINT-SRV 0660 NO-AUTO 0A52
  8162. NO-AUTOST 0977 NO-FOR-M 04BF NO-GOOD 1F45 NO-M-ARR 07DA
  8163. NO-NAME 0716 NO-PRT 1374 NO-READ 0D87 NOEMP 139B
  8164. NOFULL 12FC NOINC-C 1DF8 NONAMES 1D27 NONS-BSC 07F4
  8165. NONSENSE 0584 NOPRES 155B NOREAD 12C1 NOT-CMM 0CA5
  8166. NOT-CR 0C82 NOT-FOR-B 04D3 NOT-GRAPH 0C55 NOT-LEAD 0C4F
  8167. NOT-NET 0722 NOT-OP-B 051F NOT-OP-M 0500 NOT-PROT 15BF
  8168. NOT-RECV 1FF1 NOT-TOKEN 0C44 NOTRIGHT 145C NREPORT-1 0139
  8169. NREPORT-2 0663 NREPORT-3 062D NREPORT-4 064C NREPORT-5 0681
  8170. NREPORT-8 06A1 NREPORT-9 0683 NREPORT-L 0934 NREPORT-N 0906
  8171. NUM-ARR 0819 NXT-1 01A3 NXT-B-MAP 1351 NXT-BYTE 1431
  8172. NXT-ENTRY 0AD4 NXT-MOTOR 1597 NXT-SCT 1279 NXT-STRM 144A
  8173. NXTCHAN 11E5 OFF-MOTOR 1586 OP-B-CHAN 1FF6 OP-CHAN 186A
  8174. OP-F-1 1B16 OP-F-2 1B41 OP-F-3 1B46 OP-F-4 1B49
  8175. OP-F-5 1B5B OP-F-X 1B26 OP-M-C 0529 OP-M-STRM 1ACC
  8176. OP-PERM-N 0F52 OP-RS-CH 0B17 OP-RSCHAN 0B4E OP-RUN 1ABF
  8177. OP-STREAM 0B51 OP-STRM 1859 OP-TEMP-M 1B05 OP-TEMP-N 0F46
  8178. OPEN-N-ST 0F40 OPEN-RS 051C OPEN-SYN 04ED ORD-NAM 1CC1
  8179. OREP-1-2 073C OREPORT-1 04B2 OREPORT-8 0D82 OT-NAMS 1D22
  8180. OUT-BLK-N 0E30 OUT-CODE 1EE3 OUT-M-BLK 15B7 OUT-M-BUF 15B3
  8181. OUT-M-BYT 15D0 OUT-M-HD 15AD OUTMEM 0F9E OUTMEM2 119A
  8182. OUTPAK 1082 OUTPAK-L 1089 PAR-1 079F PAR-2 07B2
  8183. PR-REP-LP 02A7 PRCHAR 1D71 PREP-MARK 1C35 PRINT-SPC 0C9A
  8184. PRNAME 1D5B PRNM-LP 1D5E PROG 0753 PROG-LINE 0130
  8185. PRT-OUT 1EF0 PT-N-CHAN 17EB RCL-T-CH 17B7 RCLM-CH 177D
  8186. RCLM-MAP 11EF RCLM-NUM 0182 RCLM-OLD 09EC RD-BYT-1 1696
  8187. RD-BYT-2 169D RD-BYT-3 16A5 RD-NEXT 1F7A RD-RANDOM 1F0B
  8188. RD-SECTOR 1F3F RDLOOP1 165C RDLOOP2 165E RDLOOP3 1669
  8189. RDLOOP4 166B RE-MAP 1A1E RE-MAP-LP 1A2E READ-BLK 165A
  8190. READ-RS 0BAF READ-SEQ 1EFD READY-R2 1686 READY-RE 162A
  8191. REC-BYTE 0B95 REC-PROC 0B98 REP-MSG 0260 REPTEST 154C
  8192. RES-B-MAP 13E3 RES-VARS 0255 REST-MAP 1476 REST-N-AD 1A82
  8193. REST-STRM 1444 RETAD-RUN 05DD RETAD-SYN 05E0 RMERR-2 0040
  8194. ROMERR 0028 ROTATE 13DD RS-SH 1AC5 RS-SH2 11A3
  8195. RUNTIME 011B RWF-ERR 1132 S-BLK-END 0881 S-PACK-1 0E48
  8196. S-SC-DEL 103A S-STAT 016F SA-B-END 0895 SA-BLK-LP 0872
  8197. SA-BLOCK 086E SA-BYTE 0884 SA-DRI-2 1921 SA-DRI-3 1929
  8198. SA-DRI-4 194F SA-DRI-WR 1943 SA-DRIVE 18CB SA-HEADER 084F
  8199. SA-MAP 1A04 SA-MAP-LP 1A11 SA-NET 0892 SAVE-M 0849
  8200. SAVE-RUN 1AC4 SAVE-SYN 082F SC-L-LOOP 0133 SCOUT-END 1013
  8201. SCREEN$ 0771 SE-NAME 1CA0 SEL-DRIVE 1532 SEND-BLK 135A
  8202. SEND-NEOF 0FAE SEND-PACK 0E4F SEND-RESP 107B SEND-SC 101E
  8203. SENDSCOUT 0E77 SEPARATOR 05B1 SER-IN2 0C1B SER-OUT-L 0D2C
  8204. SERIAL-IN 0BD6 SET-BAUD 0ACD SET-PROG 0A19 SET-T-MCH 10A5
  8205. SH-ERR 0020 SIGN-ERR 15DE SKIP-NUM 014E SP-DL-1 0E93
  8206. SP-N-END 0EA2 SPC-COUNT 0C8C ST-BF-LEN 0E25 ST-END 05B7
  8207. ST-ERROR 0068 ST-MAP-AD 1168 ST-SHADOW 0008 START-2 009A
  8208. START-3 00A5 START-4 00BC START-BIT 0BCF STAR-SA 18D9
  8209. STCHK 1439 STO-DISP 1463 STORE-COD 0CB8 STORE-DSP 1AFF
  8210. STORE-LEN 0F30 SW-MOTOR 1565 SYNC-RD 167C T-CH-NAME 1135
  8211. T-FURTHER 0BF7 T-INPUT 0B76 T-LD-NET 09E2 T-M-COOE 0915
  8212. T-NA-1 1CAA T-NA-2 1CB5 T-OTHER 1E31 TAB-MOD 0CEE
  8213. TAB-PROC 0CB5 TAB-SERV 0CC8 TABLOOP 0CF9 TABZERO 0CF4
  8214. TCHAN-IN 0B82 TCHAN-OUT 0C3A TEST-BAUD 06B0 TEST-BLKN 0EE2
  8215. TEST-BRK 163E TEST-BUFF 0DBB TEST-CODE 00E9 TEST-DTR 0D21
  8216. TEST-LOW 013B TEST-N-BF 120F TEST-MAP 1143 TEST-MCHL 11D0
  8217. TEST-MNAM 0685 TEST-NEXT 060C TEST-OUT 0E17 TEST-PMAP 13E8
  8218. TEST-RET 05BF TEST-SAVE 07A7 TEST-SCT 1BDF TEST-SP 003A
  8219. TEST-STAT 068F TEST-TYPE 08F6 TIME-OUT 0DFC TON-DELAY 1344
  8220. TRY-AGAIN 0DE2 TS-L-NET 08D1 TS-L-RS 08D7 TST-AGAIN 0BC3
  8221. TST-MERGE 0908 TST-MR-M 098C TST-MR-N 0998 TST-N-EOF 0DD5
  8222. TST-NUM 1DE5 TST-PLACE 1A9D TST-SPACE 09C2 TST-TYPE 09CB
  8223. TST-WIDTH 0CE6 TURN-ON 153D UNPAGE 0700 UNT-MARK 108F
  8224. UNTIL-MK 106B UNTILFIVE 1A64 UPD-NXT-S 17A2 UPD-POINT 1469
  8225. UPD-STRM 1787 USE-C-RC 1F57 USE-R 1899 USE-REC 19D0
  8226. VAR~EXIST 023D VE-FAIL 1A55 VE-M-E 1A49 VERIFSYN 08A2
  8227. VR-BN 0A8E VR-DATA 0803 WAIT-1 0BEE WAIT-2 0BEF
  8228. WR-BLK 16AF WR-BYT-1 16C4 WR-BYT-2 16C8 WR-BYT-3 16CD
  8229. WR-F-TEST 1BAB WR-RECD 12DA WR-S-1 1FA1 WR-S-2 1FB3
  8230. WR-S-3 1FBB WR-SECTOR 1F85 WRITE-PRC 12EE WT-SC-E 0FD3
  8231. WT-SCOUT 0FD6 WT-SYNC 0FED WTKEY 1ED2
  8232. APPENDIX 11
  8233.  
  8234. What to do if you have an unknown ROM
  8235.  
  8236. If you should find that your Interface 1 contains a ROM which differs from both the edition 1 and the edition 2 Shadow \
  8237. ROM, then the code to implement the extended BASIC commands that is given in this book will not work. This is because \
  8238. the code that we have given contains a number of calls to routines in the Shadow ROM, which perform a number of useful \
  8239. tasks, such as selecting Microdrives, reading a sector of tape, displaying hexadecimal numbers on the screen, etc. \
  8240. Many of these routines are at different locations in the first two editions of the ROM, and presumably they would be \
  8241. different again in any future ROMs.
  8242. This does not, however mean that it is not possible for you to add the expanded BASIC commands to your machine. The \
  8243. code that we have given is still quite correct, but the calls it makes to the ROM are no longer accurate. The \
  8244. solution, then is to add to the extended BASIC commands routines of your own which have the same names as the ROM \
  8245. routines, and will perform the same functions. This doesn't mean that you'll have to write all these routines - all \
  8246. the code you need is contained in the Shadow ROM disassembly given earlier in this book. Simply find the routine you \
  8247. need in the Shadow ROM disassembly, and copy it into your program. Consider the following example:
  8248.  
  8249. The extended BASIC command '*L n' includes the following code:
  8250.  
  8251. LD H,B ;move it into HL
  8252. LD L,C
  8253. AGAIN LD A,H ;display high byte of address in hex
  8254. CALL DISP-HEX
  8255. LD A,L ;display low byte
  8256.  
  8257. This wont work as it stands, as it includes a call to the Shadow ROM routine DISP-HEX, and the address given for \
  8258. DISP-HEX in the table of EQU statements will not be correct. What you should do to make this work is to remove the \
  8259. entry for DISP-HEX from the EQU table, and then look up the entry for DISP-HEX in the alphabetical list of labels \
  8260. (Appendix 2.). According to this, the DISP-HEX routine is at 1E87H. Look this up in the disassembly, and add the \
  8261. routine you find (shown below) to the end of your program.
  8262.  
  8263. DISP-HEX PUSH AF
  8264. RRA
  8265. RRA
  8266. RRA
  8267. RRA
  8268. CALL DISP-NIB
  8269. POP AF
  8270. DISP-NIB AND 0FH
  8271. CP 0AH
  8272. JR C,CONV-1
  8273. ADD A,7
  8274. CONV-1 ADD A,30H
  8275. CALL DISP-CH
  8276. RET
  8277.  
  8278. Note, however, that this routine makes its own call to another Shadow ROM routine, DISP-CH, which you will also have \
  8279. to add to your code. DISP-CH is located at 1EA9 in the disassembly, and is as follows:
  8280.  
  8281. DISP-CH PUSH HL
  8282. PUSH DE
  8283. PUSH BC
  8284. PUSH AF
  8285. EXX
  8286. PUSH HL
  8287. PUSH DE
  8288. PUSH BC
  8289. PUSH AF
  8290. LD HL,(CURCHL)
  8291. PUSH HL
  8292. PUSH AF
  8293. LD A,2
  8294. RST CALBAS
  8295. DEFW 1601H
  8296. POP AF
  8297. RST CALBAS
  8298. DEFW 10H
  8299. POP HL
  8300. LD (CURCHL),A
  8301. POP AF
  8302. POP BC
  8303. POP DE
  8304. POP HL
  8305. EXX
  8306. POP AF
  8307. POP BC
  8308. POP DE
  8309. POP HL
  8310. RET
  8311.  
  8312. Doing the same thing with all the other Shadow ROM calls should make it possible for you to run all the extended BASIC \
  8313. commands. Note that the program, as it stands, fits into the very highest part of memory, with no room above it to \
  8314. spare. The code you will be adding will make the extended commands somewhat longer. Because of this, you will have to \
  8315. ORG your program to an earlier location, in order for it to fit into memory. Remember that when you initialise the new \
  8316. commands from BASIC, you should no longer use
  8317. RANDOMISE USR 63744
  8318. but instead use
  8319. RANDOMISE USR x
  8320. where x is the location at which your assembler program is ORGed.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement