home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / qbnewsl / qbnws105 / qbformat / qbformat.bas < prev   
BASIC Source File  |  1990-10-25  |  17KB  |  525 lines

  1. DECLARE FUNCTION QBFORMAT% (drive%, media%)
  2. DECLARE FUNCTION FormatDisk% (drive%)
  3. DECLARE FUNCTION FormatTrack% (drive%, track%, head%)
  4. DECLARE FUNCTION ValidateDisk% (drive%, media%)
  5. DECLARE FUNCTION WriteBoot% (drive%)
  6. DECLARE FUNCTION WriteDir% (drive%)
  7. DECLARE FUNCTION WriteFAT% (drive%)
  8. DECLARE FUNCTION WriteSector% (drive%, cyl%, hd%, sec%)
  9. DECLARE FUNCTION WriteBootSector% (drive%)
  10. DECLARE SUB ComputeCHS (LogSec%, cyl%, hd%, sec%)
  11. DECLARE SUB InitFormatParms (media%)
  12. DECLARE SUB ResetFDC (drive%)
  13.  
  14. 'QBFORMAT.BAS by Cornel Huth 31-Oct-90
  15. 'format MS-DOS floppy disks using QB and BIOS
  16. 'requires QB.QLB/QB.LIB (specifically INTERRUPTX())
  17.  
  18. '{5.25-inch media types supported in this code}
  19. '{DS9=double-sided 9-sector(360K)  DS15=double-sided 15-sector (1.2M)}
  20. CONST DS9 = &HFD, DS15 = &HF9
  21. '{3.5-inch media types partially supported in this code}
  22. '{DX9=double-sided 9-sector(720K)  DX18=double-sided 18-sector (1.44M)}
  23. '{*** DX9 media byte is NEGATIVE to differ from DS15 ***}
  24. CONST DX9 = -&HF9, DX18 = &HF0
  25. CONST RETRIES = 3  '{retries on BIOS error}
  26.  
  27. TYPE REGtypeX
  28. ax AS INTEGER
  29. bx AS INTEGER
  30. cx AS INTEGER
  31. dx AS INTEGER
  32. bp AS INTEGER
  33. si AS INTEGER
  34. di AS INTEGER
  35. flags AS INTEGER
  36. ds AS INTEGER
  37. es AS INTEGER
  38. END TYPE '20
  39.  
  40. TYPE ADDRFIELDtype
  41. track AS STRING * 1
  42. head AS STRING * 1
  43. sector AS STRING * 1
  44. bytesec AS STRING * 1
  45. END TYPE '4
  46.  
  47. TYPE INFOtype
  48. OEM AS STRING * 8 'system name
  49. BS AS INTEGER     'bytes/sector
  50. SC AS STRING * 1  'sectors/cluster
  51. RS AS INTEGER     'reserved sectors
  52. NF AS STRING * 1  'FATs
  53. DE AS INTEGER     'root directory entries
  54. TS AS INTEGER     'total sectors on volume
  55. MB AS STRING * 1  'media byte
  56. SF AS INTEGER     'sectors/FAT
  57. ST AS INTEGER     'sectors/track
  58. NH AS INTEGER     'heads
  59. HS AS INTEGER     'hidden sectors
  60. END TYPE '27
  61.  
  62. TYPE BOOTRECtype
  63. jmp AS STRING * 3
  64. parms AS INFOtype
  65. code AS STRING * 482
  66. END TYPE '512
  67.  
  68. '{External routine included with QB 4.0 in QB.LIB & QB.QLB}
  69. '{The INTRPT.ASM supplied with QB 4.00 has 2 known bugs, one of}
  70. '{which is so bad that this code cannot work properly with it.}
  71. '{The INTRPT.ASM supplied with QB 4.00b has 1 known bug, this}
  72. '{code will work with it but DOS BIOS INT25/26h calls will not.}
  73. '{Later versions may still have that bug!}
  74. DECLARE SUB INTERRUPTX (intnum%, ireg AS REGtypeX, oreg AS REGtypeX)
  75.  
  76. DEFINT A-Z
  77. '{INT 1Eh disk parameter table vectors}
  78. DIM SHARED OldDPTseg, OldDPToff
  79. DIM SHARED NewDPTseg, NewDPToff
  80. '{Number of tracks on media}
  81. DIM SHARED NoTracks
  82. '{format info for media}
  83. DIM SHARED Info AS INFOtype
  84. '{interface with INTERRUPTX routine}
  85. DIM SHARED ireg AS REGtypeX, oreg AS REGtypeX
  86. '{boot record buffer}
  87. DIM SHARED BootRec AS BOOTRECtype
  88. '{sector buffer to write FAT & root directory sectors}
  89. DIM SHARED SectorBuff AS STRING * 512
  90. REM $STATIC
  91. '{Allocate address field data to max possible sectors per track}
  92. DIM SHARED AddrField(1 TO 18) AS ADDRFIELDtype
  93.  
  94. BootSector:
  95. DATA &HEB,&H3E,&H90,&H20,&H20,&H20,&H20,&H20,&H20,&H20,&H20,&H0,&H0,&H0,&H0,&H0
  96. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  97. DATA &HA,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  98. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  99. DATA &H2B,&HC0,&H8E,&HD0,&HBC,&H0,&H7C,&HB8,&HC0,&H7,&H8E,&HD8,&H8E,&HC0,&HBE,&H3
  100. DATA &H0,&HBF,&HAF,&H0,&HB9,&H4,&H0,&HF3,&HA5,&HBE,&HAF,&H0,&HB4,&HE,&H8A,&H4
  101. DATA &HA,&HC0,&H74,&H7,&H56,&HCD,&H10,&H5E,&H46,&HEB,&HF1,&HFC,&HBE,&H7A,&H0,&HBF
  102. DATA &H0,&H2,&HB9,&H0,&H2,&HF3,&HA4,&HE9,&H86,&H1,&HB8,&H1,&H2,&H2B,&HDB,&HB9
  103. DATA &H1,&H0,&HBA,&H50,&H0,&HCD,&H13,&H72,&HC,&HBB,&HFE,&H1,&H81,&H3F,&H55,&HAA
  104. DATA &H75,&H3,&HE9,&HE5,&HFD,&HBE,&H58,&H2,&HB4,&HE,&H8A,&H4,&HA,&HC0,&H74,&H7
  105. DATA &H56,&HCD,&H10,&H5E,&H46,&HEB,&HF1,&H2B,&HC0,&HCD,&H16,&HCD,&H19,&HCD,&H18,&H20
  106. DATA &H20,&H20,&H20,&H20,&H20,&H20,&H20,&H20,&H6E,&H6F,&H6E,&H2D,&H62,&H6F,&H6F,&H74
  107. DATA &H61,&H62,&H6C,&H65,&H20,&H64,&H69,&H73,&H6B,&H20,&H69,&H6E,&H20,&H41,&H3A,&HD
  108. DATA &HA,&H0,&H4E,&H6F,&H20,&H62,&H6F,&H6F,&H74,&H20,&H64,&H69,&H73,&H6B,&H20,&H66
  109. DATA &H6F,&H75,&H6E,&H64,&H2C,&H20,&H72,&H65,&H70,&H6C,&H61,&H63,&H65,&H20,&H61,&H6E
  110. DATA &H64,&H20,&H70,&H72,&H65,&H73,&H73,&H20,&H61,&H20,&H6B,&H65,&H79,&H20,&HD,&HA
  111. DATA &HD,&HA,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  112. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  113. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  114. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  115. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  116. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  117. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  118. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  119. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  120. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  121. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  122. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  123. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  124. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  125. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
  126. DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H55,&HAA
  127.  
  128. '============================================================================
  129. '{The following code is a sample run to format a disk}
  130. '{All other code can be compiled and put in a library}
  131. '{format test drive A: double-sided/9-sector media (360K)}
  132. '{...and you thought that this was going to be hard}
  133. drive = 0: media = DS9
  134. CLS : DO: LOOP WHILE INKEY$ <> ""
  135. INPUT "Insert DS9 disk to format in drive A: and press a key", a$
  136. INPUT "Press a key to start QBFORMAT", a$
  137. PRINT "formatting..."
  138. xerr = QBFORMAT(drive, media)
  139. IF xerr THEN
  140.    errl = xerr \ 256
  141.    errc = xerr AND 255
  142.    PRINT "*** Error level:"; errl; " code:"; errc
  143. ELSE
  144.    PRINT "done."
  145. END IF
  146. STOP
  147.  
  148. SUB ComputeCHS (LogSec, cyl, hd, sec)
  149. '{convert a DOS logical sector to BIOS form}
  150. CylSec = Info.ST * Info.NH
  151. cyl = LogSec \ CylSec
  152. rm = LogSec - (cyl * CylSec)
  153. hd = rm \ Info.ST
  154. sec = rm - (hd * Info.ST) + 1
  155.  
  156. END SUB
  157.  
  158. FUNCTION FormatDisk (drive)
  159. '{format a track at a time a side at a time}
  160. '{any error aborts format,diskette presumed unreliable}
  161. '{retry format 1 or 2 more times before trashing the diskette}
  162. FOR track = 0 TO (NoTracks - 1)
  163.    FOR head = 0 TO (Info.NH - 1)
  164.       FOR i = 1 TO RETRIES
  165.          xerr = FormatTrack(drive, track, head)
  166.          IF xerr = 0 THEN EXIT FOR
  167.       NEXT
  168.       IF xerr THEN FormatDisk = xerr: EXIT FUNCTION
  169.    NEXT
  170. NEXT
  171. FormatDisk = 0
  172.  
  173. END FUNCTION
  174.  
  175. FUNCTION FormatTrack (drive, track, head)
  176. '{Initialize address field for each sector on this track}
  177. FOR sec = 1 TO Info.ST
  178.    AddrField(sec).track = CHR$(track)
  179.    AddrField(sec).head = CHR$(head)
  180.    AddrField(sec).sector = CHR$(sec)
  181.    AddrField(sec).bytesec = CHR$(2)  '{bytecode 2 = 512-byte sector}
  182. NEXT
  183. ireg.ax = &H500 + Info.ST            '{format track with sectors/track}
  184. ireg.cx = (track * 256) + 1          '{track to format,start with sector 1}
  185. ireg.dx = (head * 256) + drive       '{head,drive}
  186. ireg.es = VARSEG(AddrField(1))       '{point to address field data}
  187. ireg.bx = VARPTR(AddrField(1))
  188. INTERRUPTX &H13, ireg, oreg
  189. cf = oreg.flags AND 1                '{cf=1 if disk error}
  190. IF cf THEN
  191.    e& = oreg.ax
  192.    IF e& < 0 THEN e& = e& + 65536
  193.    FormatTrack = e& \ 256            '{return with status byte}
  194.    ResetFDC drive
  195. ELSE ireg.ax = &H400 + Info.ST       '{ok, verify track integrity-}
  196.    INTERRUPTX &H13, ireg, oreg       '{-optional but recommended on format}
  197.    cf = oreg.flags AND 1             '{cf=1 if disk error}
  198.    IF cf THEN
  199.       e& = oreg.ax
  200.       IF e& < 0 THEN e& = e& + 65536
  201.       FormatTrack = e& \ 256         '{return with status byte}
  202.       ResetFDC drive
  203.    ELSE
  204.       FormatTrack = 0                '{format ok}
  205.    END IF
  206. END IF
  207.  
  208. END FUNCTION
  209.  
  210. SUB InitFormatParms (media)
  211. '{set up media's format data}
  212. Info.OEM = "IBM  3.1"   '{avoid changing 'IBM'}
  213. Info.BS = 512
  214. Info.RS = 1
  215. Info.NF = CHR$(2)
  216. Info.NH = 2
  217. Info.HS = 0
  218. SELECT CASE media
  219. CASE DS9
  220.    Info.SC = CHR$(2)
  221.    Info.DE = 112
  222.    Info.TS = 720
  223.    Info.MB = CHR$(DS9)
  224.    Info.SF = 2
  225.    Info.ST = 9
  226. CASE DS15
  227.    Info.SC = CHR$(1)
  228.    Info.DE = 224
  229.    Info.TS = 2400
  230.    Info.MB = CHR$(DS15)
  231.    Info.SF = 7
  232.    Info.ST = 15
  233. CASE DX9
  234.    Info.SC = CHR$(2)
  235.    Info.DE = 112
  236.    Info.TS = 720
  237.    Info.MB = CHR$(ABS(DX9))
  238.    Info.SF = 3
  239.    Info.ST = 9
  240. CASE DX18
  241.    Info.SC = CHR$(1)
  242.    Info.DE = 224
  243.    Info.TS = 2880
  244.    Info.MB = CHR$(DX18)
  245.    Info.SF = 9
  246.    Info.ST = 18
  247. CASE ELSE
  248.    Info.OEM = ""
  249.    Info.BS = 0
  250.    Info.RS = 0
  251.    Info.NF = CHR$(0)
  252.    Info.NH = 0
  253.    Info.HS = 0
  254.    Info.SC = CHR$(0)
  255.    Info.DE = 0
  256.    Info.TS = 0
  257.    Info.MB = CHR$(0)
  258.    Info.SF = 0
  259.    Info.ST = 0
  260. END SELECT
  261. NoTracks = Info.TS \ Info.NH \ Info.ST
  262. NewDPTseg = 0   'INT 1Eh vector
  263. NewDPToff = 0   'new -> disk parameter table for formatted media
  264. OldDPTseg = 0   'original-
  265. OldDPToff = 0   '-vector
  266.  
  267. END SUB
  268.  
  269. FUNCTION QBFORMAT (drive, media)
  270. '{control routine}
  271. xerr = ValidateDisk(drive, media)
  272. IF xerr = 0 THEN xerr = FormatDisk(drive) ELSE level = 1
  273. IF xerr = 0 THEN xerr = WriteBoot(drive) ELSE IF level = 0 THEN level = 2
  274. IF xerr = 0 THEN xerr = WriteFAT(drive) ELSE IF level = 0 THEN level = 3
  275. IF xerr = 0 THEN xerr = WriteDir(drive) ELSE IF level = 0 THEN level = 4
  276. IF xerr THEN IF level = 0 THEN level = 5
  277. '{reset INT 1Eh vector to original,check both for <>0}
  278. IF OldDPTseg <> 0 OR OldDPToff <> 0 THEN
  279.    ireg.ax = &H251E
  280.    ireg.ds = OldDPTseg
  281.    ireg.dx = OldDPToff
  282.    INTERRUPTX &H21, ireg, oreg
  283. END IF
  284. QBFORMAT = (level * 256) + xerr
  285.  
  286. 'sample call
  287. 'xerr = QBFORMAT(drive, media)
  288. 'IF xerr THEN errl = xerr \ 256: errc = xerr AND 255
  289.  
  290. 'level error codes
  291. '0:no error
  292. '1:validate error
  293. '2:format error
  294. '3:boot record write error
  295. '4:FAT write error
  296. '5:directory write error
  297.  
  298. 'floppy disk error codes (xerr,in decimal):
  299. '0:no error
  300. '1:invalid function request
  301. '2:address mark not found
  302. '3:write protected
  303. '4:sector not found
  304. '6:diskette changed
  305. '8:DMA overrun
  306. '9:DMA boundary error
  307. '12:media type not available
  308. '16:bad CRC
  309. '32:diskette controller failed
  310. '64:seek failed
  311. '128:time-out/drive not ready
  312.  
  313. END FUNCTION
  314.  
  315. SUB ResetFDC (drive)
  316. '{reset the controller after any BIOS FDC error}
  317. tax = ireg.ax
  318. tdx = ireg.dx
  319. ireg.ax = 0
  320. ireg.dx = drive
  321. INTERRUPTX &H13, ireg, oreg
  322. ireg.ax = tax
  323. ireg.dx = tdx
  324.  
  325. END SUB
  326.  
  327. FUNCTION ValidateDisk (drive, media)
  328. '{check if media supported by program,by drive,and if drive is ready}
  329. InitFormatParms media
  330. IF Info.ST THEN
  331.    '{check to see if there is CMOS RAM (means we have an AT BIOS)}
  332.    OUT &H70, &H10
  333.    CMOS = (INP(&H71) <> &HFF)
  334.    ResetFDC drive
  335.    IF CMOS THEN
  336.       '{get original INT 1Eh vector to disk parameter table}
  337.       ireg.ax = &H351E
  338.       INTERRUPTX &H21, ireg, oreg
  339.       OldDPTseg = oreg.es
  340.       OldDPToff = oreg.bx
  341.       '{set media type for format on AT BIOS/multi-media drive}
  342.       '{let BIOS determine if drive can format media with a DPT in BIOS ROM}
  343.       ireg.ax = &H1800
  344.       ireg.cx = ((NoTracks - 1) * 256) + Info.ST
  345.       ireg.dx = drive
  346.       FOR checks = 1 TO RETRIES '{zerr=0 no error}
  347.          INTERRUPTX &H13, ireg, oreg '{zerr=1 drive invalid}
  348.          zerr = oreg.ax \ 256   '{zerr=&H0C unknown media/maybe invalid CMOS}
  349.          IF zerr THEN ResetFDC drive ELSE EXIT FOR
  350.       NEXT
  351.       '{set INT 1Eh vector to this media's disk parameter table in BIOS ROM}
  352.       IF zerr = 0 THEN
  353.          NewDPTseg = oreg.es
  354.          NewDPToff = oreg.di
  355.          ireg.ax = &H251E
  356.          ireg.ds = NewDPTseg
  357.          ireg.dx = NewDPToff
  358.          INTERRUPTX &H21, ireg, oreg
  359.       ELSE
  360.          OldDPTseg = 0
  361.          OldDPToff = 0
  362.       END IF
  363.    ELSE
  364.       '{pre-AT BIOS}
  365.       '{much more work involved}
  366.       '{if you want more than DS9 support, you need to add it}
  367.       DEF SEG = 0: Equip = PEEK(&H410): DEF SEG
  368.       IF Equip AND 1 THEN
  369.          MaxDrive = ((Equip AND &HC0) \ 64) '{MaxDrive=0=1drive, 1=2}
  370.          IF (drive >= 0) AND (drive <= MaxDrive) THEN
  371.             'get diskette parameter table vector
  372.             ireg.ax = &H351E
  373.             INTERRUPTX &H21, ireg, oreg
  374.             DEF SEG = oreg.es: MaxSectors = PEEK(oreg.bx + 4): DEF SEG
  375.             IF MaxSectors = 9 THEN
  376.                SELECT CASE media
  377.                CASE DS9      '{supported media}
  378.                CASE ELSE
  379.                   zerr = &HC '{invalid media}
  380.                END SELECT
  381.             '{any other max sectors not supported here}
  382.             ELSE
  383.                SELECT CASE media
  384.                CASE ELSE
  385.                   zerr = &HC '{invalid media}
  386.                END SELECT
  387.             END IF
  388.          ELSE
  389.             zerr = 1 '{invalid drive}
  390.          END IF
  391.       ELSE
  392.          zerr = 1 '{no drives to format}
  393.       END IF
  394.    END IF
  395. ELSE
  396.    zerr = &HC '{media not supported by program}
  397. END IF
  398. '{physical check for disk in the drive}
  399. IF zerr = 0 THEN
  400.    ireg.ax = &H401    '{verify 1 sector from drive}
  401.    ireg.cx = &H1      '{track=0 sector=1}
  402.    ireg.dx = drive    '{head=0 drive=drive}
  403.    FOR checks = 1 TO RETRIES
  404.       INTERRUPTX &H13, ireg, oreg
  405.       IF oreg.flags AND 1 THEN   '{bad read}
  406.          e& = oreg.ax
  407.          '{need to detect an unformatted disk}
  408.          IF e& < 0 THEN e& = e& + 65536
  409.          zerr = e& \ 256
  410.          ResetFDC drive
  411.       ELSE
  412.          zerr = 0 '{good read,already formatted disk in drive}
  413.          EXIT FOR
  414.       END IF
  415.    NEXT
  416.    '{zerr may be any of the BIOS diskette error codes if non-zero here}
  417.    '{address mark not found(2)=unformatted disk in drive}
  418.    '{sector not found(4)=wacko disk but okay to proceed}
  419.    IF zerr = 2 OR zerr = 4 THEN zerr = 0
  420. END IF
  421. ValidateDisk = zerr
  422.  
  423. END FUNCTION
  424.  
  425. FUNCTION WriteBoot (drive)
  426. RESTORE BootSector
  427. '{read default boot record data}
  428. DEF SEG = VARSEG(BootRec): offset = VARPTR(BootRec)
  429. FOR i = 0 TO 511: READ byte: POKE offset + i, byte: NEXT: DEF SEG
  430. '{update OEM name and BIOS parameter block}
  431. BootRec.parms = Info
  432. '{write the boot record}
  433. FOR i = 1 TO RETRIES
  434.    xerr = WriteBootSector(drive)
  435.    IF xerr = 0 THEN EXIT FOR
  436. NEXT
  437. WriteBoot = xerr
  438.  
  439. END FUNCTION
  440.  
  441. FUNCTION WriteBootSector (drive)
  442. ireg.ax = &H300 + 1                  '{write 1 sector}
  443. ireg.cx = 1                          '{track 0,sector 1}
  444. ireg.dx = drive                      '{head 0,drive}
  445. ireg.es = VARSEG(BootRec)            '{point to boot record data}
  446. ireg.bx = VARPTR(BootRec)
  447. INTERRUPTX &H13, ireg, oreg
  448. cf = oreg.flags AND 1                '{cf=1 if disk error}
  449. IF cf THEN
  450.    e& = oreg.ax
  451.    IF e& < 0 THEN e& = e& + 65536
  452.    WriteBootSector = e& \ 256        '{return with status byte}
  453.    ResetFDC drive
  454. ELSE
  455.    WriteBootSector = 0               '{ok}
  456. END IF
  457.  
  458. END FUNCTION
  459.  
  460. FUNCTION WriteDir (drive)
  461. MID$(SectorBuff, 1, 1) = CHR$(0)
  462. FOR i = 2 TO 512
  463.    IF (i - 1) MOD 32 = 0 THEN
  464.       MID$(SectorBuff, i, 1) = CHR$(0)
  465.    ELSE
  466.       MID$(SectorBuff, i, 1) = CHR$(&HF6)
  467.    END IF
  468. NEXT
  469. LogSec = Info.RS + Info.HS + (Info.SF * ASC(Info.NF)) 'first logical dir sector
  470. FOR i = 1 TO (Info.DE \ 16)  'sectors needed for root directory
  471.    ComputeCHS LogSec, cyl, hd, sec
  472.    FOR k = 1 TO RETRIES
  473.       xerr = WriteSector(drive, cyl, hd, sec)
  474.       IF xerr = 0 THEN EXIT FOR
  475.    NEXT
  476.    IF xerr THEN WriteDir = xerr: EXIT FUNCTION
  477.    LogSec = LogSec + 1
  478. NEXT
  479. WriteDir = 0
  480.  
  481. END FUNCTION
  482.  
  483. FUNCTION WriteFAT (drive)
  484. '{do the hussle}
  485. FAT1$ = Info.MB + CHR$(255) + CHR$(255)
  486. FAT2$ = CHR$(0) + CHR$(0) + CHR$(0)
  487. FOR i = 1 TO 512: MID$(SectorBuff, i, 1) = CHR$(0): NEXT
  488. LogSec = Info.RS + Info.HS 'first logical FAT sector
  489. FOR i = 1 TO ASC(Info.NF)
  490.    FOR j = 1 TO Info.SF
  491.       IF j = 1 THEN MID$(SectorBuff, 1) = FAT1$ ELSE MID$(SectorBuff, 1) = FAT2$
  492.       ComputeCHS LogSec, cyl, hd, sec
  493.       FOR k = 1 TO RETRIES
  494.          xerr = WriteSector(drive, cyl, hd, sec)
  495.          IF xerr = 0 THEN EXIT FOR
  496.       NEXT
  497.       IF xerr THEN WriteFAT = xerr: EXIT FUNCTION
  498.       LogSec = LogSec + 1
  499.    NEXT
  500. NEXT
  501. WriteFAT = 0
  502.  
  503. END FUNCTION
  504.  
  505. FUNCTION WriteSector (drive, cyl, hd, sec)
  506. '{BIOS write a FAT or directory sector}
  507. ireg.ax = &H300 + 1
  508. ireg.cx = (cyl * 256) + sec
  509. ireg.dx = (hd * 256) + drive
  510. ireg.es = VARSEG(SectorBuff)
  511. ireg.bx = VARPTR(SectorBuff)
  512. INTERRUPTX &H13, ireg, oreg
  513. cf = oreg.flags AND 1
  514. IF cf THEN
  515.    e& = oreg.ax
  516.    IF e& < 0 THEN e& = e& + 65536
  517.    WriteSector = e& \ 256
  518.    ResetFDC drive
  519. ELSE
  520.    WriteSector = 0
  521. END IF
  522.  
  523. END FUNCTION
  524.  
  525.