home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / FLOPPIES / FDFORM16.ZIP / FDFORMAT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-10-26  |  48.2 KB  |  1,198 lines

  1. {$A+,B-,D+,E+,F-,I-,L+,N-,O-,R-,S-,V-}
  2. {$M 8192,0,0}
  3. PROGRAM FDFORMAT;
  4.  
  5. USES dos,baseconv,desqview;
  6.  
  7.   {Copyright (c) 1988, Christoph H. Hochstätter}
  8.   {Compiled in Turbo-Pascal 5.5}
  9.   {Should Compile in Turbo-Pascal 5.0 also}
  10.   {Last Updated: 03-Sep-1989}
  11.  
  12.   {$IFDEF L49}
  13.  
  14. CONST text01 = 'Fehler ';
  15. CONST text02 = '(A)bbrechen (W)iederholen (I)gnorieren ? ';
  16. CONST t3     = 'W';
  17. CONST text04 = 'Kein gültiges Laufwerk.';
  18. CONST text05 = 'SUBST/ASSIGN/Netzwerk-Laufwerk.';
  19. CONST text06 = 'Kein Floppy-Laufwerk.';
  20. CONST text07 = 'Völlig unbekannte Laufwerksart';
  21. CONST text08 = 'Ich formatiere Laufwerk ';
  22. CONST text09 = ' Seite(n), ';
  23. CONST text10 = ' Spuren, ';
  24. CONST text11 = ' Sektoren/Spur, ';
  25. CONST text12 = ' Basisverzeichniseinträge, ';
  26. CONST text13 = ' Sektor(en)/Cluster, Sektoren-Versatz: ';
  27. CONST text14 = 'Kopf: ';
  28. CONST text15 = ', Zylinder: ';
  29. CONST text17 = 'Formatierfehler im Systembereich: Programm abgebrochen.';
  30. CONST text18 = 'Mehr als ';
  31. CONST text19 = ' Sektoren nicht lesbar. Programm abgebrochen.';
  32. CONST text20 = ' als schlecht markiert';
  33. CONST text21 = 'Format-Identifizierung:          ';
  34. CONST text22 = 'Gesamtsektoren auf der Diskette: ';
  35. CONST text23 = 'Sektoren pro Spur:               ';
  36. CONST text24 = 'Schreib-/Leseköpfe:              ';
  37. CONST text25 = 'Bytes pro Sektor:                ';
  38. CONST text26 = 'Versteckte Sektoren:             ';
  39. CONST text27 = 'Boot-Sektoren:                   ';
  40. CONST text28 = 'Anzahl der FAT''s:                ';
  41. CONST text29 = 'Sektoren pro FAT:                ';
  42. CONST text30 = 'Cluster auf Diskette:            ';
  43. CONST text31 = ' Bytes Gesamtkapazität';
  44. CONST text32 = ' Bytes in schlechten Sektoren';
  45. CONST text33 = ' Bytes auf der Diskette verfügbar';
  46. CONST text34 = 'Dieses Laufwerk kann nicht formatiert werden.';
  47. CONST text35 = 'Laufwerk ist physisch ';
  48. CONST text36 = 'BIOS Umschaltung 40/80 Spuren: ';
  49. CONST text37 = 'nach XT-Standard';
  50. CONST text38 = 'nach EPSON QX-16 Standard';
  51. CONST text39 = 'nach AT-Standard';
  52. CONST text40 = 'wird nicht unterstützt';
  53. CONST text41 = 'Syntax Error beim Aufruf.';
  54. CONST text42 = 'Format ist: FDFORMAT drive: [Optionen]';
  55. CONST text43 = '  Beispiel: FDFORMAT a: t41 h2 s10 C1 D112';
  56. CONST text44 = 'Parameter Bedeutung                              Voreinstellung';
  57. CONST text45 = 'drive:    Laufwerk, das formatiert werden soll   ----';
  58. CONST text46 = 'Tnn       Anzahl der Spuren je Seite             40/80 je nach Laufwerk';
  59. CONST text47 = 'Hnn       Anzahl der Seiten                      2';
  60. CONST text48 = 'Nnn       Anzahl der Sektoren je Spur            9/15/18 je nach Laufwerk';
  61. CONST text49 = 'Cn        Anzahl der Sektoren je Cluster         1 bei HD, 2 bei DD';
  62. CONST text50 = 'Dnnn      Anzahl der Basisverzeichniseinträge    224 bei HD, 112 bei DD';
  63. CONST text51 = 'Inn       Interleave-Faktor                      1';
  64. CONST text52 = 'Fnnn      Format festlegen';
  65. CONST text53 = 'R         Formatierung nicht verifizieren';
  66. CONST text69 = 'Bnnn      Diskettentypbyte festlegen             je nach Format';
  67. CONST text70 = 'Gnnn      GAP-Länge festlegen                    je nach Format';
  68. CONST text71 = 'Lesen Sie die READ.ME Datei für weitere Optionen';
  69. CONST text54 = 'Dieses Programm benötigt mindestens DOS 3.20.';
  70. CONST text55 = 'FDFORMAT -- Formatieren von Disketten mit erhöhter Kapazität';
  71. CONST text56 = 'Copyright (c) 03.01.1990, Christoph H. Hochstätter, Ver 1.60';
  72. CONST text57 = 'Sie können nur 1 oder 2 Seiten nehmen.';
  73. CONST text58 = 'Sie sollten schon mindestens eine Spur formatieren.';
  74. CONST text59 = 'Interleave muß von 1-';
  75. CONST text60 = ' sein.';
  76. CONST text61 = 'WARNUNG! DOS verwaltet bei Disketten nur 1 oder 2 Sektoren/Cluster';
  77. CONST text62 = 'WARNUNG! Zu viele Spuren. Das kann Ihr Laufwerk beschädigen';
  78. CONST text63 = 'WARNUNG! DOS verwaltet bei Disketten maximal 240 Basisverzeichniseinträge';
  79. CONST text64 = 'Neue Diskette in Laufwerk ';
  80. CONST text65 = ': einlegen';
  81. CONST text66 = 'Anschließend ENTER drücken (ESC=Abbruch)';
  82. CONST text67 = 'Übertragungsrate: ';
  83. CONST text68 = ', GAP-Länge: ';
  84. CONST text79 = 'Kann alte Formatierung nicht finden.';
  85. CONST text72 = 'EIN';
  86. CONST text73 = 'AUS';
  87. CONST text74 = 'Bitte Diskettennamen eingeben (max. 11 Zeichen): ';
  88. CONST text75 = 'Fehler beim Erstellen des Namens.';
  89. CONST text76 = 'Syntax-Fehler in der Datei FDFORMAT.CFG.';
  90. CONST text77 = 'Lesefehler in der Datei FDFORMAT.CFG.';
  91. CONST text78 = ', Sektoren: ';
  92. CONST error01 = 'Falsches Disketten-Steuer-Kommando';
  93. CONST error02 = 'Formatierung nicht gefunden';
  94. CONST error03 = 'Diskette ist schreibgeschützt';
  95. CONST error04 = 'Sektor nicht gefunden';
  96. CONST error06 = 'Unerlaubter Diskettenwechsel';
  97. CONST error08 = 'DMA-Baustein übergelaufen';
  98. CONST error09 = 'Mehr als 64 kByte im DMA Baustein';
  99. CONST error0c = 'Format nicht kompatibel mit Datenübertragungsrate';
  100. CONST error10 = 'Zyklische Redundanzprüfung fehlerhaft';
  101. CONST error20 = 'Diskettenadapter fehlerhaft';
  102. CONST error40 = 'Laufwerkskopf konnte nicht positioniert werden';
  103. CONST error80 = 'Keine Diskette im Laufwerk oder falsch eingelegt';
  104. CONST errorxx = 'Fehlerursache unbekannt';
  105.  
  106.   {$ENDIF}
  107.   {$IFDEF L1}
  108.  
  109. const text01 = 'Error ';
  110. const text02 = '(A)bort (R)etry (I)gnore ? ';
  111. const t3     = 'R';
  112. const text04 = 'No valid drive.';
  113. const text05 = 'SUBST/ASSIGN/Network-Drive.';
  114. const text06 = 'Not a floppy drive.';
  115. const text07 = 'Unknown drive type.';
  116. const text08 = 'Formatting drive ';
  117. const text09 = ' Head(s), ';
  118. const text10 = ' Tracks, ';
  119. const text11 = ' Sectors/track, ';
  120. const text12 = ' Root Directory Entries, ';
  121. const text13 = ' Sector(s)/Cluster, Sector-Shift: ';
  122. const text14 = 'Head: ';
  123. const text15 = ', Cylinder: ';
  124. const text17 = 'Format error in system area: Program aborted.';
  125. const text18 = 'More than ';
  126. const text19 = ' sectors unreadable. Program aborted.';
  127. const text20 = ' marked as bad';
  128. const text21 = 'OEM-Entry:              ';
  129. const text22 = 'Total sectors on disk:  ';
  130. const text23 = 'Sectors per track:      ';
  131. const text24 = 'Heads:                  ';
  132. const text25 = 'Bytes per sector:       ';
  133. const text26 = 'Hidden sectors:         ';
  134. const text27 = 'Boot-sectors:           ';
  135. const text28 = 'Number of FATs:         ';
  136. const text29 = 'Sectors per FAT:        ';
  137. const text30 = 'Total clusters on disk: ';
  138. const text31 = ' total bytes on disk';
  139. const text32 = ' bytes in bad sectors';
  140. const text33 = ' bytes available';
  141. const text34 = 'This drive cannot be formatted.';
  142. const text35 = 'Drive is physical ';
  143. const text36 = 'BIOS double-step support: ';
  144. const text37 = 'XT-like';
  145. const text38 = 'EPSON QX-16 like';
  146. const text39 = 'AT-like';
  147. const text40 = 'Not available or unknown';
  148. const text41 = 'Syntax Error.';
  149. const text42 = 'Usage is: FDFORMAT drive: [options]';
  150. const text43 = ' Example: FDFORMAT a: t41 h2 s10 C1 D112';
  151. const text44 = 'Option   Meaning                                 Default';
  152. const text45 = 'drive:   drive to be formatted                   none';
  153. const text46 = 'Tnn      Number of tracks                        40/80 depends on drive';
  154. const text47 = 'Hnn      Number of heads                         2';
  155. const text48 = 'Nnn      Number of sectors per track             9/15/18 depends on drive';
  156. const text49 = 'Cn       Number of sectors per cluster           1 for HD, 2 for DD';
  157. const text50 = 'Dnnn     Number of root directory entries        224 for HD, 112 for DDD';
  158. const text51 = 'Inn      Interleave                              1';
  159. const text52 = 'F        specify Diskette format';
  160. const text53 = 'R        Skip verifying';
  161. const text69 = 'Bnnn     Force a specified Format-Descriptor     depends on format';
  162. const text70 = 'Gnnn     Use specified GAP-Length                depends on format';
  163. const text71 = 'See the READ.ME file for other options';
  164. const text54 = 'This program requires DOS 3.2 or higher.';
  165. const text55 = 'FDFORMAT - Disk Formatter for High Capacity Disks - Ver 1.60';
  166. const text56 = 'Copyright (c) 03-Jan-1990, Christoph H. Hochstätter, Germany';
  167. const text57 = 'Heads must be 1 or 2.';
  168. const text58 = 'At least one track should be formatted.';
  169. const text59 = 'Interleave must be from 1 to ';
  170. const text60 = '.';
  171. const text61 = 'WARNING! DOS supports only 1 or 2 sectors per cluster.';
  172. const text62 = 'WARNING! That many tracks could cause damage to your drive.';
  173. const text63 = 'WARNING! DOS supports a maximum of 240 root directory entries.';
  174. const text64 = 'Insert new Diskette in drive ';
  175. const text65 = ':';
  176. const text66 = 'Press ENTER when ready (ESC=QUIT)';
  177. const text67 = 'Data Transfer Rate: ';
  178. const text68 = ', GAP-Length: ';
  179. const text79 = 'Cannot find old format of diskette.';
  180. const text72 = 'ON';
  181. const text73 = 'OFF';
  182. const text74 = 'Enter Volume Name (max. 11 characters): ';
  183. const text75 = 'Error creating volume label.';
  184. const text76 = 'Syntax Error in FDFORMAT.CFG.';
  185. const text77 = 'Error reading FDFORMAT.CFG.';
  186. const text78 = ', Sectors: ';
  187. CONST error01 = 'Illegal Command. Bug in FDFORMAT';
  188. CONST error02 = 'Address mark not found';
  189. CONST error03 = 'Disk is write protected';
  190. CONST error04 = 'Sector not found';
  191. CONST error06 = 'Illegal disk change';
  192. CONST error08 = 'DMA overrun';
  193. CONST error09 = 'DMA accross 64 kB boundary';
  194. CONST error0c = 'Format not compatible with data transfer rate';
  195. CONST error10 = 'CRC error';
  196. CONST error20 = 'controller/adapter error';
  197. CONST error40 = 'seek error';
  198. CONST error80 = 'No disk in drive';
  199. CONST errorxx = 'Unknown error';
  200.  
  201. {$ENDIF}
  202.  
  203. CONST maxform = 20;
  204.  
  205. TYPE tabletyp = ARRAY[1..25] OF RECORD
  206.                                   t,h,s,f:Byte;
  207.                                 END;
  208.  
  209.   paratyp =  ARRAY[0..10] OF Byte;
  210.   boottyp =  ARRAY[30..511] OF Byte;
  211.  
  212.   btttyp  =  ARRAY[1..20] OF RECORD
  213.                                head:  Byte;
  214.                                track: Byte;
  215.                              END;
  216.   ftabtyp = ARRAY[1..maxform] OF RECORD
  217.                                    fmt: Word;
  218.                                    trk: Byte;
  219.                                    sec: Byte;
  220.                                    hds: Byte;
  221.                                  END;
  222.  
  223.   bpbtyp  =  RECORD
  224.                jmp: ARRAY[1..3] OF Byte;                                     {Die ersten drei Bytes für JUMP}
  225.                oem: ARRAY[1..8] OF Char;                                                        {OEM-Eintrag}
  226.                bps: Word;                                                                  {Bytes pro Sektor}
  227.                spc: Byte;                                                              {Sektoren pro Cluster}
  228.                res: Word;                                                                     {BOOT-Sektoren}
  229.                fat: Byte;                                                                  {Anzahl der FAT's}
  230.                rde: Word;                                                          {Basisverzeichniseinträge}
  231.                sec: Word;                                                       {Gesamtsektoren der Diskette}
  232.                mds: Byte;                                                                  {Media-Deskriptor}
  233.                spf: Word;                                                                  {Sektoren pro FAT}
  234.                spt: Word;                                                                 {Sektoren pro Spur}
  235.                hds: Word;                                                                            {Seiten}
  236.                shh: Word;                                                               {Versteckte Sektoren}
  237.                boot_code: boottyp;                                                     {Puffer für BOOT-Code}
  238.              END;
  239.  
  240. VAR regs:     registers;                                                                 {Prozessor-Register}
  241.   track:      Byte;                                                                           {Aktuelle Spur}
  242.   head:       Byte;                                                                          {Aktuelle Seite}
  243.   table:      tabletyp;                                                               {Formatierungs-Tabelle}
  244.   table2:     ARRAY[1..25] OF Byte;                                                      {Interleave-Tabelle}
  245.   x:          Word;                                                                           {Hilfsvariable}
  246.   buffer:     ARRAY[0..18432] OF Byte;                                      {Puffer für eingelesene Sektoren}
  247.   old1E:      Pointer;                                                  {Alter Zeiger auf die Parameterliste}
  248.   new1E:      ^paratyp;                                                 {Neuer Zeiger auf die Parameterliste}
  249.   old13:      Pointer;                                                        {Alter Zeiger auf Interrupt 13}
  250.   old58:      Pointer;                                                   {Alter Zeiger auf Hilfsinterrupt 58}
  251.   bpb:        bpbtyp;                                                   {Boot-Sektor mit BIOS-Parameterblock}
  252.   chx:        Char;                                                                           {Hilfsvariable}
  253.   lw:         Byte;                                                                   {Ausgewähltes Laufwerk}
  254.   hds,sec:    Word;                                                             {Anzahl der Seiten, Sektoren}
  255.   trk:        Word;                                                                       {Anzahl der Spuren}
  256.   hd,lwhd:    Boolean;                                                                   {High-Density Flags}
  257.   lwtrk:      Byte;                                                           {maximale Spuren des Laufwerks}
  258.   lwsec:      Byte;                                                         {maximale Sektoren des Laufwerks}
  259.   para:       ARRAY[1..50] OF String[20];                                   {Parameter von der Kommandozeile}
  260.   rde:        Byte;                                                                {Basisverzeichniseinträge}
  261.   spc:        Byte;                                                                    {Sektoren pro Cluster}
  262.   i:          Byte;                                                                          {Hilfsvariablen}
  263.   j,n:        Integer;                                                                        {Hilfsvariable}
  264.   again:      Boolean;                                                   {Flag, ob INT 13 nochmal kommen muß}
  265.   bttCount:   Word;                                                            {Anzahl der schlechten Spuren}
  266.   btt:        btttyp;                                                         {Tabelle der schlechten Spuren}
  267.   Offset:     Word;                                                                {Relative Position im FAT}
  268.   Mask:       Word;                                                            {Maske für schlechten Cluster}
  269.   bytes:      LongInt;                                                                {Bytes Gesamtkapazität}
  270.   bad:        LongInt;                                                         {Bytes in schlechten Sektoren}
  271.   at80:       Boolean;                                                   {TRUE, wenn 80/40 Spur nach AT-BIOS}
  272.   noverify:   Boolean;                                               {TRUE, wenn Verify nicht verlangt wurde}
  273.   DiskId:     Byte;                                               {Disketten-Format-Beschreibung für AT-BIOS}
  274.   il:         Byte;                                                                       {Interleave-Faktor}
  275.   gpl:        Byte;                                                                               {GAP-Länge}
  276.   shiftt:     Byte;                                                              {Sektor-Shifting für Spuren}
  277.   shifth:     Byte;                                                               {Sektor-Shifting für Köpfe}
  278.   ModelByte:  Byte ABSOLUTE $F000:$FFFE;                                                          {XT/AT/386}
  279.   ForceType:  Byte;                                                                      {Gezwungener Diskid}
  280.   ForceMedia: Byte;                                                            {Erzwungener Media-Deskriptor}
  281.   dosdrive:   Byte;                                                            {DOS-Laufwerks-Identifizierer}
  282.   PCount:     Byte;                                                                    {Anzahl der Parameter}
  283.   found:      Boolean;                                                                      {Format gefunden}
  284.   sys:        Boolean;                                                                {System initialisieren}
  285.   lwtab:      ARRAY[0..3] OF Byte ABSOLUTE $40:$90;                                   {Tabelle der Laufwerke}
  286.   dlabel:     String[15];                                                                   {Disketten-Label}
  287.   setlabel:   Boolean;                                                                         {Label setzen}
  288.   batch:      Boolean;                                                                {Ohne Tastatur-Abfrage}
  289.   cfgat80:    Boolean;                                              {TRUE, wenn Laufwerk für AT konfiguriert}
  290.   cfgpc80:    Boolean;                                              {TRUE, wenn Laufwerk für XT konfiguriert}
  291.   noformat:   Boolean;                                     {TRUE, wenn nicht physisch formatiert werden soll}
  292.   cfgdrive:   Byte;                                                          {Laufwerksart aus Konfiguration}
  293.   bios:       Boolean;                                                          {TRUE, wenn nur BIOS-Aufrufe}
  294.   pc80:       Byte;                                                         {Maske, für 80 Spur nach XT-BIOS}
  295.   pc40:       Byte;                                                         {Maske, für 80 Spur nach XT-BIOS}
  296.   v720:       Byte;                                                                 {Media-Typ für 720 kByte}
  297.   v360:       Byte;                                                                 {Media-Typ für 360 kByte}
  298.   v12:        Byte;                                                                 {Media-Typ für 1.2 MByte}
  299.   v144:       Byte;                                                                {Media-Typ für 1.44 MByte}
  300.  
  301. CONST para17: paratyp =($df,$02,$25,$02,17,$02,$ff,$23,$f6,$0f,$08);
  302.   para18a:    paratyp =($df,$02,$25,$02,18,$02,$ff,$02,$f6,$0f,$08);
  303.   para18:     paratyp =($df,$02,$25,$02,18,$02,$ff,$6c,$f6,$0f,$08);
  304.   para10:     paratyp =($df,$02,$25,$02,10,$02,$ff,$2e,$f6,$0f,$08);                              {GPL 26-36}
  305.   para11:     paratyp =($df,$02,$25,$02,11,$02,$ff,$02,$f6,$0f,$08);
  306.   para15:     paratyp =($df,$02,$25,$02,15,$02,$ff,$54,$f6,$0f,$08);
  307.   para09:     paratyp =($df,$02,$25,$02,09,$02,$ff,$50,$f6,$0f,$08);
  308.   para08:     paratyp =($df,$02,$25,$02,08,$02,$ff,$58,$f6,$0f,$08);
  309.   para20:     paratyp =($df,$02,$25,$02,20,$02,$ff,$2a,$f6,$0f,$08);                              {GPL 17-33}
  310.   para21:     paratyp =($df,$02,$25,$02,21,$02,$ff,$0c,$f6,$0f,$08);
  311.   para22:     paratyp =($df,$02,$25,$02,22,$02,$ff,$01,$f6,$0f,$08);
  312.  
  313.   ftab:    ftabtyp = ((fmt:160;trk:40;sec:8;hds:1),                                {Requires 180 kByte Drive}
  314.                       (fmt:180;trk:40;sec:9;hds:1),                                {Requires 180 kByte Drive}
  315.                       (fmt:200;trk:40;sec:10;hds:1),                               {Requires 180 kByte Drive}
  316.                       (fmt:205;trk:41;sec:10;hds:1),                               {Requires 180 kByte Drive}
  317.                       (fmt:320;trk:40;sec:8;hds:2),                                {Requires 360 kByte Drive}
  318.                       (fmt:360;trk:40;sec:9;hds:2),                                {Requires 360 kByte Drive}
  319.                       (fmt:400;trk:40;sec:10;hds:2),                               {Requires 360 kByte Drive}
  320.                       (fmt:410;trk:41;sec:10;hds:2),                               {Requires 360 kByte Drive}
  321.                       (fmt:720;trk:80;sec:9;hds:2),                                {Requires 720 kByte Drive}
  322.                       (fmt:800;trk:80;sec:10;hds:2),                               {Requires 720 kByte Drive}
  323.                       (fmt:820;trk:82;sec:10;hds:2),                               {Requires 720 kByte Drive}
  324.                       (fmt:120;trk:80;sec:15;hds:2),                               {Requires 1.2 MByte Drive}
  325.                       (fmt:12;trk:80;sec:15;hds:2),                                {Requires 1.2 MByte Drive}
  326.                       (fmt:144;trk:80;sec:18;hds:2),                               {Requires 1.2 MByte Drive}
  327.                       (fmt:14;trk:80;sec:18;hds:2),                                {Requires 1.2 MByte Drive}
  328.                       (fmt:148;trk:82;sec:18;hds:2),                               {Requires 1.2 MByte Drive}
  329.                       (fmt:16;trk:80;sec:20;hds:2),                                {Requires 1.4 MByte Drive}
  330.                       (fmt:164;trk:82;sec:20;hds:2),                               {Requires 1.4 MByte Drive}
  331.                       (fmt:168;trk:80;sec:21;hds:2),                               {Requires 1.4 MByte Drive}
  332.                       (fmt:172;trk:82;sec:21;hds:2));                              {Requires 1.4 MByte Drive}
  333.  
  334.   GetPhys: ARRAY[0..14] OF Byte =(
  335.  
  336.     $1E,                                                                             {  PUSH DS             }
  337.     $B8,$40,$00,                                                                     {  MOV  AX,40H         }
  338.     $8E,$D8,                                                                         {  MOV  DS,AX          }
  339.     $88,$16,$41,$00,                                                                 {  MOV  [41H],DL       }
  340.     $1F,                                                                             {  POP  DS             }
  341.     $B8,$01,$01,                                                                     {  MOV  AX,101H        }
  342.     $CF);                                                                            {  IRET                }
  343.  
  344.   Help58: ARRAY[0..3] OF Byte =(
  345.  
  346.     $CD,$25,                                                                         {  INT  25H            }
  347.     $59,                                                                             {  POP  CX             }
  348.     $CF);                                                                            {  IRET                }
  349.  
  350.   boot: boottyp=(
  351.  
  352.     {$IFDEF L49}
  353.  
  354.     $00,$00,
  355.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  356.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  357.     $00,$00,$8C,$C8,$3D,$00,$7C,$74,$08,$BE,$82,$02,$E8,$6A,$00,$CD,
  358.     $20,$FA,$33,$C0,$8E,$D0,$BC,$00,$7C,$B8,$B0,$07,$50,$50,$1F,$07,
  359.     $BE,$00,$01,$BF,$00,$03,$B9,$00,$01,$F3,$A5,$B8,$D0,$07,$50,$50,
  360.     $50,$1F,$07,$B8,$78,$01,$50,$CB,$FB,$BE,$C9,$01,$E8,$3A,$00,$B8,
  361.     $01,$02,$B9,$01,$00,$BA,$80,$00,$33,$DB,$53,$07,$BB,$00,$7C,$06,
  362.     $53,$CD,$13,$72,$0A,$26,$81,$3E,$FE,$7D,$55,$AA,$75,$01,$CB,$BE,
  363.     $0F,$02,$E8,$14,$00,$B4,$01,$CD,$16,$74,$06,$32,$E4,$CD,$16,$EB,
  364.     $F4,$32,$E4,$CD,$16,$33,$D2,$CD,$19,$8A,$04,$0A,$C0,$75,$01,$C3,
  365.     $56,$B4,$0E,$CD,$10,$5E,$46,$EB,$F0,$46,$44,$46,$4F,$52,$4D,$41,
  366.     $54,$20,$56,$65,$72,$73,$69,$6F,$6E,$20,$31,$2E,$36,$0A,$0D,$4B,
  367.     $65,$69,$6E,$65,$20,$53,$79,$73,$74,$65,$6D,$64,$69,$73,$6B,$65,
  368.     $74,$74,$65,$2E,$20,$53,$74,$61,$72,$74,$65,$6E,$20,$76,$6F,$6E,
  369.     $20,$46,$65,$73,$74,$70,$6C,$61,$74,$74,$65,$2E,$0A,$0D,$00,$4B,
  370.     $61,$6E,$6E,$20,$6E,$69,$63,$68,$74,$20,$76,$6F,$6E,$20,$64,$65,
  371.     $72,$20,$46,$65,$73,$74,$70,$6C,$61,$74,$74,$65,$20,$73,$74,$61,
  372.     $72,$74,$65,$6E,$2E,$0A,$0D,$53,$79,$73,$74,$65,$6D,$2D,$44,$69,
  373.     $73,$6B,$65,$74,$74,$65,$20,$69,$6E,$20,$4C,$61,$75,$66,$77,$65,
  374.     $72,$6B,$20,$41,$3A,$20,$65,$69,$6E,$6C,$65,$67,$65,$6E,$0A,$0D,
  375.     $41,$6E,$73,$63,$68,$6C,$69,$65,$E1,$65,$6E,$64,$20,$65,$69,$6E,
  376.     $65,$20,$54,$61,$73,$74,$65,$20,$64,$72,$81,$63,$6B,$65,$6E,$0A,
  377.     $0D,$00,$44,$69,$65,$73,$65,$20,$44,$61,$74,$65,$69,$20,$6E,$69,
  378.     $63,$68,$74,$20,$61,$75,$73,$66,$81,$68,$72,$65,$6E,$2E,$07,$0A,
  379.     $0D,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  380.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  381.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  382.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  383.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  384.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55,$AA);
  385.  
  386.   {$ENDIF}
  387.     {$IFDEF L1}
  388.  
  389. $00,$00,
  390. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  391. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  392. $00,$00,$8C,$C8,$3D,$00,$7C,$74,$08,$BE,$4A,$02,$E8,$6A,$00,$CD,
  393. $20,$FA,$33,$C0,$8E,$D0,$BC,$00,$7C,$B8,$B0,$07,$50,$50,$1F,$07,
  394. $BE,$00,$01,$BF,$00,$03,$B9,$00,$01,$F3,$A5,$B8,$D0,$07,$50,$50,
  395. $50,$1F,$07,$B8,$78,$01,$50,$CB,$FB,$BE,$C9,$01,$E8,$3A,$00,$B8,
  396. $01,$02,$B9,$01,$00,$BA,$80,$00,$33,$DB,$53,$07,$BB,$00,$7C,$06,
  397. $53,$CD,$13,$72,$0A,$26,$81,$3E,$FE,$7D,$55,$AA,$75,$01,$CB,$BE,
  398. $07,$02,$E8,$14,$00,$B4,$01,$CD,$16,$74,$06,$32,$E4,$CD,$16,$EB,
  399. $F4,$32,$E4,$CD,$16,$33,$D2,$CD,$19,$8A,$04,$0A,$C0,$75,$01,$C3,
  400. $56,$B4,$0E,$CD,$10,$5E,$46,$EB,$F0,$46,$44,$46,$4F,$52,$4D,$41,
  401. $54,$20,$56,$65,$72,$73,$69,$6F,$6E,$20,$31,$2E,$36,$0A,$0D,$4E,
  402. $6F,$20,$53,$79,$73,$74,$65,$6D,$64,$69,$73,$6B,$2E,$20,$42,$6F,
  403. $6F,$74,$69,$6E,$67,$20,$66,$72,$6F,$6D,$20,$68,$61,$72,$64,$64,
  404. $69,$73,$6B,$2E,$0A,$0D,$00,$43,$61,$6E,$6E,$6F,$74,$20,$6C,$6F,
  405. $61,$64,$20,$66,$72,$6F,$6D,$20,$68,$61,$72,$64,$64,$69,$73,$6B,
  406. $2E,$0A,$0D,$49,$6E,$73,$65,$72,$74,$20,$53,$79,$73,$74,$65,$6D,
  407. $64,$69,$73,$6B,$20,$61,$6E,$64,$20,$70,$72,$65,$73,$73,$20,$61,
  408. $6E,$79,$20,$6B,$65,$79,$2E,$0A,$0D,$00,$44,$6F,$20,$6E,$6F,$74,
  409. $20,$65,$78,$65,$63,$75,$74,$65,$20,$74,$68,$69,$73,$20,$43,$4F,
  410. $4D,$2D,$46,$69,$6C,$65,$2E,$0A,$0D,$00,$00,$00,$00,$00,$00,$00,
  411. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  412. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  413. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  414. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  415. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  416. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  417. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  418. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  419. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$55,$AA);
  420.  
  421.  
  422.   {$ENDIF}
  423.  
  424.     FUNCTION ReadKey:Char;
  425.       VAR r:registers;
  426.     BEGIN
  427.       GiveUpIdle;
  428.       WITH r DO BEGIN
  429.         ah:=7;
  430.         intr($21,r);
  431.         IF al IN [3,27] THEN BEGIN
  432.           WriteLn;
  433.           Halt(4);
  434.         END;
  435.         ReadKey:=Chr(al);
  436.       END;
  437.     END;
  438.  
  439.     PROCEDURE ConfigError;
  440.     BEGIN
  441.       WriteLn;
  442.       WriteLn(text76);
  443.       Halt(16);
  444.     END;
  445.  
  446.     PROCEDURE GetValue(x,y:String;VAR Value:Byte);
  447.       VAR i,k: Byte;
  448.       j:   Integer;
  449.     BEGIN
  450.       y:=' '+y+'=';
  451.       i:=pos(y,x);
  452.       IF i<>0 THEN BEGIN
  453.         i:=i+Length(y);
  454.         WHILE x[i]=' ' DO Inc(i);
  455.         IF i>Length(x) THEN ConfigError;
  456.         k:=i;
  457.         WHILE x[k]<>' ' DO Inc(k);
  458.         IF x[i]<>'$' THEN BEGIN
  459.           Val(Copy(x,i,k-i),Value,j);
  460.           IF j<>0 THEN ConfigError;
  461.         END ELSE BEGIN
  462.           Value:=dezh(Copy(x,i+1,k-i-1));
  463.           IF BaseError<>0 THEN ConfigError;
  464.         END;
  465.       END;
  466.     END;
  467.  
  468.     PROCEDURE CfgRead;
  469.       VAR f: Text;
  470.       x: String;
  471.       i: Byte;
  472.     BEGIN
  473.       cfgat80:=False;
  474.       cfgpc80:=False;
  475.       cfgdrive:=255;
  476.       bios:=False;
  477.       pc80:=0;
  478.       pc40:=0;
  479.       v720:=0;
  480.       v360:=0;
  481.       v12:=0;
  482.       v144:=0;
  483.       x:=FSearch('FDFORMAT.CFG',GetEnv('PATH'));
  484.       IF x<>'' THEN BEGIN
  485.         Assign(f,x);
  486.         {$I-} Reset(f); {$I+}
  487.         IF IoResult=0 THEN BEGIN
  488.           WHILE NOT eof(f) DO BEGIN
  489.             ReadLn(f,x);
  490.             x:=x+' ';
  491.             FOR i:=1 TO Length(x) DO x[i]:=Upcase(x[i]);
  492.             IF Copy(x,1,2)=para[1] THEN BEGIN
  493.               IF pos(' BIOS ',x)<>0 THEN bios:=True;
  494.               IF pos(' AT ',x)<>0 THEN cfgat80:=True;
  495.               GetValue(x,'F',cfgdrive);
  496.               IF NOT(cfgdrive IN [0,1,2,7,255]) THEN ConfigError;
  497.               IF pos(' XT ',x)<>0 THEN cfgpc80:=True;
  498.               GetValue(x,'40',pc40);
  499.               GetValue(x,'80',pc80);
  500.               GetValue(x,'360',v360);
  501.               GetValue(x,'720',v720);
  502.               GetValue(x,'1.2',v12);
  503.               GetValue(x,'1.44',v144);
  504.               GetValue(x,'X',shifth);
  505.               GetValue(x,'Y',shiftt);
  506.             END;
  507.             IF cfgat80 AND cfgpc80 THEN ConfigError;
  508.           END;
  509.           {$I-} Close(f); {$I+}
  510.         END ELSE BEGIN
  511.           WriteLn;
  512.           WriteLn(text77);
  513.           Halt(8);
  514.         END;
  515.       END;
  516.     END;
  517.  
  518.     PROCEDURE int13error;
  519.     BEGIN
  520.       WriteLn;
  521.       CASE regs.ah OF
  522.         $01: Write(error01);
  523.         $02: Write(error02);
  524.         $03: Write(error03);
  525.         $04: Write(error04);
  526.         $06: Write(error06);
  527.         $08: Write(error08);
  528.         $09: Write(error09);
  529.         $0c: Write(error0c);
  530.         $10: Write(error10);
  531.         $20: Write(error20);
  532.         $40: Write(error40);
  533.         $80: Write(error80);
  534.         ELSE Write(errorxx);
  535.       END;
  536.       WriteLn('.');
  537.     END;
  538.  
  539.     PROCEDURE int13;
  540.       VAR axs: Word;
  541.       chx: Char;
  542.       er:  Boolean;
  543.     BEGIN
  544.       again:=False;
  545.       WITH regs DO BEGIN
  546.         axs:=ax;
  547.         REPEAT
  548.           GiveUpCPU;
  549.           ax:=axs;
  550.           IF ah IN [2,3,5] THEN SetIntVec($1E,new1E);
  551.           IF trk>43 THEN dl:=dl OR pc80 ELSE dl:=dl OR pc40;
  552.           IF NOT(bios) THEN lwtab[dl]:=DiskId;
  553.           intr($13,regs);
  554.           SetIntVec($1E,old1E);
  555.           GiveUpCPU;
  556.           er:=ah>1;
  557.         UNTIL ah<>6;
  558.         IF er THEN BEGIN
  559.           WriteLn;
  560.           WriteLn(text01,regs.ah,'  ',text14,dh,text15,ch,text78,cl,'-',cl+Lo(axs)-1);
  561.           int13error;
  562.           WriteLn(text02);
  563.           REPEAT
  564.             chx:=Upcase(ReadKey);
  565.             CASE chx OF
  566.               'A': Halt(4);
  567.               'I': er:=False;
  568.               t3 : BEGIN er:=False; again:=True; END;
  569.             END;
  570.           UNTIL chx IN ['A','I',t3];
  571.         END;
  572.         ax:=axs;
  573.       END;
  574.     END;
  575.  
  576.     PROCEDURE parse;
  577.       VAR j:    Byte;
  578.       argstr: String[80];
  579.     BEGIN
  580.       argstr:='';
  581.       FOR j:=1 TO 50 DO para[j]:='';
  582.       FOR j:=1 TO ParamCount DO argstr:=argstr+' '+ParamStr(j);
  583.       FOR j:=1 TO Length(argstr) DO argstr[j]:=Upcase(argstr[j]);
  584.       PCount:=0;
  585.       FOR j:=1 TO Length(argstr) DO BEGIN
  586.         CASE argstr[j] OF
  587.           ' ','-','/': Inc(PCount);
  588.           ELSE         IF (NOT(argstr[j] IN [':','.'])) OR (PCount=1) THEN
  589.               para[PCount]:=para[PCount]+argstr[j];
  590.         END;
  591.       END;
  592.     END;
  593.  
  594.  
  595.     PROCEDURE GetPhysical(VAR lw:Byte);
  596.     BEGIN
  597.       WITH regs DO BEGIN
  598.         GetIntVec($58,old58);
  599.         GetIntVec($13,old13);
  600.         SetIntVec($58,@Help58);
  601.         SetIntVec($13,@GetPhys);
  602.         al:=lw; cx:=1; dx:=0;
  603.         ds:=Seg(buffer); bx:=Ofs(buffer);
  604.         intr($58,regs);
  605.         SetIntVec($58,old58);
  606.         SetIntVec($13,old13);
  607.         lw:=Mem[$40:$41];
  608.       END;
  609.     END;
  610.  
  611.     PROCEDURE DriveTyp(VAR lw:Byte;VAR hd:Boolean;VAR trk,sec:Byte);
  612.     BEGIN
  613.       WITH regs DO BEGIN
  614.         ax:=$4409; bx:=lw+1;
  615.         intr($21,regs);
  616.         IF (FCarry AND Flags) <> 0 THEN BEGIN
  617.           WriteLn(text04);
  618.           trk:=0;
  619.           Exit;
  620.         END;
  621.         IF (dx AND $9200)<>0 THEN BEGIN
  622.           WriteLn(text05);
  623.           trk:=0;
  624.           Exit;
  625.         END;
  626.         ax:=$440f; bx:=lw+1;
  627.         intr($21,regs);
  628.         IF (FCarry AND Flags)<>0 THEN BEGIN
  629.           WriteLn(text04);
  630.           trk:=0;
  631.           Exit;
  632.         END;
  633.         ax:=$440d; cx:=$860; bl:=lw+1;
  634.         bh:=0; dx:=Ofs(buffer); ds:=Seg(buffer);
  635.         buffer[0]:=0;
  636.         intr($21,regs);
  637.         dosdrive:=buffer[1];
  638.         IF cfgdrive<>255 THEN
  639.           dosdrive:=cfgdrive;
  640.         CASE dosdrive OF
  641.           0: BEGIN trk:=39; sec:= 9; hd:=False; END;
  642.           1: BEGIN trk:=79; sec:=15; hd:=True ; END;
  643.           2: BEGIN trk:=79; sec:= 9; hd:=False; END;
  644.           7: BEGIN trk:=79; sec:=18; hd:=True ; END;
  645.           ELSE
  646.             BEGIN
  647.               WriteLn(text06);
  648.               trk:=0;
  649.               Exit;
  650.             END
  651.         END;
  652.         GetPhysical(lw);
  653.         lw:=lw AND $9f;
  654.         IF NOT(lw IN [0..3]) THEN BEGIN
  655.           WriteLn(text07);
  656.           trk:=0;
  657.           Exit;
  658.         END;
  659.         IF cfgat80 THEN
  660.           at80:=cfgat80
  661.         ELSE
  662.           at80:=(ModelByte=$f8) OR (ModelByte=$fc);
  663.       END;
  664.     END;
  665.  
  666.     PROCEDURE ATSetDrive(lw:Byte; trk,sec,Disk2,Disk,SetUp:Byte);
  667.     BEGIN
  668.       WITH regs DO BEGIN
  669.         dh:=lw; ah:=$18; ch:=trk; cl:=sec;
  670.         intr($13,regs);
  671.         IF ah>1 THEN BEGIN
  672.           ah:=$17; al:=SetUp; dl:=lw;
  673.           intr($13,regs);
  674.         END;
  675.         IF ForceType<>0 THEN BEGIN
  676.           lwtab[lw]:=ForceType;
  677.           bios:=False;
  678.         END ELSE IF Disk2<>0 THEN BEGIN
  679.           bios:=False;
  680.           lwtab[lw]:=Disk2;
  681.         END ELSE
  682.           IF NOT(bios) THEN lwtab[lw]:=Disk;
  683.         DiskId:=lwtab[lw];
  684.       END;
  685.     END;
  686.  
  687.     PROCEDURE SectorAbsolute(sector:Word;VAR hds,trk,sec:Byte);
  688.       VAR h:Word;
  689.     BEGIN
  690.       sec:=(sector MOD bpb.spt)+1;
  691.       h:=sector DIV bpb.spt;
  692.       trk:=h DIV bpb.hds;
  693.       hds:=h MOD bpb.hds;
  694.     END;
  695.  
  696.     FUNCTION SectorLogical(hds,trk,sec:Byte):Word;
  697.     BEGIN
  698.       SectorLogical:=trk*bpb.hds*bpb.spt+hds*bpb.spt+sec-1;
  699.     END;
  700.  
  701.     FUNCTION Cluster(sector: Word):Word;
  702.     BEGIN
  703.       Cluster:=((sector-(bpb.rde SHR 4)
  704.                  -(bpb.spf SHL 1)-1)
  705.                 DIV Word(bpb.spc))+2;
  706.     END;
  707.  
  708.     PROCEDURE ClusterOffset(Cluster:Word; VAR Offset,Mask:Word);
  709.     BEGIN
  710.       Offset:=Cluster*3 SHR 1;
  711.       IF Cluster AND 1 = 0 THEN
  712.         Mask:=$ff7
  713.       ELSE
  714.         Mask:=$ff70;
  715.     END;
  716.  
  717.     PROCEDURE GetOldParms;
  718.     BEGIN
  719.       WITH regs DO BEGIN
  720.         ax:=$201;
  721.         dx:=lw;
  722.         cx:=1;
  723.         es:=Seg(bpb);
  724.         bx:=Ofs(bpb);
  725.         REPEAT int13 UNTIL NOT again;
  726.         IF ((FCarry AND Flags) = 0) AND (bpb.hds<>0) AND (bpb.spt<>0)
  727.         AND (bpb.sec MOD (bpb.hds*bpb.spt)=0) THEN BEGIN
  728.           sec:=bpb.spt;
  729.           hds:=bpb.hds;
  730.           trk:=bpb.sec DIV bpb.hds DIV bpb.spt;
  731.         END ELSE BEGIN
  732.           WriteLn(text79);
  733.           Halt(4);
  734.         END;
  735.       END;
  736.     END;
  737.  
  738.     PROCEDURE format;
  739.       VAR i:Byte;
  740.     BEGIN
  741.       IF rde AND 15 <> 0 THEN Inc(rde,16);
  742.       rde:=rde SHR 4;
  743.       IF (spc=2) AND (rde AND 1 = 0) THEN Inc(rde);
  744.       bpb.rde:=rde SHL 4;
  745.       CASE sec OF
  746.         0..8:   new1E:=@para08;
  747.         9:      new1E:=@para09;
  748.         10:     new1E:=@para10;
  749.         11:     new1E:=@para11;
  750.         12..15: new1E:=@para15;
  751.         17:     new1E:=@para17;
  752.         18:     IF lwsec>17 THEN
  753.                   new1E:=@para18
  754.                 ELSE
  755.                   new1E:=@para18a;
  756.         19..20: new1E:=@para20;
  757.         21:     new1E:=@para21;
  758.         22..255:new1E:=@para22;
  759.       END;
  760.       IF gpl<>0 THEN
  761.         new1E^[7]:=gpl
  762.       ELSE
  763.         gpl:=new1E^[7];
  764.       WriteLn;
  765.       Write(text08,Chr(lw+$41),': ');
  766.       IF hd THEN WriteLn('High-Density') ELSE WriteLn('Double-Density');
  767.       WriteLn(hds,text09,trk,text10,sec,text11,'Interleave: ',il,text68,gpl);
  768.       WriteLn(bpb.rde,text12,spc,text13,shiftt,':',shifth);
  769.       bttCount:=0;
  770.       WITH regs DO BEGIN
  771.         FOR i:=1 TO 25 DO BEGIN
  772.           table[i].f:=2;
  773.           table2[i]:=0;
  774.         END;
  775.         i:=1;
  776.         n:=1;
  777.         REPEAT
  778.           REPEAT
  779.             WHILE table2[n]<>0 DO Inc(n);
  780.             IF n>sec THEN n:=1;
  781.           UNTIL table2[n]=0;
  782.           table2[n]:=i;
  783.           n:=n+il;
  784.           Inc(i);
  785.         UNTIL i>sec;
  786.         ax:=0;
  787.         bx:=0;
  788.         dl:=lw;
  789.         IF at80 THEN BEGIN
  790.           IF (trk>43) AND (sec>11) AND (sec<16) THEN ATSetDrive(lw,79,lwsec,v12,$14,5);
  791.           IF (trk>43) AND (sec>11) AND (sec>15) THEN ATSetDrive(lw,79,lwsec,v144,$14,5);
  792.           IF (dosdrive IN [0,1]) AND (trk>43) AND (sec<12) THEN ATSetDrive(lw,79,9,v720,$53,4);
  793.           IF (dosdrive IN [2,7]) AND (trk>43) AND (sec<12) THEN ATSetDrive(lw,79,9,v720,$97,4);
  794.           IF (trk<44) AND (sec>11) THEN ATSetDrive(lw,39,lwsec,0,$34,3);
  795.           IF (dosdrive IN [2,7]) AND (trk<44) AND (sec<12) THEN ATSetDrive(lw,39,9,v360,$B7,2);
  796.           IF (dosdrive IN [0,1]) AND (trk<44) AND (sec<12) THEN ATSetDrive(lw,39,9,v360,$73,2);
  797.         END;
  798.         IF at80 AND NOT(bios) THEN BEGIN
  799.           Write(text67);
  800.           CASE (DiskId AND $C0) OF
  801.             $00: Write('500');
  802.             $40: Write('300');
  803.             $80: Write('250');
  804.             $C0: Write('???');
  805.           END;
  806.           Write(' kBaud, Double-Stepping: ');
  807.           IF (DiskId AND 32)=0 THEN
  808.             Write(text73,', ')
  809.           ELSE
  810.             Write(text72,', ');
  811.         END;
  812.         bpb.jmp[1]:=$EB;
  813.         bpb.jmp[2]:=$40;
  814.         bpb.jmp[3]:=144;
  815.         bpb.spt:=sec;
  816.         bpb.hds:=hds;
  817.         bpb.shh:=0;
  818.         bpb.bps:=512;
  819.         bpb.spc:=spc;
  820.         bpb.res:=1;
  821.         bpb.fat:=2;
  822.         bpb.sec:=sec*bpb.hds*trk;
  823.         bpb.boot_code:=boot;
  824.         IF ForceMedia=0 THEN BEGIN
  825.           CASE bpb.spc OF
  826.             1:   IF (trk>44) AND (bpb.spt IN [12..17]) THEN
  827.                    bpb.mds:=$f9
  828.                  ELSE
  829.                    bpb.mds:=$f0;
  830.             2:   IF trk IN [1..43] THEN bpb.mds:=$fd ELSE bpb.mds:=$f9;
  831.             ELSE bpb.mds:=$f8;
  832.           END;
  833.         END
  834.         ELSE bpb.mds:=ForceMedia;
  835.         bpb.spf:=Trunc(bpb.sec*1.5/512/bpb.spc)+1;
  836.         WHILE Trunc((1.5*(((bpb.sec-bpb.res-(bpb.rde DIV 16)
  837.                             -bpb.fat*(bpb.spf-1)) DIV bpb.spc)+2)-1)/bpb.bps)+1<bpb.spf DO
  838.           Dec(bpb.spf);
  839.         WriteLn('Media-Byte: ',hexf(bpb.mds,2));
  840.         WriteLn;
  841.         dl:=lw;
  842.         ax:=0;
  843.         REPEAT int13 UNTIL NOT again;
  844.         n:=0;
  845.         FillChar(buffer,SizeOf(buffer),#0);
  846.         FOR track:=trk-1 DOWNTO 0 DO BEGIN
  847.           IF track<>trk-1 THEN n:=n+shiftt;
  848.           FOR head:=hds-1 DOWNTO 0 DO BEGIN
  849.             IF head<>hds-1 THEN n:=n+shifth;
  850.             n:=n MOD sec;
  851.             FOR i:=1 TO sec DO
  852.               table[i].s:=table2[(i+n-1) MOD sec+1];
  853.             Write(text14,head,text15,track);
  854.             x:=SectorLogical(head,track,1);
  855.             x:=Cluster(x);
  856.             FOR i:=1 TO sec DO BEGIN
  857.               table[i].t:=track;
  858.               table[i].h:=head;
  859.             END;
  860.             REPEAT
  861.               IF noformat THEN BEGIN
  862.                 again:=False;
  863.                 Write('  ');
  864.               END ELSE BEGIN
  865.                 ah:=5;
  866.                 al:=sec;
  867.                 dl:=lw;
  868.                 dh:=head;
  869.                 ch:=track;
  870.                 cl:=1;
  871.                 es:=Seg(table);
  872.                 bx:=Ofs(table);
  873.                 Write('  F   '#8#8#8);
  874.                 Mem[$40:$41]:=0;
  875.                 int13;
  876.               END;
  877.               Write(#8,'V                         ');Write(#13);
  878.               IF NOT(again OR noverify) OR (track<3) THEN BEGIN
  879.                 ah:=3;
  880.                 al:=sec;
  881.                 dl:=lw;
  882.                 dh:=head;
  883.                 ch:=track;
  884.                 cl:=1;
  885.                 es:=Seg(buffer);
  886.                 bx:=Ofs(buffer);
  887.                 int13;
  888.               END;
  889.             UNTIL NOT again;
  890.             IF (FCarry AND Flags) <> 0 THEN BEGIN
  891.               IF (x<2) OR (x>10000) THEN BEGIN
  892.                 WriteLn(text17);
  893.                 Halt(2);
  894.               END;
  895.               Inc(bttCount);
  896.               IF bttCount>20 THEN BEGIN
  897.                 WriteLn(text18,20*sec,text19);
  898.                 Halt(2);
  899.               END;
  900.               btt[bttCount].track:=track;
  901.               btt[bttCount].head:=head;
  902.               WriteLn(text14,head,text15,track,text20,#10#13);
  903.             END;
  904.           END;
  905.         END;
  906.       END;
  907.     END;
  908.  
  909.     PROCEDURE WriteBootSect;
  910.     BEGIN
  911.       WITH regs DO BEGIN
  912.         WriteLn; bpb.oem:='CH-FOR16'; WriteLn;
  913.         WriteLn(text21,bpb.oem); WriteLn(text22,bpb.sec);
  914.         WriteLn(text23,bpb.spt); WriteLn(text24,bpb.hds);
  915.         WriteLn(text25,bpb.bps); WriteLn(text26,bpb.shh);
  916.         WriteLn(text27,bpb.res); WriteLn(text28,bpb.fat);
  917.         WriteLn(text29,bpb.spf); WriteLn(text30,Cluster(bpb.sec)-2);
  918.         dh:=0; dl:=lw; ch:=0; cl:=1;
  919.         al:=1; ah:=3; es:=Seg(bpb);
  920.         bx:=Ofs(bpb);
  921.         REPEAT int13 UNTIL NOT again;
  922.         FillChar(buffer[3],18430,#0);
  923.         buffer[0]:=bpb.mds;
  924.         buffer[1]:=$ff;
  925.         buffer[2]:=$ff;
  926.         bad:=0;
  927.         FOR i:=1 TO bttCount DO
  928.           FOR j:=1 TO sec DO BEGIN
  929.             x:=SectorLogical(btt[i].head,btt[i].track,j);
  930.             x:=Cluster(x);
  931.             ClusterOffset(x,Offset,Mask);
  932.             IF buffer[Offset] AND Lo(Mask)=0 THEN Inc(bad,bpb.spc*512);
  933.             buffer[Offset]:=buffer[Offset] OR Lo(Mask);
  934.             buffer[Offset+1]:=buffer[Offset+1] OR Hi(Mask);
  935.           END;
  936.         es:=Seg(buffer);
  937.         bx:=Ofs(buffer);
  938.         Inc(cl);
  939.         al:=bpb.spf;
  940.         REPEAT int13 UNTIL NOT again;
  941.         SectorAbsolute(bpb.spf+1,dh,ch,cl);
  942.         ah:=3;
  943.         dl:=lw;
  944.         IF bpb.spf+cl>sec+1 THEN al:=sec-cl+1;
  945.         REPEAT int13 UNTIL NOT again;
  946.         IF bpb.spf+cl>sec+1 THEN BEGIN
  947.           bx:=bx+al*512;
  948.           al:=bpb.spf-al;
  949.           Inc(dh);
  950.           cl:=1;
  951.           REPEAT int13 UNTIL NOT again;
  952.         END;
  953.         bytes:=LongInt(Cluster(bpb.sec)-2)*512*LongInt(bpb.spc);
  954.         WriteLn;
  955.         WriteLn(bytes:9,text31);
  956.         IF bad<>0 THEN WriteLn(bad:9,text32);
  957.         WriteLn(bytes-bad:9,text33);
  958.         WriteLn;
  959.         IF NOT(bios) THEN lwtab[lw]:=0;
  960.         dl:=lw;
  961.         ah:=0;
  962.         REPEAT int13 UNTIL NOT again;
  963.         ax:=$440f; bx:=lw+1;
  964.         intr($21,regs);
  965.       END;
  966.     END;
  967.  
  968.     PROCEDURE WriteSys;
  969.       VAR comspec: String[40];
  970.     BEGIN
  971.       comspec:=GetEnv('COMSPEC');
  972.       exec(comspec,'/C SYS '+Chr(lw+$41)+':');
  973.       exec(comspec,'/C COPY '+comspec+' '+Chr(lw+$41)+':\ >NUL');
  974.     END;
  975.  
  976.     PROCEDURE WriteLabel(x:String);
  977.       VAR i: Byte;
  978.     BEGIN
  979.       WITH regs DO BEGIN
  980.         IF x='' THEN BEGIN
  981.           REPEAT
  982.             Write(text74);
  983.             ReadLn(x);
  984.           UNTIL Length(x)<12;
  985.         END;
  986.         IF x<>'' THEN BEGIN
  987.           IF Length(x)>8 THEN Insert('.',x,9);
  988.           x:=Chr(lw+$41)+':\'+x;
  989.           x[Length(x)+1]:=#0;
  990.           cx:=8;
  991.           ds:=Seg(x);
  992.           dx:=Ofs(x)+1;
  993.           ah:=$3c;
  994.           msdos(regs);
  995.           IF (FCarry AND Flags) <> 0 THEN BEGIN
  996.             WriteLn(text75);
  997.             Exit;
  998.           END;
  999.           bx:=ax;
  1000.           ah:=$3e;
  1001.           msdos(regs);
  1002.           IF (FCarry AND Flags) <> 0 THEN BEGIN
  1003.             WriteLn(text75);
  1004.             Halt(32);
  1005.           END;
  1006.         END;
  1007.       END;
  1008.     END;
  1009.  
  1010.     PROCEDURE DrivePrt;
  1011.     BEGIN
  1012.       WriteLn;
  1013.       IF lwtrk=0 THEN BEGIN
  1014.         WriteLn(text34);
  1015.         Exit;
  1016.       END;
  1017.       Write(text35,Chr(lw+$41));
  1018.       IF lwhd THEN
  1019.         Write(': High-Density, ')
  1020.       ELSE
  1021.         Write(': Double-Density, ');
  1022.       WriteLn(lwtrk+1,text10,lwsec,text11);
  1023.       Write(text36);
  1024.       IF pc80=$20 THEN WriteLn(text37);
  1025.       IF pc80=$40 THEN WriteLn(text38);
  1026.       IF at80 THEN WriteLn(text39);
  1027.       IF NOT(at80) AND (pc80=0) THEN WriteLn(text40);
  1028.       WriteLn;
  1029.     END;
  1030.  
  1031.     PROCEDURE SyntaxError;
  1032.     BEGIN
  1033.       WriteLn; WriteLn(text41); WriteLn;
  1034.       WriteLn(text42); WriteLn(text43); WriteLn;
  1035.       WriteLn(text44); WriteLn; WriteLn(text45);
  1036.       WriteLn(text46); WriteLn(text47); WriteLn(text48);
  1037.       WriteLn(text49); WriteLn(text50); WriteLn(text51);
  1038.       WriteLn(text52); WriteLn(text53);
  1039.       WriteLn(text69); WriteLn(text70); WriteLn;
  1040.       WriteLn(text71);
  1041.       Halt(1);
  1042.     END;
  1043.  
  1044.     PROCEDURE CheckDos;
  1045.       VAR Version: Word;
  1046.     BEGIN
  1047.       Version:=Swap(DosVersion);
  1048.       IF Version<$314 THEN BEGIN
  1049.         WriteLn(text54);
  1050.         Halt(128);
  1051.       END;
  1052.     END;
  1053.  
  1054.     BEGIN
  1055.       WriteLn;
  1056.       WriteLn(text55);
  1057.       WriteLn(text56);
  1058.       CheckDos;
  1059.       GetIntVec($1E,old1E);
  1060.       new1E:=old1E;
  1061.       parse;
  1062.       noverify:=False;
  1063.       noformat:=False;
  1064.       IF (Length(para[1])<>2) OR (para[1,2]<>':') THEN SyntaxError;
  1065.       lw:=Ord(Upcase(para[1,1]))-$41;
  1066.       shiftt:=0;
  1067.       shifth:=0;
  1068.       CfgRead;
  1069.       DriveTyp(lw,lwhd,lwtrk,lwsec);
  1070.       DrivePrt;
  1071.       IF (lwtrk=0) AND (para[1]<>'') THEN Halt(1);
  1072.       rde:=0;
  1073.       il:=0;
  1074.       spc:=0;
  1075.       gpl:=0;
  1076.       setlabel:=False;
  1077.       sys:=False;
  1078.       ForceType:=0;
  1079.       ForceMedia:=0;
  1080.       batch:=False;
  1081.       trk:=lwtrk+1;
  1082.       sec:=lwsec;
  1083.       hds:=2;
  1084.       FOR i:=2 TO PCount DO
  1085.         IF para[i]<>'' THEN BEGIN
  1086.           chx:=para[i,1];
  1087.           IF Upcase(chx)='V' THEN BEGIN
  1088.             dlabel:='';
  1089.             setlabel:=True;
  1090.             dlabel:=Copy(para[i],2,11);
  1091.           END ELSE
  1092.             IF Length(para[i])=1 THEN BEGIN
  1093.               CASE Upcase(chx) OF
  1094.                 'P': BEGIN END;
  1095.                 'R': noverify:=True;
  1096.                 'A': noformat:=True;
  1097.                 'O': BEGIN
  1098.                        trk:=80;
  1099.                        sec:=9;
  1100.                        rde:=144;
  1101.                      END;
  1102.                 '4': BEGIN
  1103.                        trk:=40;
  1104.                        sec:=9;
  1105.                      END;
  1106.                 '1': BEGIN
  1107.                        hds:=1;
  1108.                      END;
  1109.                 '8': BEGIN
  1110.                        sec:=8;
  1111.                      END;
  1112.                 'S': BEGIN
  1113.                        sys:=True;
  1114.                      END;
  1115.                 'K': BEGIN
  1116.                        batch:=True;
  1117.                      END;
  1118.                 ELSE SyntaxError;
  1119.               END;
  1120.             END ELSE BEGIN
  1121.               IF para[i,2]='$' THEN BEGIN
  1122.                 n:=dezh(Copy(para[i],3,255));
  1123.                 j:=BaseError
  1124.               END ELSE
  1125.                 Val(Copy(para[i],2,255),n,j);
  1126.               IF j<>0 THEN SyntaxError;
  1127.               CASE Upcase(para[i,1]) OF
  1128.                 'T':trk:=n;
  1129.                 'H':hds:=n;
  1130.                 'N':sec:=n;
  1131.                 'S':sec:=n;
  1132.                 'M':ForceMedia:=n;
  1133.                 'D':rde:=n;
  1134.                 'C':spc:=n;
  1135.                 'I':il:=n;
  1136.                 'G':gpl:=n;
  1137.                 'X':shifth:=n;
  1138.                 'Y':shiftt:=n;
  1139.                 'B':ForceType:=n;
  1140.                 'F':BEGIN
  1141.                       found:=False;
  1142.                       FOR j:=1 TO maxform DO
  1143.                         IF NOT(found) AND (n=ftab[j].fmt) THEN BEGIN
  1144.                           trk:=ftab[j].trk;
  1145.                           sec:=ftab[j].sec;
  1146.                           hds:=ftab[j].hds;
  1147.                           found:=True;
  1148.                         END;
  1149.                       IF NOT(found) THEN SyntaxError;
  1150.                     END;
  1151.                 ELSE SyntaxError;
  1152.               END;
  1153.             END;
  1154.         END;
  1155.       IF noformat THEN GetOldParms;
  1156.       IF sec>11 THEN hd:=True ELSE hd:=False;
  1157.       IF rde=0 THEN
  1158.         CASE hd OF
  1159.           True:  rde:=224;
  1160.           False: rde:=112;
  1161.         END;
  1162.       IF spc=0 THEN
  1163.         CASE hd OF
  1164.           True:  spc:=1;
  1165.           False: spc:=2;
  1166.         END;
  1167.       IF il=0 THEN
  1168.         IF sec-lwsec IN [3..8] THEN il:=2 ELSE il:=1;
  1169.       IF NOT(hds IN [1..2]) THEN BEGIN
  1170.         WriteLn(text57);
  1171.         Halt(1);
  1172.       END;
  1173.       IF trk<1 THEN BEGIN
  1174.         WriteLn(text58);
  1175.         Halt(1);
  1176.       END;
  1177.       IF il>=Pred(sec) THEN BEGIN
  1178.         WriteLn(text59,Pred(sec),text60);
  1179.         Halt(1);
  1180.       END;
  1181.       IF NOT(spc IN [1..2]) THEN
  1182.         WriteLn(text61);
  1183.       IF ShortInt(trk-lwtrk)>4 THEN
  1184.         WriteLn(text62);
  1185.       IF rde>240 THEN
  1186.         WriteLn(text63);
  1187.       IF NOT(batch) THEN BEGIN
  1188.         WriteLn;
  1189.         WriteLn(text64,Chr(lw+$41),text65);
  1190.         WriteLn(text66);
  1191.         chx:=ReadKey;
  1192.       END;
  1193.       format;
  1194.       WriteBootSect;
  1195.       IF sys THEN WriteSys;
  1196.       IF setlabel THEN WriteLabel(dlabel);
  1197.     END.
  1198.