The Acorn DFS Osword commands - by - Gordon Horsington ---------------------------------------------------------- Module 4. Converting 40 track discs for 80 track drives ------------------------------------------------------- +----------------------------------------------------------+ | All the DFS modules in this series use programs which | | experiment with the format and contents of discs. These | | experiments may have disasterous effects if you use any | | of the programs on discs which store programs or data | | which you cannot afford to lose. You should first try | | out the programs using discs that have either been | | duplicated or, better still, have not been used at all. | +----------------------------------------------------------+ In this module I will examine the problem of modifying forty track discs so that they work properly on eighty track disc drives. There are a number of possible solutions to the problem of using forty track discs on an eighty track disc drive. If you have a 40/80 track switchable disc drive it is possible to use *BACKUP 0 0 and switch the track density selector from forty to eighty before inserting an eighty track disc and then switch back to forty for the forty track disc. If you use dual switchable drives this can be a less error prone method because you would not have to remember to switch the drives between reading and writing. One problem with this method is that, although it will produce a disc which can be used on an eighty track disc drive, it will only use forty of the eighty tracks. This could be overcome by using the *COPY command and switching the track density selector appropriately. A philosophical problem with using either of these methods to make the conversion is that the conversion itself is pointless if you have switchable disc drives. The real problem exists for disc users who have a forty track disc and only one eighty track disc drive. In these circumstances it is necessary to modify the disc itself so that it becomes an eighty track disc. In this module I will demonstrate how to use the Osword &7F commands to modify a forty track disc on an eighty track disc drive so that the forty track disc becomes an eighty track disc. Forty track discs have a track density exactly one half of that used by eighty track discs. Track &00 of both forty and eighty track discs share the same physical position as the outer track on the disc. Track &01 on a forty track disc is in the same physical position as track &02 on an eighty track disc, track &02 is in the same position as track &04, and so on. The relative position of the physical tracks on forty and eighty track discs is shown in figure 1. 40T> 00 01 ... 09 0A 0B ... 13 14 15 ... 25 26 27 80T> 00 01 02 ... 12 13 14 15 16 ... 26 27 28 29 2A ... 4A 4B 4C 4D 4E 4F Figure 1. The relative position of tracks on 40 and 80 track discs ------------------------------------------------------------------ All the numbers in figure 1 are in hexadecimal and I am using the term track density to refer to the physical proximity of the tracks (which are closer together on 80 track discs). Because the track density of an eighty track disc is twice that of a forty track disc, an eighty track disc is sometimes refered to as double density even if it uses the single density format. I will not refer to 80 track discs as double density because this can be confused with the double density ADFS, which can use 80 track discs in a double density format. If you look at figure 1 you should be able to work out what needs to be done to make forty track discs work on an eighty track disc drive. Because track &00 is in the same physical position with both forty and eighty track discs, any data on track &00 can be accessed with either type of disc drive. All the other tracks on a forty track disc are in the wrong physical position to be read on an eighty track disc drive. Assuming that you have an Acorn DFS forty track disc in an eighty track disc drive, you will need to copy physical track &02 (logical track &01) onto physical track &01, copy physical track &04 (logical track &02) onto physical track &02 and so on until physical track &4E (logical track &27) is copied onto physical track &27. This copying is summarised in figure 2. Read physical track -> Format and write physical track &00 -> &00 &02 -> &01 &04 -> &02 &06 -> &03 . . . &4B -> &25 &4C -> &26 &4E -> &27 Figure 2. The required copying of physical tracks ------------------------------------------------- You should note that figure 2 refers to the physical tracks and not the logical tracks. This is important because, with Acorn DFS forty track discs in an eighty track disc drive, physical track &02 will contain logical track &01, physical track &04 will contain logical track &02, and so on. It will be necessary to re-format each physical track after reading and before writing the data back onto the disc. This is because the odd numbered tracks will be unformatted and the even numbered tracks will have the wrong logical track numbers in their ID fields. When all forty tracks have been copied you can then go on to format the tracks from &28 to &4F to make the disc an eighty track disc. In order that the DFS can access all eighty tracks it is necessary to modify the catalogue to indicate that 800 (&320) sectors are available. The number of sectors is stored in bytes &06 (MSB) and &07 (LSB) of track &00, sector &00. Note that it is not LSB and MSB as you might expect. The following algorithm can be used to implement this idea. 1) Start with current track number = &00 2) Seek current track * 2 (ie. for logical track &01 seek &02, and so on) 3) Write the current track number into the track register (number &12). The head is now positioned above the appropriate track for reading the data and the track register also contains the logical track number. 4) Read the entire track into a buffer. 5) Write the current track number * 2 into the track register. 6) Format the physical track indicated by the current track number. 7) Write the contents of the buffer onto the newly formatted track. 8) Increment the current track number. If the current track number is less than &28 go back to 2) to copy the next track. 9) All forty tracks have been converted. Now format tracks &28 to &4F to create an eighty track disc. 10) Read the contents of track &00, sector &01 into a buffer. 11) OR the contents of buffer+&06 with the number &03, and store the number &20 in buffer+&07 to indicate that &320 (800) sectors are available on the disc. 12) Write the contents of the buffer back onto track &00, sector &01. This algorithm has been implemented in the program CONVERT. You can use the program CONVERT with an eighty track drive &00 to convert an Acorn formatted 40 track single density disc into an eighty track single density disc. The program will not work with copy-protected discs and you should only use it if you have a duplicate of the disc you intend to convert. If you use CONVERT and press the Escape key before it has finished the conversion you will probably destroy some or all the data on the disc. Do not use the program with a forty track disc drive. You have been warned to be careful with all the programs used to illustrate this series. This program can easily destroy all the data on your disc if you fail to use it with care. If you want to modify the program to make it more idiot proof you could delete line 130 to take out the routine which polls the Escape flag. This would make the program safer for ham-fisted or inexperienced users because pressing Escape would not halt the program before it had finished. Whatever modifications you make to this or any other of the programs used to ilustrate the DFS modules of the series, don't ignore the warning about the potentially disasterous effects these programs can have on your discs. 10 REM: CONVERT 20 osnewl=&FFE7 30 oswrch=&FFEE 40 osword=&FFF1 50 osbyte=&FFF4 60 DIM mcode &500 70 DIM buffer &1000 80 FOR pass=0 TO 2 STEP 2 90 P%=mcode 100 [ OPT pass 110 JSR osnewl 120 .mainloop 130 JSR escape \ check escape flag 140 JSR seektwo \ seek track * 2 150 LDA track \ load logical track number 160 JSR register \ write track register 170 JSR read \ read logical track 180 LDA track \ load logical track number 190 ASL A \ *2 = physical track 200 JSR register \ write track register 210 JSR format \ format physical track 220 JSR write \ write data onto disc 230 JSR printbyte \ print track number 240 INC track \ get ready for next track 250 LDA track \ load logical track number 260 CMP #40 \ is it track 40? 270 BNE mainloop \ if not read next track 280 .formloop 290 JSR escape \ check escape flag 300 JSR format \ format tracks 40 - 79 310 JSR printbyte \ print track number 320 INC track \ increment track number 330 LDA track \ load track number 340 CMP #80 \ is it 80? 350 BNE formloop \ if not format next track 360 LDA #0 \ go back to track 0 370 STA track 380 STA copyblock+7 390 LDA #1 \ sector 1 400 STA copyblock+8 410 LDA #&21 \ 1 sector of 256 bytes 420 STA copyblock+9 430 JSR read \ read track 0 sector 1 440 LDA #&03 \ 800 sectors DIV 256 450 ORA buffer+6 \ keep old *OPT4,n option 460 STA buffer+6 \ MSB number of sectors 470 LDA #&20 \ 800 sectors MOD 256 480 STA buffer+7 \ LSB number of sectors 490 JSR write \ store track 0 sector 1 500 JSR osnewl 510 RTS \ return to BASIC 520 .escape 530 LDA &FF \ escape flag 540 BMI pressed \ bit 7 set if pressed 550 RTS 560 .pressed 570 LDA #&7E 580 JSR osbyte \ acknowledge Escape 590 BRK 600 BRK 610 EQUS "Escape" 620 BRK 630 .seektwo 640 LDA track \ source track number 650 ASL A \ *2 660 STA seekblock+7 \ physical track number 670 LDA #&7F 680 LDX #seekblock MOD 256 690 LDY #seekblock DIV 256 700 JSR osword 710 LDA seekblock+8 \ result 720 BNE seekerror \ = 0 if OK 730 RTS 740 .seekerror 750 BRK 760 BRK 770 EQUS "Seek error" 780 BRK 790 .format 800 LDA track \ source track number 810 STA formblock+7 \ store physical track 820 LDX #36 830 .tableloop 840 STA table,X \ store logical track number in ID table 850 DEX 860 DEX 870 DEX 880 DEX 890 BPL tableloop 900 LDA #&7F 910 LDX #formblock MOD 256 920 LDY #formblock DIV 256 930 JSR osword 940 LDA formblock+12 \ result 950 BNE formerror \ = 0 if OK 960 RTS 970 .formerror 980 BRK 990 BRK 1000 EQUS "Format error" 1010 BRK 1020 .register 1030 STA regblock+8 \ value to put in register 1040 LDA #&7F 1050 LDX #regblock MOD 256 1060 LDY #regblock DIV 256 1070 JSR osword 1080 LDA regblock+9 \ result 1090 BNE regerror \ = 0 if OK 1100 RTS 1110 .regerror 1120 BRK 1130 BRK 1140 EQUS "Special register error" 1150 BRK 1160 .read 1170 LDA track \ source track number 1180 STA copyblock+7 \ logical track number 1190 LDA #&53 \ read data multi-sector 1200 STA copyblock+6 1210 LDA #&7F 1220 LDX #copyblock MOD 256 1230 LDY #copyblock DIV 256 1240 JSR osword 1250 LDA copyblock+10 1260 BNE readerror 1270 RTS 1280 .readerror 1290 BRK 1300 BRK 1310 EQUS "Read error" 1320 BRK 1330 .write 1340 LDA #&4B \ write data multi-sector 1350 STA copyblock+6 1360 LDA #&7F 1370 LDX #copyblock MOD 256 1380 LDY #copyblock DIV 256 1390 JSR osword 1400 LDA copyblock+10 \ result 1410 BNE writeerror \ = 0 if OK 1420 RTS 1430 .writeerror 1440 BRK 1450 BRK 1460 EQUS "Write error" 1470 BRK 1480 .printbyte 1490 LDA track \ print source track number 1500 PHA 1510 LSR A 1520 LSR A 1530 LSR A 1540 LSR A 1550 JSR nybble \ print MS nybble 1560 PLA 1570 JSR nybble \ print LS nybble 1580 LDA #ASC(" ") 1590 JSR oswrch \ print space 1600 JMP oswrch \ print space 1610 .nybble 1620 AND #&0F 1630 SED 1640 CLC 1650 ADC #&90 1660 ADC #&40 1670 CLD 1680 JMP oswrch \ print nybble and return 1690 .seekblock 1700 EQUB &00 \ drive 0 1710 EQUD &00 \ does not matter 1720 EQUB &01 \ 1 parameter 1730 EQUB &69 \ seek command 1740 EQUB &00 \ physical track 1750 EQUB &00 \ result byte 1760 .regblock 1770 EQUB &00 \ drive 0 1780 EQUD &00 \ does not matter 1790 EQUD &00127A02 \ write special register 1800 EQUB &00 \ result byte 1810 .copyblock 1820 EQUB &00 \ drive 0 1830 EQUD buffer \ address of buffer 1840 EQUB &03 \ 3 parameters 1850 EQUB &57 \ read data multi-sector 1860 EQUB &00 \ logical track number 1870 EQUB &00 \ logical sector number 1880 EQUB &2A \ 10 sectors of 256 bytes 1890 EQUB &00 \ result byte 1900 .formblock 1910 EQUB &00 \ drive 0 1920 EQUD table \ address of sector table 1930 EQUB &05 \ 5 parameters 1940 EQUB &63 \ format command 1950 EQUB &00 \ physical track number 1960 EQUB &15 \ gap 3 size 1970 EQUB &2A \ 10 sectors of 256 bytes 1980 EQUB &00 \ gap 5 size 1990 EQUB &10 \ gap 1 size 2000 EQUB &00 \ result byte 2010 .table 2020 EQUD &01000000 2030 EQUD &01010000 2040 EQUD &01020000 2050 EQUD &01030000 2060 EQUD &01040000 2070 EQUD &01050000 2080 EQUD &01060000 2090 EQUD &01070000 2100 EQUD &01080000 2110 EQUD &01090000 2120 .track 2130 EQUB &00 \ logical track number 2140 ] 2150 NEXT 2160 PRINT'"Place 40 track disc in 80 track drive 0" 2170 PRINT"Press Spacebar to convert to 80 tracks" 2180 REPEAT 2190 UNTIL GET = 32 2200 CALL mcode