Home | Contents | KwikPik |
PATCHING UP THE 'DRIVES Faulty files are now a thing of the past! Using this second instalment of code, Andrew Pennell shows you how to recover unloadable files from that Microdrive cartridge that's giving you hassle. Take it away, Andrew ... | code, you'll need to use the listing given
to slightly alter the data you've already
got in order to accommodate that given
here. The relocator program achieves its
object and corrects the problems
described above; it then goes on to save
the new code under the name "SLC.2".
Once you've entered this little goodie,
move RAMtop up to, say, 32768 to
allow room for the new bytes shown in
the second listing. (A word of warning -
there's insufficient memory to allow both
of these programs to be present simultaneously!) The second program given here reads in "SLC.2", adds the extra code to it and then saves it out as "SLC.3". In fact, it was while entering this listing myself that I discovered the low memory bug that still remains in the third version of the Interface 1 ROM. I tried a CAT command as soon as I realised that memory was running out and the system crashed in the most spectacular of fashions. But, as long as you don't get RAMtop below the value in line 100, you shouldn't have any problem on any of the Interface ROMs. When you've sorted the machine code to rights, do a RANDOMIZE USR 32816 to allow the extra commands to be accepted by the syntax checker. Now enter the third listing given, saving it so that it starts at line 9000. It's an extended version of the first part's Basic. | |
---|---|---|
In issue 8 of our most illustrious magazine, I got about half-way through devising a Microdrive repair kit that could smell out faulty files in an article called Running Repairs. Now, to finish it off, I have evolved a way of allowing the recovery of unloadable files from cartridge. SORRY!But first, an apology. Part one of this article, Running Repairs, was not quite the pristine job it might have been, and those with sharp eyes will have spotted the odd buglet or two; the pity is, I can't even lay the blame on our poor ol' Ed (Poor yes, but less of the 'old'. Ed.). The problem is that we get a sector list that's minus some of the necessary data ... indeed, there are quite a few sectors missing. As it stands, this produces incorrect results in the 'check file' section. | Anyway, I've modified the code to improve the performance and, although it's still not perfect - some sectors that do exist may not be found on very full cartridges, and some will be marked as 'bad' when they're not - this is not so much of a problem now because one of the functions of the extra code given in this issue, is for it to act as an individual sector read, and this achieves perfect results. Another problem in Running Repairs was the code's position in memory - RAMtop at 30000 proved too low for the extra Basic. Thus, I've provided a relocator program that'll shift the code for you - that'll teach me to hand in part one of an article before working out part two! GETTING UNDER WAY!So, before you enter this issue's section of |
THE COMMAND TABLE | |
---|---|
COMMAND | ACTION |
*L <drive> | Gets the sector list into z$. |
*D <drive> | Sets the drive number for all the other commands. |
*F <sector> CODE <location> | Loads the given sector into a given location. IX corresponds to the first location, so it requires 595 bytes. |
*S CODE <location> | Saves the sector read into the location on the next free sector on the cartridge. |
*E <sector> | 'Removes' the numbered sector from the cartridge. |
INTO ACTIONThe menu has been extended to cover the extra operations; probably the most useful of these is 'Examine sector', which searches a cartridge for a given sector, and loads it (corrupted or not) into RAM for inspection. Lines 6000 onwards load the sector into locations 60000 on, revealing various details about it. Most important here are the checksums; if either of these are incorrect it means that the file of which it is a part will probably not load, and the sector should be repaired - which is exactly what option 6 does. You can usually tell if tape is physically damaged, because the checksum result will give a different value every time you read it.A sector is repaired by it being read to address 60000 onwards; this is then written out on to the next available sector, with the checksums re-calculated. It's not, of course, written back on to the same sector as there's every chance that the actual tape is damaged at this point. Once a sector has been fixed in this way, the 'bad' version should be 'removed' from the cartridge; there's not much point in freeing the faulty sector for further use. Option 7 achieves this by marking it with a strange filename full of CHR$ 0s. That done, the next time you ask for a sector list of the cartridge you'll get a bad sector with the name "??????????"; this is normal, so don't try |
to delete it again. The strange name will
not show up in a normal CAT. As much
of the utility is in Basic, you can reconfigure it to suit, using the extra
commands provided; check out the table of
commands given with this article. CODE CONSIDERATIONSFor those blessed with an assembler, it's obviously a bit easier to enter the assembly listing, rather than the accompanying Hex. The listing, in fact, is a bit strange for two reasons. First, it's fragmented, consisting initially of the modifications made to the code in Running Repairs. As the original line numbers were chopped from my listing (ha! - at last something I can blame on someone else) the position of each modification may not be clear. To help, I've included at least one label in each block. The only one that's a bit vague is the main extra section ... it should go directly after TEMPA in the code in Running Repairs. The '*L+' commands in the listing are assembler directives, and should be ignored.The second odd thing about the listing is that it uses a 'macro'. I've used one called OLD to make it clearer when calling 16K ROM routines with the 8K ROM in place. The usual way to call a routine is with two instructions - namely a RST#10 followed by a DEFW - and this is not exactly crystal clear; with the |
macro defined, a much clearer command
(such as OLD#20) can be used. Currently, the only assembler that allows
macros is the one from Hisoft - if you
use another, simply replace it with the
more long-winded version. (I cannot
claim any originality for this idea. The
shadow ROMs were written by Sinclair
Research using a similar macro, named
OLDCAL, but the Hisoft assembler
doesn't allow long macro names.) And now for the code itself. To begin with, there's a mod allowing the additional routines to be accessed - by alteration of the JP instruction. The other mods are to do with getting around the 'missing sector' problem, and the DEFB 0s are there to pad out the code so that it ends up pretty much like the code you saw in Running Repairs. If you have a look at the code, you'll see the macro definition, and that's followed by the new syntax checker. Check out the listing itself for further documentation. Anyway, that's about it. With this little lot, you should be able to reclaim at least some of your unloadable files. The existing program does not alter corrupt data from sectors - only the checksums - and you could add a nice little editor around line 6020 to do just that. Sorry for the long wait between the two parts of this article ... let's hope I don't have to wait so long for you to come up with an editor at line 6020! |
*1 This listing is used to alter the code given in Running Repairs to accommodate the code provided in this article - it also corrects the slight problem in the previous listing! |
100 CLEAR 29999 110 LOAD *"m";1;"SL.CODE" CODE 120 FOR i=30000 TO 30463 130 LET a=PEEK i: IF a=117 OR a=118 THEN LET a=a+11 140 IF (i>=30141 AND i<=30154) OR (i>=30225 AND i<=30228) THEN LET a=0 150 POKE i+2816,a 160 NEXT i 170 DATA 2,128,25,0,26,130,133,255,140,129 180 DATA 222,201,224,53,229,32 190 RESTORE: FOR i=1 TO 8 200 READ a,b: POKE 32816+a,b 210 NEXT i 220 SAVE *"m";1;"SLC.2" CODE 32816,464 |
*2 Once you've saved the code from the first listing as "SLC.2", move RAMtop up to, say, 32768, to make room for the listing below, which reads in "SLC.2", adds the extra code to it and then saves it out as "SLC.3". | |
100 CLEAR 32815 110 LOAD *"m";1;"SLC.2" CODE 120 RESTORE 130 LET s=0 500 FOR i=33280 TO 33788 510 READ a: POKE i,a: LET s=s+a 520 NEXT i 530 IF s<>57690 THEN PRINT "Data error": STOP 540 SAVE *"m";1;"SLC.3" CODE 32816,1000 1000 DATA 245,205,144,131,241,254 1010 DATA 100,40,17,254,102,40 1020 DATA 31,254,115,202,173,130 1030 DATA 254,101,202,10,131,195 1040 DATA 240,1,215,32,0,205 1050 DATA 30,6,205,183,5,42 1060 DATA 214,92,34,251,131,195 1070 DATA 193,5,215,32,0,205 1080 DATA 30,6,254,175,194,40 1090 DATA 0,215,32,0,237,67 1100 DATA 201,92,205,30,6,205 1110 DATA 183,5,197,33,1,0 1120 DATA 34,218,92,42,251,131 1130 DATA 34,214,92,205,232,15 1140 DATA 221,126,25,205,247,23 1150 DATA 42,201,92,221,117,13 1160 DATA 33,255,0,34,201,92 1170 DATA 205,196,18,221,126,41 1180 DATA 221,190,13,40,12,33 1190 DATA 201,92,53,32,239,225 1200 DATA 54,255,195,107,131,221 1210 DATA 229,225,17,67,0,25 1220 DATA 205,169,24,1,14,0 1230 DATA 205,204,129,221,119,11 1240 DATA 17,15,0,25,1,0 1250 DATA 2,205,204,129,221,119 1260 DATA 12,221,54,0,0,221 1270 DATA 229,225,209,1,83,2 1280 DATA 237,176,195,107,131,215 1290 DATA 32,0,254,175,194,240 1300 DATA 1,215,32,0,205,30 1310 DATA 6,205,183,5,237,67 1320 DATA 253,129,33,0,131,34 1330 DATA 220,92,1,10,0,34 1340 DATA 218,92,42,251,131,34 1350 DATA 214,92,205,41,27,221 1360 DATA 110,26,221,102,27,6 1370 DATA 32,126,254,255,32,5 | 1380 DATA 35,16,248,231,15,221 1390 DATA 229,225,1,67,0,9 1400 DATA 235,42,253,129,9,1 1410 DATA 16,2,237,176,205,61 1420 DATA 18,195,107,131,0,1 1430 DATA 2,3,4,5,6,7 1440 DATA 8,9,215,32,0,205 1450 DATA 30,6,205,183,5,237 1460 DATA 67,253,129,33,0,131 1470 DATA 34,220,92,1,10,0 1480 DATA 34,218,92,42,251,131 1490 DATA 34,214,92,205,232,15 1500 DATA 221,126,25,205,247,23 1510 DATA 219,239,230,1,32,2 1520 DATA 231,14,33,255,0,34 1530 DATA 201,92,205,196,18,58 1540 DATA 253,129,221,190,41,32 1550 DATA 42,62,230,211,239,205 1560 DATA 125,131,1,104,1,245 1570 DATA 11,120,177,32,251,241 1580 DATA 0,221,229,225,17,55 1590 DATA 0,25,205,120,24,62 1600 DATA 238,211,239,221,203,24 1610 DATA 134,205,169,18,195,193 1620 DATA 5,33,201,92,53,32 1630 DATA 197,24,238,221,229,6 1640 DATA 10,221,54,71,0,221 1650 DATA 35,16,248,221,225,221 1660 DATA 203,70,206,201,33,163 1670 DATA 131,58,218,22,6,11 1680 DATA 254,255,202,108,128,33 1690 DATA 207,131,195,108,128,213 1700 DATA 130,41,27,82,130,232 1710 DATA 15,42,131,232,15,251 1720 DATA 130,61,18,101,131,120 1730 DATA 24,88,130,247,23,48 1740 DATA 131,247,23,103,130,196 1750 DATA 18,65,131,196,18,133 1760 DATA 130,169,24,112,131,169 1770 DATA 18,213,130,5,27,82 1780 DATA 130,165,16,42,131,165 1790 DATA 16,251,130,34,19,101 1800 DATA 131,179,21,88,130,50 1810 DATA 21,48,131,50,21,103 1820 DATA 130,169,19,65,131,169 1830 DATA 19,133,130,235,21,112 1840 DATA 131,142,19,1,0 |
*3 This listing should be saved at line 9000. It's an extended version of the Basic given in Running Repairs. | |
100 INPUT "Drive number ";d 110 IF d<1 OR d>8 THEN GO TO 100 120 DIM z$(250,13): DIM n$(13) 130 *D d: *L d 135 PRINT "Wait a sec ..." 139 REM find last item 140 FOR i=1 TO 250 150 IF Z$(i,12)<>CHR$ 255 THEN NEXT i 160 LET n=i-1 169 REM ove repetitions 170 FOR i=2 TO n 180 IF z$(i, TO 12)<>z$(i-1, TO 12) THEN GO TO 190 182 IF CODE z$(i,13)>127 THEN LET z$(i)=n$: GO TO 190 184 LET z$(i-1)=n$ 190 NEXT i 200 LET c=2 1000 CLS: PRINT INVERSE 1;" MICRODRIVE REPAIR KIT " 1005 PRINT ''"0. Output to ";"printer" AND c=2;"screen" AND c=3 1010 PRINT '"1. Full catalogue" 1020 PRINT '"2. Sector list" 1030 PRINT '"3. Bad sector list" 1040 PRINT '"4. Check file" 1050 PRINT '"5. Examine sector" 1060 PRINT '"6. Repair sector" 1070 PRINT '"7. Remove sector" 1080 PRINT '"8. Change drive no." 1090 PRINT 1095 INPUT ;: PRINT #0;"Choose an option"; 1100 PAUSE 0: LET a$=INKEY$: INPUT ; 1110 IF a$<"0" OR a$>"8" THEN GO TO 1095 1120 IF a$="0" THEN LET c=5-c: GO TO 1000 1125 IF a$="8" THEN INPUT "Drive no.";d:*D d: GO TO 1000 1130 GO SUB 1000+1000*VAL a$ 1140 IF c=2 THEN PRINT "Press any key for menu": PAUSE 0 1150 GO TO 1000 1999 REM Full catalogue 2000 PRINT #c;"Full catalogue" 2010 DIM f$(10): LET f$=z$(1) 2020 FOR i=1 TO n 2030 IF z$(i)=n$ OR z$(i, TO 10)=f$ THEN GO TO 2060 2040 PRINT #c;f$( TO 10) 2050 LET f$=z$(i, TO 10) 2060 NEXT i 2065 PRINT #c;z$(n, TO 10) 2070 RETURN 2999 REM Complete sector list 3000 DIM f$(10): INPUT "Filename (or ENTER for all):",f$ 3010 FOR i=1 TO n 3015 IF z$(i)=n$ THEN GO TO 3030 3020 IF f$=n$( TO 10) THEN GO SUB 9500: GO TO 3030 3025 IF z$(i, TO 10)=f$ THEN GO SUB 9500 3030 NEXT i 3040 RETURN 3999 REM Bad sector list 4000 PRINT #c;"Bad sector list" 4010 FOR i=1 TO n 4020 IF z$(i)<>n$ AND z$(i,13)>CHR$ 127 THEN GO SUB 9500 4030 NEXT i 4040 RETURN 4999 REM Check file 5000 DIM f$(10): INPUT "Filename? ";f$ 5005 DIM x$(256): LET eof=-1: LET good=1 5010 FOR i=1 TO n 5020 IF z$(i, TO 10)<>f$ THEN GO TO 5100 5030 IF z$(i,13)>CHR$ 127 THEN GO TO 5060 | 5039 REM good sector 5040 LET x$(CODE z$(i,11)+1)="y" 5050 GO TO 5080 5059 REM bad sector 5060 PRINT #c;"Record ";CODE z$(i,11);" bad on sector ";CODE z$(i,12) 5070 LET good=0 5080 LET a=CODE z$(i,13) 5090 IF a/2<>INT (a/2) THEN LET eof=CODE z$(i,11) 5100 NEXT i 5110 IF eof>=0 THEN GO TO 5120 5111 REM missing EOF 5112 FOR i=250 TO 1 STEP -1 5114 IF x$(i)=" " THEN NEXT i 5116 LET eof=i-1 5118 LET good=0: PRINT #c;"No EOF record" 5120 FOR i=0 TO eof 5130 IF x$(i+1)=" " THEN PRINT "Record ";i;" missing": LET good=0 5140 NEXT i 5150 IF good=1 THEN PRINT "File ";f$;" intact" 5160 IF good=0 THEN PRINT "File ";f$;" corrupted" 5170 RETURN 5999 REM Read a sector 6000 INPUT "Sector no.";s 6010 *F s CODE 60000 6020 IF c=2 THEN CLS 6090 PRINT #c;"Sector ";s 6100 IF PEEK 60000 THEN PRINT #c; FLASH 1;"Not found": RETURN 6110 PRINT #c;"Cart name:"; 6120 FOR i=44 TO 53 6130 PRINT #c;CHR$ PEEK (60000+i); 6140 NEXT i: PRINT #c 6150 PRINT #c;"RECFLG:";PEEK 60067 6160 PRINT #c;"RECNUM:";PEEK 60068 6170 PRINT #c;"RECLEN:";PEEK 60069+256*PEEK 60070 6180 PRINT #c;"Filename:"; 6190 FOR i=71 TO 80 6200 PRINT #c;CHR$ PEEK (60000+i); 6210 NEXT i: PRINT #c 6220 PRINT #c;"Checksum1:";PEEK 60081, 6230 IF PEEK 60011=PEEK 60081 THEN PRINT #c;"OK" 6240 IF PEEK 60011<>PEEK 60081 THEN PRINT #c;"(should be ";PEEK 60011;")" 6245 PRINT #c;"Checksum2:";PEEK 60594, 6250 IF PEEK 60012=PEEK 60594 THEN PRINT #c;"OK" 6260 IF PEEK 60012<>PEEK 60594 THEN PRINT #c;"(should be ";PEEK 60012;")" 6300 RETURN 6999 REM repair sector 7000 GO SUB 6000 7010 IF PEEK 60000 THEN RETURN 7020 PRINT '"Re-writing to spare sector" 7030 *S CODE 60000 7040 PRINT 7050 RETURN 7999 REM remove sector 8000 INPUT "Sector no.";s 8010 *E s 8020 PRINT "Sector removed" 8030 RETURN 9000 CLEAR 32815: LOAD *"m";1;"SLC.3" CODE: RANDOMIZE USR 32816: RUN 9500 PRINT #c;z$(i, TO 10);" r";CODE z$(i,11);TAB 16;"s";CODE z$(i,12);TAB 21; 9510 LET f=CODE z$(i,13) 9520 IF f/2<>INT (f/2) THEN PRINT #c;"EOF"; 9530 IF CODE z$(i,13)>127 THEN PRINT #c;TAB 25;"BAD"; 9540 PRINT #c 9550 RETURN 9999 CLEAR: ERASE "m";1;"repair 2": SAVE *"m";1;"repair 2" |
* This is the main assembler listing and should be entered using an assembler program. If you've not got an assembler to hand, you can use a Hex loader to type in the figures on the left-hand side of the listing. [It is unnecessary to do this, as the "SLC.3" program creates all the code.] |
100 ORG #8030 ;**new org** 8030 213A80 110 LD HL,NEWVEC 8033 22B75C 120 LD (VECTOR),HL ;alter vector 8036 010000 130 LD BC,0 8039 C9 140 RET 803A C6CE 200 NEWVEC ADD A,206 803C FE2A 210 CP "*" 803E C2F001 220 JP NZ,#01F0 8041 D7 230 RST #10 8042 2000 240 DEFW #20 ;next char 8044 F620 245 OR #20 ;make it l.c. 8046 FE6C 247 CP "l" 8048 C20082 248 JP NZ,NVEC2 ;**new jump** 804B D7 249 RST #10 804C 2000 250 DEFW #20 ;next char 1055 *L+ 1056 ; 1057 ; 80B1 CDF717 1060 L2 CALL MOTOR ;switch on 80B4 21FF00 1070 LD HL,255 ;**new number** 80B7 22C95C 1080 LD (SECTOR),HL 80BA CDA381 1090 FLOOP CALL NXHDBF ;next header & buffer 1100 DEFB 0,0,0,0,0,0,0 ;**blank old code** 1110 DEFB 0,0,0,0,0,0,0 80CB 2840 1200 LESS JR Z,NEXT ;if not used 80CD 3810 1201 JR C,ISBAD ;if 1st checksum fails 1375 *L+ 1376 ; 1377 ; 1378 ;(rather different) 810D 21C95C 1380 NEXT LD HL,SECTOR 8110 35 1390 DEC (HL) 8111 00000000 1400 DEFB 0,0,0,0 8115 20A3 1430 JR NZ,FLOOP 4999 *L+ 5000 ; 5010 ;REPAIR KIT PART 2 5020 ;STARTS HERE 5030 ; 5031 ;do Macro for 16K ROM calls 8200 5032 OLD MAC 8200 5033 RST #10 8200 5034 DEFW =0 8200 5035 ENDM 5036 ; 5040 ;further syntax checker 8200 F5 5042 NVEC2 PUSH AF 8201 CD9083 5045 CALL WATRM2 ;alter code 8204 F1 5047 POP AF 8205 FE64 5050 CP "d" 8207 2811 5060 JR Z,SETDRV 8209 FE66 5070 CP "f" 820B 281F 5080 JR Z,FINDSC 820D FE73 5090 CP "s" 820F CAAD82 5100 JP Z,SAVSEC 8212 FE65 5110 CP "e" 8214 CA0A83 5120 JP Z,ERASEC 8217 C3F001 5130 JP #01F0 ;if none 5140 ; 821B 5150 SETDRV OLD #20 821D CD1E06 5160 CALL EVALBC 8220 CDB705 5170 CALL CHKEND 8223 2AD65C 5180 LD HL,(D_STR1) 8226 22FB83 5190 LD (DRIVE),HL 8229 C3C105 5200 JP #05C1 ;end of *D 5210 ; |
The first extra command handler is SETDRV, which handles the *D command simply by finding the value and putting it in DRIVE. |
822C 5220 FINDSC OLD #20 822F CD1E06 5230 CALL EVALBC ;get sector no 8232 FEAF 5240 CP 175 ;"CODE" 8234 C22800 5250 JP NZ,#0028 8237 5260 OLD #20 823A ED43C95C 5270 LD (SECTOR),BC ;sector no 823E CD1E06 5280 CALL EVALBC 8241 CDB705 5290 CALL CHKEND 8244 C5 5300 PUSH BC ;save destination 8245 210100 5310 LD HL,1 8248 22DA5C 5320 LD (N_STR1),HL ;name len 824B 2AFB83 5330 LD HL,(DRIVE) 824E 22D65C 5340 LD (D_STR1),HL |
The next routine is FINDSC, which handles the *F command. After syntax checking, an 'M' channel is created, and each sector examined until the required one is found - or until the sector counter expires. If the sector is found, then its particulars are stored in the said location; if not, then 255 is placed into the location instead. An exit is made via QUITM, which closes the channel before returning to the interpreter. |
8251 CDE80F 5350 M2 CALL CREATM 8254 DD7E19 5360 LD A,(IX+25) 8257 CDF717 5370 M6 CALL MOTOR ;turn on 825A 2AC95C 5380 LD HL,(SECTOR) 825D DD750D 5390 LD (IX+13),L ;save sector no 8260 21FF00 5400 LD HL,255 8263 22C95C 5410 LD (SECTOR),HL ;count 8266 CDC412 5420 DOAGIN CALL NEXTHD 8269 DD7E29 5430 LD A,(IX+41) ;sector loaded 826C DDBE0D 5440 CP (IX+13) ;is it wanted? 826F 280C 5450 JR Z,GOTIT ;if it's the one 8271 21C95C 5460 LD HL,SECTOR 8274 35 5470 DEC (HL) 8275 20EF 5480 JR NZ,DOAGIN ;do 255 times 8277 E1 5490 POP HL ;destination 8278 36FF 5500 LD (HL),255 ;'not found' 827A C36B83 5505 JP QUITM 827D DDE5 5530 GOTIT PUSH IX 827F E1 5540 POP HL 8280 114300 5550 LD DE,#0043 8283 19 5560 ADD HL,DE ;HL=RECFLG 8284 CDA918 5570 M10 CALL RDBYTS 8287 010E00 5580 LD BC,#000E 828A CDCC81 5590 CALL CHKSUM 828D DD770B 5600 LD (IX+11),A 8290 110F00 5602 LD DE,#000F 8293 19 5603 ADD HL,DE 8294 010002 5604 LD BC,#0200 8297 CDCC81 5605 CALL CHKSUM 829A DD770C 5606 LD (IX+12),A 829D DD360000 5610 LD (IX+0),0 ;'found' 82A1 DDE5 5620 PUSH IX 82A3 E1 5630 POP HL 82A4 D1 5640 POP DE ;destination 82A5 015302 5650 LD BC,595 82A8 EDB0 5660 LDIR ;copy whole buffer 82AA C36B83 5665 JP QUITM 5700 ; 5710 ;save data on next free sector 82AD 5720 SAVESC OLD #20 82B0 FEAF 5730 CP 175 ;"CODE" 82B2 C2F001 5740 JP NZ,#01F0 82B5 5750 OLD #20 82B8 CD1E06 5760 CALL EVALBC 82BB CDB705 5770 CALL CHKEND 82BE ED43FD81 5780 LD (FMARK),BC ;store source 82C2 210083 5790 LD HL,SILLNM 82C5 22DC5C 5800 LD (T_STR1),HL 82C8 010A00 5810 LD BC,10 82CB 22DA5C 5820 LD (N_STR1),HL 82CE 2AFB83 5830 LD HL,(DRIVE) 82D1 22D65C 5840 LD (D_STR1),HL |
Routine SAVESC handles the *S command and, again, it starts by opening an 'M' channel with a silly filename that should never exist on the cartridge. A full cartridge is tested prior to the data being written onto the next free sector, with the ROM routine WRBUF handling most of the tricky stuff ... including doing the checksums. |
82D4 CD291B 5850 M1 CALL OPENM 82D7 DD6E1A 5860 LD L,(IX+26) 82DA DD661B 5870 LD H,(IX+27) 82DD 0620 5880 LD B,32 82DF 7E 5890 FULL? LD A,(HL) 82E0 FEFF 5900 CP #FF 82E2 2005 5910 JR NZ,ISSPAC ;if at least 1 free sector 82E4 23 5920 INC HL 82E5 10F8 5930 DJNZ FULL? 82E7 E7 5940 RST #20 82E8 0F 5950 DEFB #0F ;"Microdrive full" 82E9 DDE5 5960 ISSPAC PUSH IX 82EB E1 5970 POP HL 82EC 014300 5980 LD BC,67 82EF 09 5990 ADD HL,BC 82F0 EB 6000 EX DE,HL ;DE=RECFLG 82F1 2AFD81 6010 LD HL,(FMARK) 82F4 09 6020 ADD HL,BC ;source+67 82F5 011002 6030 LD BC,595-67 82F8 EDB0 6040 LDIR ;copy into buffer 82FA CD3D12 6050 M4 CALL WRBUF ;send it 82FD C36B83 6070 JP QUITM 8300 00010203 6090 SILLNM DEFB 0,1,2,3,4,5,6,7,8,9 ;silly filename 6100 ; 6110 ;remove an individual sector 830A 6120 ERASEC OLD #20 830D CD1E06 6130 CALL EVALBC 8310 CDB705 6140 CALL CHKEND 8313 ED43FD81 6150 LD (FMARK),BC 8317 210083 6160 LD HL,SILLNM 831A 22DC5C 6170 LD (T_STR1),HL 831D 010A00 6180 LD BC,10 8320 22DA5C 6190 LD (N_STR1),HL 8323 2AFB83 6200 LD HL,(DRIVE) 8326 22D65C 6210 LD (D_STR1),HL |
The code at ERASEC handles the *E command, by searching for the required sector in a similar way to FINDSC. When it's found, a null filename is written out to it, along with a bit that shows the sector is being 'used'; thus, it's removed from use. |
8329 CDE80F 6220 M3 CALL CREATM 832C DD7E19 6230 LD A,(IX+25) 832F CDF717 6240 M7 CALL MOTOR ;switch on 8332 DBEF 6250 IN A,(#EF) 8334 E601 6260 AND 1 8336 2002 6270 JR NZ,NPROT 8338 E7 6280 RST #20 8339 0E 6290 DEFB #E ;"Write protected" 833A 21FF00 6300 NPROT LD HL,255 833D 22C95C 6310 LD (SECTOR),HL 8340 CDC412 6320 ERALP CALL NEXTHD ;next sector 8343 3AFD81 6330 LD A,(FMARK) 8346 DDBE29 6340 CP (IX+41) 8349 202A 6350 JR NZ,NOTWON 6360 ;this is the sector 834B 3EE6 6370 LD A,#E6 834D D3EF 6380 OUT (#EF),A ;signal 'write' to ULA 834F CD7D83 6390 CALL CLRBUF 8352 016801 6400 LD BC,#0168 8355 F5 6410 PUSH AF 8356 0B 6420 WAITBC DEC BC 8357 78 6430 LD A,B 8358 B1 6440 OR C 8359 20FB 6450 JR NZ,WAITBC 835B F1 6460 POP AF 835C 00 6470 NOP ;after a delay 835D DDE5 6480 PUSH IX 835F E1 6490 POP HL 8360 113700 6500 LD DE,#0037 8363 19 6510 ADD HL,DE ;preamble 8364 CD7818 6520 M5 CALL WRBIT ;send it 8367 3EEE 6530 LD A,#EE 8369 D3EF 6540 OUT (#EF),A ;put 'write' off 836B DDCB1886 6550 QUITM RES 0,(IX+24) 836F CDA912 6560 M11 CALL CLOSEM 8372 C3C105 6570 JP #05C1 ;end of *E 8375 21C95C 6580 NOTWON LD HL,SECTOR 8378 35 6590 DEC (HL) 8379 20C5 6600 JR NZ,ERALP 837B 18EE 6610 JR QUITM ;if can't find it 837D DDE5 6620 CLRBUF PUSH IX 837F 060A 6630 LD B,10 8381 DD364700 6640 CLBLP LD (IX+71),0 8385 DD23 6650 INC IX 8387 10F8 6660 DJNZ CLBLP ;make null filename 8389 DDE1 6670 POP IX 838B DDCB46CE 6680 SET 1,(IX+70); mark it 'used' 838F C9 6690 RET 7000 ; 7010 ;alter part 2 for different ROMs 8390 21A383 7020 WATRM2 LD HL,OLD2 8393 3ADA16 7030 LD A,(#16DA) 8396 060B 7040 LD B,11 8398 FEFF 7050 CP #FF 839A CA6C80 7060 JP Z,REDOLP 839D 21CF83 7070 LD HL,NEW2 83A0 C36C80 7080 JP REDOLP |
The final routine is WATRM2, and this does what's necessary to ensure that the program works on all types of ROM. As far as this program is concerned, there's no difference between versions 2 and 3, so no extra steps are taken for the latter version of the Interface 1 ROM. You'll also find that the code given in Running Repairs also works fine on the third version of the ROM. |
7090 ;data for old ROM 83A3 D582291B 7100 OLD2 DEFW M1+1,OPENM 83A7 5282E80F 7110 DEFW M2+1,CREATM 83AB 2A83E80F 7120 DEFW M3+1,CREATM 83AF FB823D12 7130 DEFW M4+1,WRBUF 83B3 65837818 7140 DEFW M5+1,WRBIT 83B7 5882F717 7150 DEFW M6+1,MOTOR 83BB 3083F717 7160 DEFW M7+1,MOTOR 83BF 6782C412 7170 DEFW DOAGIN+1,NEXTHD 83C3 4183C412 7180 DEFW ERALP+1,NEXTHD 83C7 8582A918 7190 DEFW M10+1,RDBYTS 83CB 7083A912 7200 DEFW M11+1,CLOSEM 83CF D582051B 7210 NEW2 DEFW M1+1,#1B05 83D3 5282A510 7220 DEFW M2+1,#10A5 83D7 2A83A510 7230 DEFW M3+1,#10A5 83DB FB822213 7240 DEFW M4+1,#1322 83DF 6583B315 7250 DEFW M5+1,#15B3 83E3 58823215 7260 DEFW M6+1,#1532 83E7 30833215 7270 DEFW M7+1,#1532 83EB 6782A913 7280 DEFW DOAGIN+1,#13A9 83EF 4183A913 7290 DEFW ERALP+1,#13A9 83F3 8582EB15 7300 DEFW M10+1,#15EB 83F7 70838E13 7310 DEFW M11+1,#138E |
Home | Contents | KwikPik |