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