format.txt Floppy disc formatter for Acorn DFS, MS-DOS, Opus DDOS and EDOS Version 2.01 Greg Cook, 17/Jun/2008 Below is a listing in BASIC I/II for the BBC Micro model B, B+ or Master. An alternative distribution is available (format-ssd.zip) which includes an SSD disc image, plus ASCII text scripts to format a DFS disc from scratch and install the formatter on it. You will require one of the supported disc controllers, namely:- - Opus EDOS interface for Model B, WD 2791 - Opus DDOS interface for Model B, WD 1770 - Watford Electronics interface for Model B, WD 1770 - Built-in interface on Model B+, WD 1770 - Built-in interface on Master 128, WD 1770 If anyone has the Opus 2791 controller please let me know as it will need a slight modification to support Quad Density (and my board came with another mod to the latch presets.) The earlier, more common Intel 8271 controller will not work with this program as it has an entirely different API. On a technical note, the x7xx FDCs prescribe a fixed gap2 sequence (aka read/write gap or ID gap); therefore the formats' conventional gap2 sequences are not reproduced here. Acknowledgements are due for the DOS disk parameter layout which comes from: http://www.ata-atapi.com/hiwdos.htm Warning: The code and documentation included in this document (including, but not limited to, program listings, program patches and session transcripts) are supplied without warranty, not even the implied warranties of merchantability or fitness for a particular purpose. In no event shall the author or his suppliers be liable for any loss, damage, injury or death, of any nature and howsoever caused, arising from the use of, or failure, inability or unwillingness to use, this software or documentation. Greg Cook debounce@yahoo.co.uk http://homepages.tesco.net/~rainstorm/ --- >*INFO *.* $.STAMP L 31900 38023 04F6 02 $.FORMAT L 30E00 38023 33CD 07 $.FORMATC L 31900 38023 1819 3B $.FORMATM L 31900 38023 19AA 54 $.FORMAMC L 31900 38023 09F0 6E >LOAD "FORMAT" >LIST 10REM >FORMAT 20REM Disc formatter for various WD 1770 controller based BBCs 30REM (Not suitable for machines with Intel 8271 controllers) 40REM Greg Cook 11/Jun/2008 50REM Version 2.00 70PROCget_controller 80PROCget_format 90PROCinit 100PROCget_drive 110PROCformat 120PROCinit_fs 130END 150DEF PROCget_controller 160LOCAL fdcs%:REM returns fdc% 170RESTORE 180READ fdcs% 190PRINT 200FOR fdc%=1 TO fdcs% 210PROCreaddata_fdc 220PRINT fdc%;": ";fdc_name$ 230NEXT 240PRINT 250INPUT "Controller: " fdc% 260ENDPROC 280DEF PROCget_format 290LOCAL formats%:REM returns format% 300READ formats% 310PRINT 320FOR format%=1 TO formats% 330PROCreaddata_format 340PRINT format%;": ";format_name$ 350NEXT 360PRINT 370INPUT "Format: " format% 380ENDPROC 400DEF PROCinit 410LOCAL fdcs%,iter%,formats% 420RESTORE 430READ fdcs% 440IF fdc%<=0 OR fdc%>fdcs% STOP 450FOR iter%=1 TO fdc% 460PROCreaddata_fdc 470NEXT 480IF fdc%formats% STOP 510FOR iter%=1 TO format% 520PROCreaddata_format 530NEXT 540IF format%=0 AND drive%<=3 970IF format_sides%>1 drive%=drive% AND 1 980PRINT '"WARNING: will overwrite disc in drive"; 990IF format_sides%>1 PRINT ;"s ";drive%;" and ";drive% OR 2 1000IF format_sides%<=1 PRINT ;" ";drive% 1010VDU 7 1020PRINT '"Do you want to proceed? (Y/N): "; 1030REPEAT 1040answer%=GET AND &DF 1050UNTIL answer%=&4E OR answer%=&59 1060IF answer%=&4E PRINT "no":END ELSE PRINT "yes" 1070ENDPROC 1090DEF PROCformat 1100LOCAL track%,side% 1110REM Initialise track buffer 1120PROClayout(format_mfm%) 1130: 1140REM Restore drive and test track range 1150PROClatch(drive%,0,format_mfm%,format_500k%) 1160?fdc_addr%=&08 EOR fdc_bus_mask%:CALLseekwait 1170?fdc_data%=format_tracks%-1 EOR fdc_bus_mask% 1180?fdc_addr%=&18 EOR fdc_bus_mask%:CALLseekwait 1190: 1200REM Format disc 1210FOR track%=0 TO format_tracks%-1 1220FOR side%=0 TO format_sides%-1 1230REM Lay out/interleave sectors 1240PROCid_layout 1250PROCwrite(track%,side%,fdc_write_track%) 1260NEXT, 1270: 1280ENDPROC 1300DEF PROClayout(mfm%) 1310PRINT '"Preparing track buffer" 1320IF mfm%=0 PROClayout_fm 1330IF mfm%=1 PROClayout_mfm 1340ENDPROC 1360DEF PROClayout_fm 1370LOCAL ptr%,sector%,buffer_size% 1380ptr%=buffer% 1390REM Gap 1 1400PROCdeposit(format_gap1%,&FF) 1410FOR sector%=0 TO format_sectors%-1 1420REM Sector header 1430PROCdeposit(&06,&00) 1440PROCbyte(&FE) 1450sector_off%(sector%)=ptr% 1460REM ID area, CHRN 1470PROCdeposit(&04,&00) 1480PROCbyte(&F7) 1490REM Gap 2 1500PROCdeposit(&0B,&FF) 1510REM Sector data 1520PROCdeposit(&06,&00) 1530PROCbyte(&FB) 1540REM Data area 1550PROCdeposit(format_sector_size%,&E5) 1560PROCbyte(&F7) 1570REM Gap 3 1580PROCdeposit(format_gap3%,&FF) 1590NEXT 1600IF format_500k% THEN buffer_size%=6250 ELSE buffer_size%=3125 1610PRINT "Gap 4 = ";buffer%+buffer_size%-ptr%-(2*format_sectors%) 1620PROCdeposit(buffer%+6275-ptr%,&FF) 1630ENDPROC 1650DEF PROClayout_mfm 1660LOCAL ptr%,sector%,buffer_size% 1670ptr%=buffer% 1680REM Gap 1 1690PROCdeposit(format_gap1%,&4E) 1700FOR sector%=0 TO format_sectors%-1 1710REM Sector header 1720PROCdeposit(&0C,&00) 1730PROCdeposit(&03,&F5) 1740PROCbyte(&FE) 1750sector_off%(sector%)=ptr% 1760REM ID area, CHRN 1770PROCdeposit(&04,&00) 1780PROCbyte(&F7) 1790REM Gap 2 1800PROCdeposit(&16,&4E) 1810REM Sector data 1820PROCdeposit(&0C,&00) 1830PROCdeposit(&03,&F5) 1840PROCbyte(&FB) 1850REM Data area, value &F6 not allowed 1860PROCdeposit(format_sector_size%,&E5) 1870PROCbyte(&F7) 1880REM Gap 3 1890PROCdeposit(format_gap3%,&4E) 1900NEXT 1910IF format_500k% THEN buffer_size%=12500 ELSE buffer_size%=6250 1920PRINT "Gap 4 = ";buffer%+buffer_size%-ptr%-(2*format_sectors%) 1930PROCdeposit(buffer%+12550-ptr%,&FF) 1940ENDPROC 1960DEF PROCstring(string$) 1970LOCAL iter% 1980IF string$="" ENDPROC 1990FOR iter%=1 TO LEN(string$) 2000PROCdeposit(&01,ASC(MID$(string$,iter%,1))) 2010NEXT 2020ENDPROC 2040DEF PROCdword(dword%) 2050PROCword(dword% AND &FFFF) 2060PROCword(dword% DIV &10000 AND &FFFF) 2070ENDPROC 2090DEF PROCword(word%) 2100PROCdeposit(&01,word% AND &FF) 2110PROCdeposit(&01,word% DIV 256 AND &FF) 2120ENDPROC 2140DEF PROCbyte(byte%) 2150PROCdeposit(&01,byte%) 2160ENDPROC 2180DEF PROCdeposit(count%,byte%) 2190LOCAL iter% 2200byte%=byte% EOR fdc_bus_mask% 2210FOR iter%=1 TO count% 2220?ptr%=byte% 2230ptr%=ptr%+1 2240NEXT 2250ENDPROC 2270DEF PROCid_layout 2280LOCAL token%,iter%,ptr% 2290token%=((track%*format_sides%+side%)*format_skew%+format_sectors%-1) MOD format_sectors% 2300FOR iter%=0 TO format_sectors%-1 2310?sector_off%(iter%)=&FE EOR fdc_bus_mask% 2320NEXT 2330FOR iter%=0 TO format_sectors%-1 2340REPEAT 2350token%=(token%+1) MOD format_sectors% 2360UNTIL(?sector_off%(token%) EOR fdc_bus_mask%)=&FE 2370ptr%=sector_off%(token%) 2380PROCbyte(track%) 2390PROCbyte(side%) 2400PROCbyte(iter%+format_sector_start%) 2410PROCbyte(sizecode%) 2420token%=(token%+format_ilv%-1) MOD format_sectors% 2430NEXT 2440ENDPROC 2460DEF PROCinit_fs 2470PRINT '"Preparing file system" 2480IF format_fs%=-1 PROCdfs 2490IF format_fs%=-2 PROCddos(format_aux%) 2500IF format_fs%=12 OR format_fs%=16 PROCdos(format_fs%,format_aux%) 2510ENDPROC 2530DEF PROCdfs 2540LOCAL ptr% 2550ptr%=buffer% 2560PROCdeposit(format_sector_size%+&06,&00) 2570PROCbyte(discsects% DIV 256 AND &07) 2580PROCbyte(discsects% AND &FF) 2590PROCdeposit(format_sector_size%-&08,&00) 2600PROCdeposit((format_sectors%-2)*format_sector_size%,&E5) 2610PROCwrite(0,0,fdc_write_sectors%) 2620ENDPROC 2640DEF PROCddos(volumes%) 2650LOCAL ptr%,asects%,atracks%,bsects% 2660IF volumes%>1 THEN asects%=FNceil(discsects%*5,9) ELSE asects%=discsects%-format_sectors% 2670atracks%=FNceil(asects%,format_sectors%) 2680asects%=atracks%*format_sectors% 2690bsects%=discsects%-format_sectors%-asects% 2700ptr%=buffer% 2710PROCdeposit(format_sector_size%+&06,&00) 2720PROCbyte(asects% DIV 256 AND &07) 2730PROCbyte(asects% AND &FF) 2740IF volumes%>1 PROCdeposit(2*format_sector_size%-&02,&00):PROCbyte(bsects% DIV 256 AND &07):PROCbyte(bsects% AND &FF) 2750PROCdeposit(format_sector_size%-&08,&00) 2760IF volumes%>2 PROCdeposit(format_sector_size%*(volumes%*2-4),&E5) 2770PROCbyte(&00):REM catalogue version number 2780PROCword(discsects% AND &7FF) 2790PROCbyte(format_sectors% AND &1F) 2800PROCbyte(format_tracks% AND &7F) 2810PROCdeposit(&03,&00) 2820PROCbyte(&01):REM volume A starts on track 1 2830PROCbyte(&00) 2840IF volumes%>1 PROCbyte(1+atracks%) ELSE PROCbyte(&00) 2850PROCdeposit(2*format_sector_size%-11,&00) 2860PROCwrite(0,0,fdc_write_sectors%) 2870ENDPROC 2890DEF PROCdos(fat%,media_type%) 2900LOCAL ptr%,iter%,dword%,fatsects%,fattail%,trackbytes%,sects_per_cluster%,root_dir_entries%,fs$ 2910REM broken, assumes volume is double sided 2920REM and second FAT starts on track 0 head 0 and ends on track 0 head 1 2930sects_per_cluster%=1:root_dir_entries%=&E0 2940IF media_type%=&F9 sects_per_cluster%=2:root_dir_entries%=&70 2950IF media_type%=-1 sects_per_cluster%=4:root_dir_entries%=&10:media_type%=&F0 2960fatsects%=FNceil((discsects% DIV sects_per_cluster%)*fat%,format_sector_size%*8) 2970fatbytes%=fatsects%*format_sector_size% 2980trackbytes%=format_sectors%*format_sector_size% 2990fs$=LEFT$("FAT"+STR$fat%+" ",8) 3000ptr%=RND(-(ABS(TIME EOR RND))) 3010ptr%=buffer% 3020FOR iter%=0 TO &1FF STEP 4 3030READ dword% 3040PROCdword(dword%) 3050NEXT 3060ptr%=buffer%+&0B 3070PROCword(format_sector_size%) 3080PROCbyte(sects_per_cluster%) 3090PROCword(1):REM reserved sectors 3100PROCbyte(2):REM number of FATs 3110PROCword(root_dir_entries%) 3120PROCword(discsects%) 3130PROCbyte(media_type%) 3140PROCword(fatsects%) 3150PROCword(format_sectors%) 3160PROCword(format_sides%) 3170PROCdword(0):REM number of hidden sectors 3180PROCdword(0):REM number of sectors huge (ignore) 3190PROCbyte(0):REM drive number 3200PROCbyte(0):REM reserved 3210PROCbyte(&29):REM signature 3220PROCdword(RND):REM serial number 3230PROCstring("NO NAME ") 3240PROCstring(fs$) 3250ptr%=buffer%+format_sector_size% 3260PROCbyte(media_type%) 3270PROCdeposit(&02,&FF) 3280PROCdeposit(format_sector_size%*(format_sectors%-1)-3,&00) 3290ptr%=buffer%+fatbytes%+format_sector_size% 3300PROCbyte(media_type%) 3310PROCdeposit(&02,&FF) 3320PROCwrite(0,0,fdc_write_sectors%) 3330ptr%=buffer% 3340fattail%=format_sector_size%+fatbytes%*2+root_dir_entries%*32-trackbytes% 3350IF fattail%<0 fattail%=0 3360IF fattail%>trackbytes% fattail=trackbytes% 3370IF fattail%>0 PROCdeposit(fattail%,&00) 3380IF fattail%