home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / disk / fdformat / fdformat.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1991-06-26  |  41.6 KB  |  1,168 lines

  1. (*------------------------------------------------------------*)
  2. (*                        FDFORMAT.PAS                        *)
  3. (*     Copyright (c) 1988, Christoph H. Hochstätter           *)
  4. (*               Compiled in Turbo-Pascal 5.5                 *)
  5. (*          Should Compile in Turbo-Pascal 5.0 also           *)
  6. (*                Last Update: 03-Sept-1989                   *)
  7. (*------------------------------------------------------------*)
  8.  
  9. {$A+,B-,D+,E+,F-,I-,L+,N-,O-,R-,S-,V-,M 8192,0,0}
  10. PROGRAM FDFormat;
  11.  
  12. USES Dos, BaseConv;
  13.  
  14. {$DEFINE German}           {Change this to German or English}
  15. CONST
  16. {$IFDEF German}
  17.   Text01  = 'Fehler ';
  18.   Text02  = '(A)bbrechen (W)iederholen (I)gnorieren ? ';
  19.   T3      = 'W';
  20.   Text04  = 'Kein gültiges Laufwerk.';
  21.   Text05  = 'SUBST/ASSIGN/Netzwerk-Laufwerk.';
  22.   Text06  = 'Kein Floppy-Laufwerk.';
  23.   Text07  = 'Völlig unbekannte Laufwerksart';
  24.   Text08  = 'Ich formatiere Laufwerk ';
  25.   Text09  = ' Seite(n), ';
  26.   Text10  = ' Spuren, ';
  27.   Text11  = ' Sektoren/Spur, ';
  28.   Text12  = ' Basisverzeichniseinträge, ';
  29.   Text13  = ' Sektor(en)/Cluster, Sektoren-Versatz: ';
  30.   Text14  = 'Kopf: ';
  31.   Text15  = ', Zylinder: ';
  32.   Text17  = 'Formatierfehler im Systembereich: Programm abgebrochen.';
  33.   Text18  = 'Mehr als ';
  34.   Text19  = ' Sektoren nicht lesbar. Programm abgebrochen.';
  35.   Text20  = ' als schlecht markiert';
  36.   Text21  = 'Format-Identifizierung:          ';
  37.   Text22  = 'Gesamtsektoren auf der Diskette: ';
  38.   Text23  = 'Sektoren pro Spur:               ';
  39.   Text24  = 'Schreib-/Leseköpfe:              ';
  40.   Text25  = 'Bytes pro Sektor:                ';
  41.   Text26  = 'Versteckte Sektoren:             ';
  42.   Text27  = 'Boot-Sektoren:                   ';
  43.   Text28  = 'Anzahl der FAT''s:                ';
  44.   Text29  = 'Sektoren pro FAT:                ';
  45.   Text30  = 'Cluster auf Diskette:            ';
  46.   Text31  = ' Bytes Gesamtkapazität';
  47.   Text32  = ' Bytes in schlechten Sektoren';
  48.   Text33  = ' Bytes auf der Diskette verfügbar';
  49.   Text34  = 'Dieses Laufwerk kann nicht formatiert werden.';
  50.   Text35  = 'Laufwerk ist physisch ';
  51.   Text36  = 'BIOS Umschaltung 40/80 Spuren: ';
  52.   Text37  = 'nach XT-Standard';
  53.   Text38  = 'nach EPSON QX-16 Standard';
  54.   Text39  = 'nach AT-Standard';
  55.   Text40  = 'wird nicht unterstützt';
  56.   Text41  = 'Syntax Error beim Aufruf.';
  57.   Text42  = 'Format ist: FDFORMAT drive: [Optionen]';
  58.   Text43  = '  Beispiel: FDFORMAT a: t41 h2 s10 C1 D112';
  59.   Text44  = 'Parameter Bedeutung                              Voreinstellung';
  60.   Text45  = 'drive:    Laufwerk, das formatiert werden soll   ----';
  61.   Text46  = 'Tnn       Anzahl der Spuren je Seite             40/80 je nach Laufwerk';
  62.   Text47  = 'Hnn       Anzahl der Seiten                      2';
  63.   Text48  = 'Nnn       Anzahl der Sektoren je Spur            9/15/18 je nach Laufwerk';
  64.   Text49  = 'Cn        Anzahl der Sektoren je Cluster         1 bei HD, 2 bei DD';
  65.   Text50  = 'Dnnn      Anzahl der Basisverzeichniseinträge    224 bei HD, 112 bei DD';
  66.   Text51  = 'Inn       Interleave-Faktor                      1';
  67.   Text52  = 'Fnnn      Format festlegen';
  68.   Text53  = 'R         Formatierung nicht verifizieren';
  69.   Text69  = 'Bnnn      Diskettentypbyte festlegen             je nach Format';
  70.   Text70  = 'Gnnn      GAP-Länge festlegen                    je nach Format';
  71.   Text71  = 'Lesen Sie die READ.ME Datei für weitere Optionen';
  72.   Text54  = 'Dieses Programm benötigt mindestens DOS 3.20.';
  73.   Text55  = 'FDFORMAT -- Formatieren von Disketten mit erhöhter Kapazität';
  74.   Text56  = 'Copyright (c) 03.09.1989, Christoph H. Hochstätter, Ver 1.50';
  75.   Text57  = 'Sie können nur 1 oder 2 Seiten nehmen.';
  76.   Text58  = 'Sie sollten schon mindestens eine Spur formatieren.';
  77.   Text59  = 'Interleave muß von 1-';
  78.   Text60  = ' sein.';
  79.   Text61  = 'WARNUNG! DOS verwaltet bei Disketten nur 1 oder 2 Sektoren/Cluster';
  80.   Text62  = 'WARNUNG! Zu viele Spuren. Das kann Ihr Laufwerk beschädigen';
  81.   Text63  = 'WARNUNG! DOS verwaltet bei Disketten maximal 240 Basisverzeichniseinträge';
  82.   Text64  = 'Neue Diskette in Laufwerk ';
  83.   Text65  = ': einlegen';
  84.   Text66  = 'Anschließend ENTER drücken (ESC=Abbruch)';
  85.   Text67  = 'Übertragungsrate: ';
  86.   Text68  = ', GAP-Länge: ';
  87.   Text72  = 'EIN';
  88.   Text73  = 'AUS';
  89.   Text74  = 'Bitte Diskettennamen eingeben (max. 11 Zeichen): ';
  90.   Text75  = 'Fehler beim Erstellen des Namens.';
  91.   Text76  = 'Syntax-Fehler in der Datei FDFORMAT.CFG.';
  92.   Text77  = 'Lesefehler in der Datei FDFORMAT.CFG.';
  93.   Text78  = ', Sektoren: ';
  94.   Error01 = 'Falsches Disketten-Steuer-Kommando';
  95.   Error02 = 'Formatierung nicht gefunden';
  96.   Error03 = 'Diskette ist schreibgeschützt';
  97.   Error04 = 'Sektor nicht gefunden';
  98.   Error06 = 'Unerlaubter Diskettenwechsel';
  99.   Error08 = 'DMA-Baustein übergelaufen';
  100.   Error09 = 'Mehr als 64 kByte im DMA Baustein';
  101.   Error0c = 'Format nicht kompatibel mit Datenübertragungsrate';
  102.   Error10 = 'Zyklische Redundanzprüfung fehlerhaft';
  103.   Error20 = 'Diskettenadapter fehlerhaft';
  104.   Error40 = 'Laufwerkskopf konnte nicht positioniert werden';
  105.   Error80 = 'Keine Diskette im Laufwerk oder falsch eingelegt';
  106.   Errorxx = 'Fehlerursache unbekannt';
  107. {$ELSE}
  108.   Text01 = 'Error ';
  109.   Text02 = '(A)bort (R)etry (I)gnore ? ';
  110.   T3     = 'R';
  111.   Text04 = 'No valid drive.';
  112.   Text05 = 'SUBST/ASSIGN/Network-Drive.';
  113.   Text06 = 'Not a floppy drive.';
  114.   Text07 = 'Unknown drive type.';
  115.   Text08 = 'Formatting drive ';
  116.   Text09 = ' Head(s), ';
  117.   Text10 = ' Tracks, ';
  118.   Text11 = ' Sectors/track, ';
  119.   Text12 = ' Root Directory Entries, ';
  120.   Text13 = ' Sector(s)/Cluster, Sector-Shift: ';
  121.   Text14 = 'Head: ';
  122.   Text15 = ', Cylinder: ';
  123.   Text17 = 'Format error in system area: Program aborted.';
  124.   Text18 = 'More than ';
  125.   Text19 = ' sectors unreadable. Program aborted.';
  126.   Text20 = ' marked as bad';
  127.   Text21 = 'OEM-Entry:              ';
  128.   Text22 = 'Total sectors on disk:  ';
  129.   Text23 = 'Sectors per track:      ';
  130.   Text24 = 'Heads:                  ';
  131.   Text25 = 'Bytes per sector:       ';
  132.   Text26 = 'Hidden sectors:         ';
  133.   Text27 = 'Boot-sectors:           ';
  134.   Text28 = 'Number of FATs:         ';
  135.   Text29 = 'Sectors per FAT:        ';
  136.   Text30 = 'Total clusters on disk: ';
  137.   Text31 = ' total bytes on disk';
  138.   Text32 = ' bytes in bad sectors';
  139.   Text33 = ' bytes available';
  140.   Text34 = 'This drive cannot be formatted.';
  141.   Text35 = 'Drive is physical ';
  142.   Text36 = 'BIOS double-step support: ';
  143.   Text37 = 'XT-like';
  144.   Text38 = 'EPSON QX-16 like';
  145.   Text39 = 'AT-like';
  146.   Text40 = 'Not available or unknown';
  147.   Text41 = 'Syntax Error.';
  148.   Text42 = 'Usage is: FDFORMAT drive: [options]';
  149.   Text43 = ' Example: FDFORMAT a: t41 h2 s10 C1 D112';
  150.   Text44 = 'Option   Meaning                                 Default';
  151.   Text45 = 'drive:   drive to be formatted                   none';
  152.   Text46 = 'Tnn      Number of tracks                        40/80 depends on drive';
  153.   Text47 = 'Hnn      Number of heads                         2';
  154.   Text48 = 'Nnn      Number of sectors per track             9/15/18 depends on drive';
  155.   Text49 = 'Cn       Number of sectors per cluster           1 for HD, 2 for DD';
  156.   Text50 = 'Dnnn     Number of root directory entries        224 for HD, 112 for DDD';
  157.   Text51 = 'Inn      Interleave                              1';
  158.   Text52 = 'F        specify Diskette format';
  159.   Text53 = 'R        Skip verifying';
  160.   Text69 = 'Bnnn     Force a specified Format-Descriptor     depends on format';
  161.   Text70 = 'Gnnn     Use specified GAP-Length                depends on format';
  162.   Text71 = 'See the READ.ME file for other options';
  163.   Text54 = 'This program requires DOS 3.2 or higher.';
  164.   Text55 = 'FDFORMAT - Disk Formatter for High Capacity Disks - Ver 1.50';
  165.   Text56 = 'Copyright (c) 03-Sep-1989, Christoph H. Hochstätter, Germany';
  166.   Text57 = 'Heads must be 1 or 2.';
  167.   Text58 = 'At least one track should be formatted.';
  168.   Text59 = 'Interleave must be from 1 to ';
  169.   Text60 = '.';
  170.   Text61 = 'WARNING! DOS supports only 1 or 2 sectors per cluster.';
  171.   Text62 = 'WARNING! That many tracks could cause damage to your drive.';
  172.   Text63 = 'WARNING! DOS supports a maximum of 240 root directory entries.';
  173.   Text64 = 'Insert new Diskette in drive ';
  174.   Text65 = ':';
  175.   Text66 = 'Press ENTER when ready (ESC=QUIT)';
  176.   Text67 = 'Data Transfer Rate: ';
  177.   Text68 = ', GAP-Length: ';
  178.   Text72 = 'ON';
  179.   Text73 = 'OFF';
  180.   Text74 = 'Enter Volume Name (max. 11 characters): ';
  181.   Text75 = 'Error creating volume label.';
  182.   Text76 = 'Syntax Error in FDFORMAT.CFG.';
  183.   Text77 = 'Error reading FDFORMAT.CFG.';
  184.   Text78 = ', Sectors: ';
  185.   Error01 = 'Illegal Command. Bug in FDFORMAT';
  186.   Error02 = 'Address mark not found';
  187.   Error03 = 'Disk is write protected';
  188.   Error04 = 'Sector not found';
  189.   Error06 = 'Illegal disk change';
  190.   Error08 = 'DMA overrun';
  191.   Error09 = 'DMA accross 64 kB boundary';
  192.   Error0c = 'Format not compatible with data transfer rate';
  193.   Error10 = 'CRC error';
  194.   Error20 = 'controller/adapter error';
  195.   Error40 = 'seek error';
  196.   Error80 = 'No disk in drive';
  197.   Errorxx = 'Unknown error';
  198. {$ENDIF}
  199.  
  200. CONST
  201.   MaxForm = 20;
  202.  
  203. TYPE
  204.   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
  240.   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;                         {Erzwungener 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.   CfgDrive:   BYTE;                         {Laufwerksart aus Konfiguration}
  292.   BIOS:       BOOLEAN;                      {TRUE, wenn nur BIOS-Aufrufe}
  293.   PC80:       BYTE;                         {Maske, für 80 Spur nach XT-BIOS}
  294.   PC40:       BYTE;                         {Maske, für 80 Spur nach XT-BIOS}
  295.   V720:       BYTE;                         {Media-Typ für 720 kByte}
  296.   V360:       BYTE;                         {Media-Typ für 360 kByte}
  297.   V12:        BYTE;                         {Media-Typ für 1.2 MByte}
  298.   V144:       BYTE;                         {Media-Typ für 1.44 MByte}
  299.                                 
  300. CONST 
  301.   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.     $1E,                                            {  PUSH DS             }
  336.     $B8,$40,$00,                                    {  MOV  AX,40H         }
  337.     $8E,$D8,                                        {  MOV  DS,AX          }
  338.     $88,$16,$41,$00,                                {  MOV  [41H],DL       }
  339.     $1F,                                            {  POP  DS             }
  340.     $B8,$01,$01,                                    {  MOV  AX,101H        }
  341.     $CF);                                           {  IRET                }
  342.  
  343.   Help58: ARRAY[0..3] OF BYTE =(
  344.  
  345.     $CD,$25,                                        {  INT  25H            }
  346.     $59,                                            {  POP  CX             }
  347.     $CF);                                           {  IRET                }
  348.                                   
  349.   Boot: BootTyp=(
  350. {$IFDEF German}
  351.     $00,$00,
  352.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  353.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  354.     $00,$00,$8C,$C8,$3D,$00,$7C,$74,$08,$BE,$82,$02,$E8,$6A,$00,$CD,
  355.     $20,$FA,$33,$C0,$8E,$D0,$BC,$00,$7C,$B8,$B0,$07,$50,$50,$1F,$07,
  356.     $BE,$00,$01,$BF,$00,$03,$B9,$00,$01,$F3,$A5,$B8,$D0,$07,$50,$50,
  357.     $50,$1F,$07,$B8,$78,$01,$50,$CB,$FB,$BE,$C9,$01,$E8,$3A,$00,$B8,
  358.     $01,$02,$B9,$01,$00,$BA,$80,$00,$33,$DB,$53,$07,$BB,$00,$7C,$06,
  359.     $53,$CD,$13,$72,$0A,$26,$81,$3E,$FE,$7D,$55,$AA,$75,$01,$CB,$BE,
  360.     $0F,$02,$E8,$14,$00,$B4,$01,$CD,$16,$74,$06,$32,$E4,$CD,$16,$EB,
  361.     $F4,$32,$E4,$CD,$16,$33,$D2,$CD,$19,$8A,$04,$0A,$C0,$75,$01,$C3,
  362.     $56,$B4,$0E,$CD,$10,$5E,$46,$EB,$F0,$46,$44,$46,$4F,$52,$4D,$41,
  363.     $54,$20,$56,$65,$72,$73,$69,$6F,$6E,$20,$31,$2E,$35,$0A,$0D,$4B,
  364.     $65,$69,$6E,$65,$20,$53,$79,$73,$74,$65,$6D,$64,$69,$73,$6B,$65,
  365.     $74,$74,$65,$2E,$20,$53,$74,$61,$72,$74,$65,$6E,$20,$76,$6F,$6E,
  366.     $20,$46,$65,$73,$74,$70,$6C,$61,$74,$74,$65,$2E,$0A,$0D,$00,$4B,
  367.     $61,$6E,$6E,$20,$6E,$69,$63,$68,$74,$20,$76,$6F,$6E,$20,$64,$65,
  368.     $72,$20,$46,$65,$73,$74,$70,$6C,$61,$74,$74,$65,$20,$73,$74,$61,
  369.     $72,$74,$65,$6E,$2E,$0A,$0D,$53,$79,$73,$74,$65,$6D,$2D,$44,$69,
  370.     $73,$6B,$65,$74,$74,$65,$20,$69,$6E,$20,$4C,$61,$75,$66,$77,$65,
  371.     $72,$6B,$20,$41,$3A,$20,$65,$69,$6E,$6C,$65,$67,$65,$6E,$0A,$0D,
  372.     $41,$6E,$73,$63,$68,$6C,$69,$65,$E1,$65,$6E,$64,$20,$65,$69,$6E,
  373.     $65,$20,$54,$61,$73,$74,$65,$20,$64,$72,$81,$63,$6B,$65,$6E,$0A,
  374.     $0D,$00,$44,$69,$65,$73,$65,$20,$44,$61,$74,$65,$69,$20,$6E,$69,
  375.     $63,$68,$74,$20,$61,$75,$73,$66,$81,$68,$72,$65,$6E,$2E,$07,$0A,
  376.     $0D,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  377.     $00,$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,$55,$AA);
  382. {$ELSE}
  383.     $00,$00,
  384.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  385.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  386.     $00,$00,$8C,$C8,$3D,$00,$7C,$74,$08,$BE,$4A,$02,$E8,$6A,$00,$CD,
  387.     $20,$FA,$33,$C0,$8E,$D0,$BC,$00,$7C,$B8,$B0,$07,$50,$50,$1F,$07,
  388.     $BE,$00,$01,$BF,$00,$03,$B9,$00,$01,$F3,$A5,$B8,$D0,$07,$50,$50,
  389.     $50,$1F,$07,$B8,$78,$01,$50,$CB,$FB,$BE,$C9,$01,$E8,$3A,$00,$B8,
  390.     $01,$02,$B9,$01,$00,$BA,$80,$00,$33,$DB,$53,$07,$BB,$00,$7C,$06,
  391.     $53,$CD,$13,$72,$0A,$26,$81,$3E,$FE,$7D,$55,$AA,$75,$01,$CB,$BE,
  392.     $07,$02,$E8,$14,$00,$B4,$01,$CD,$16,$74,$06,$32,$E4,$CD,$16,$EB,
  393.     $F4,$32,$E4,$CD,$16,$33,$D2,$CD,$19,$8A,$04,$0A,$C0,$75,$01,$C3,
  394.     $56,$B4,$0E,$CD,$10,$5E,$46,$EB,$F0,$46,$44,$46,$4F,$52,$4D,$41,
  395.     $54,$20,$56,$65,$72,$73,$69,$6F,$6E,$20,$31,$2E,$35,$0A,$0D,$4E,
  396.     $6F,$20,$53,$79,$73,$74,$65,$6D,$64,$69,$73,$6B,$2E,$20,$42,$6F,
  397.     $6F,$74,$69,$6E,$67,$20,$66,$72,$6F,$6D,$20,$68,$61,$72,$64,$64,
  398.     $69,$73,$6B,$2E,$0A,$0D,$00,$43,$61,$6E,$6E,$6F,$74,$20,$6C,$6F,
  399.     $61,$64,$20,$66,$72,$6F,$6D,$20,$68,$61,$72,$64,$64,$69,$73,$6B,
  400.     $2E,$0A,$0D,$49,$6E,$73,$65,$72,$74,$20,$53,$79,$73,$74,$65,$6D,
  401.     $64,$69,$73,$6B,$20,$61,$6E,$64,$20,$70,$72,$65,$73,$73,$20,$61,
  402.     $6E,$79,$20,$6B,$65,$79,$2E,$0A,$0D,$00,$44,$6F,$20,$6E,$6F,$74,
  403.     $20,$65,$78,$65,$63,$75,$74,$65,$20,$74,$68,$69,$73,$20,$43,$4F,
  404.     $4D,$2D,$46,$69,$6C,$65,$2E,$0A,$0D,$00,$00,$00,$00,$00,$00,$00,
  405.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  406.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  407.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  408.     $00,$00,$00,$00,$00,$00,$00,$00,$00,$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,$55,$AA);
  414. {$ENDIF}
  415.  
  416. FUNCTION ReadKey:CHAR;
  417. VAR r: Registers;
  418. BEGIN
  419.   WITH r DO BEGIN
  420.     AH := 7;
  421.     Intr($21, r);
  422.     IF AL IN [3, 27] THEN BEGIN
  423.       WriteLn;
  424.       Halt(4);
  425.     END;
  426.     ReadKey := Chr(AL);
  427.   END;
  428. END;
  429.  
  430. PROCEDURE ConfigError;
  431. BEGIN
  432.   WriteLn;
  433.   WriteLn(Text76);
  434.   Halt(16);
  435. END;
  436.  
  437. PROCEDURE GetValue(x,y:STRING;VAR VALUE:BYTE);
  438. VAR
  439.   i, k: BYTE;
  440.   j   :   INTEGER;
  441. BEGIN
  442.   y := ' ' + y + '=';
  443.   i := Pos(y, x);
  444.   IF i <> 0 THEN BEGIN
  445.     i := i + Length(y);
  446.     WHILE x[i] = ' ' DO Inc(i);
  447.     IF i > Length(x) THEN ConfigError;
  448.     k := i;
  449.     WHILE x[k] <> ' ' DO Inc(k);
  450.     IF x[i] <> '$' THEN BEGIN
  451.       Val(Copy(x, i, k - i), VALUE, j);
  452.       IF j <> 0 THEN ConfigError;
  453.     END ELSE BEGIN
  454.       VALUE := DezH(Copy(x, i + 1, k - i - 1));
  455.       IF BaseError <> 0 THEN ConfigError;
  456.     END;
  457.   END;
  458. END;
  459.  
  460. PROCEDURE CfgRead;
  461. VAR f: TEXT;
  462.     x: STRING;
  463.     i: BYTE;
  464. BEGIN
  465.   CfgAt80  := FALSE;
  466.   CfgPC80  := FALSE;
  467.   CfgDrive := 255;
  468.   BIOS     := FALSE;
  469.   PC80     := 0;
  470.   PC40     := 0;
  471.   V720     := 0;
  472.   V360     := 0;
  473.   V12      := 0;
  474.   V144     := 0;
  475.   x := FSearch('FDFORMAT.CFG', GetEnv('PATH'));
  476.   IF x <> '' THEN BEGIN
  477.     Assign(f, x);
  478.     {$I-} Reset(f); {$I+}
  479.     IF IOResult = 0 THEN BEGIN
  480.       WHILE NOT EoF(f) DO BEGIN
  481.         ReadLn(f, x);
  482.         x := x + ' ';
  483.         FOR i:=1 TO Length(x) DO x[i]:=UpCase(x[i]);
  484.         IF Copy(x, 1, 2) = Para[1] THEN BEGIN
  485.           IF Pos(' BIOS ', x) <> 0 THEN BIOS := TRUE;
  486.           IF Pos(' AT ', x)   <> 0 THEN CfgAt80 := TRUE;
  487.           GetValue(x, 'F', CfgDrive);
  488.           IF NOT(CfgDrive IN [0, 1, 2, 7, 255]) THEN ConfigError;
  489.           IF Pos(' XT ', x) <> 0 THEN CfgPC80 := TRUE;
  490.           GetValue(x,   '40', PC40);
  491.           GetValue(x,   '80', PC80);
  492.           GetValue(x,  '360', V360);
  493.           GetValue(x,  '720', V720);
  494.           GetValue(x,  '1.2', V12);
  495.           GetValue(x, '1.44', V144);
  496.           GetValue(x,    'X', ShiftH);
  497.           GetValue(x,    'Y', ShiftT);
  498.         END;
  499.         IF CfgAt80 AND CfgPC80 THEN ConfigError;
  500.       END;
  501.       {$I-} Close(f); {$I+}
  502.     END ELSE BEGIN
  503.       WriteLn;
  504.       WriteLn(Text77);
  505.       Halt(8);
  506.     END;
  507.   END;
  508. END;
  509.  
  510. PROCEDURE Int13Error;
  511. BEGIN
  512.   WriteLn;
  513.   CASE Regs.AH OF
  514.     $01: Write(Error01);
  515.     $02: Write(Error02);
  516.     $03: Write(Error03);
  517.     $04: Write(Error04);
  518.     $06: Write(Error06);
  519.     $08: Write(Error08);
  520.     $09: Write(Error09);
  521.     $0C: Write(Error0c);
  522.     $10: Write(Error10);
  523.     $20: Write(Error20);
  524.     $40: Write(Error40);
  525.     $80: Write(Error80);
  526.     ELSE Write(Errorxx);
  527.   END;
  528.   WriteLn('.');
  529. END;
  530.  
  531. PROCEDURE Int13;
  532. VAR
  533.   AXS: WORD;
  534.   CHX: CHAR;
  535.   er : BOOLEAN;
  536. BEGIN
  537.   Again := FALSE;
  538.   WITH Regs DO BEGIN
  539.     AXS := AX;
  540.     REPEAT
  541.       AX := AXS;
  542.       IF AH = 5 THEN SetIntVec($1E, New1E);
  543.       IF Trk > 43 THEN DL := DL OR PC80 ELSE DL := DL OR PC40;
  544.       IF NOT(BIOS) THEN LwTab[DL] := DiskId;
  545.       Intr($13, Regs);
  546.       SetIntVec($1E, Old1E);
  547.       er := AH > 1;
  548.     UNTIL AH <> 6;
  549.     IF er THEN BEGIN
  550.       WriteLn;
  551.       WriteLn(Text01, AH, '  ',
  552.               Text14, DH,
  553.               Text15, CH,
  554.               Text78, CL,
  555.               '-',    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 BEGIN
  640.         WriteLn(Text06);
  641.         Trk := 0;
  642.         Exit;
  643.       END
  644.     END;
  645.     GetPhysical(Lw);
  646.     Lw := Lw AND $9F;
  647.     IF NOT(Lw IN [0..3]) THEN BEGIN
  648.       WriteLn(Text07);
  649.       Trk := 0;
  650.       Exit;
  651.     END;
  652.     IF CfgAt80 THEN
  653.       At80 := CfgAt80
  654.     ELSE
  655.       At80 := (ModelByte = $F8) OR (ModelByte = $FC);
  656.   END;
  657. END;
  658.  
  659. PROCEDURE ATSetDrive(Lw: BYTE; Trk, Sec, Disk2, Disk, SetUp: BYTE);
  660. BEGIN
  661.   WITH Regs DO BEGIN
  662.     DH := Lw; AH := $18; CH := Trk; CL := Sec;
  663.     Intr($13, Regs);
  664.     IF AH > 1 THEN BEGIN
  665.       AH := $17; AL := SetUp; DL := Lw;
  666.       Intr($13, Regs);
  667.     END;
  668.     IF ForceType <> 0 THEN BEGIN
  669.       LwTab[Lw] := ForceType;
  670.       BIOS := FALSE;
  671.     END ELSE IF Disk2 <> 0 THEN BEGIN
  672.       BIOS := FALSE;
  673.       LwTab[Lw] := Disk2;
  674.     END ELSE IF NOT(BIOS) THEN LwTab[Lw] := Disk;
  675.     DiskId := LwTab[Lw];
  676.   END;
  677. END;
  678.  
  679. PROCEDURE SectorAbsolute(Sector: WORD; VAR Hds, Trk, Sec: BYTE);
  680. VAR
  681.   h: WORD;
  682. BEGIN
  683.   Sec := (Sector MOD BPB.SpT) + 1;
  684.   h   := Sector DIV BPB.SpT;
  685.   Trk := h DIV BPB.Hds;
  686.   Hds := h MOD BPB.Hds;
  687. END;
  688.  
  689. FUNCTION SectorLogical(Hds, Trk, Sec: BYTE): WORD;
  690. BEGIN
  691.   SectorLogical := Trk * BPB.Hds * BPB.SpT + Hds * BPB.SpT + Sec - 1;
  692. END;
  693.  
  694. FUNCTION Cluster(Sector: WORD): WORD;
  695. BEGIN
  696.   Cluster := ((Sector - (BPB.RDE SHR 4)
  697.             - (BPB.SpF SHL 1) - 1)
  698.             DIV WORD(BPB.Spc)) + 2;
  699. END;
  700.  
  701. PROCEDURE ClusterOffset(Cluster: WORD; VAR Offset, Mask: WORD);
  702. BEGIN
  703.   Offset := Cluster * 3 SHR 1;
  704.   IF Cluster AND 1 = 0 THEN Mask := $FF7 ELSE Mask := $FF70;
  705. END;
  706.  
  707. PROCEDURE Format;
  708. VAR
  709.   i: BYTE;
  710. BEGIN
  711.   IF RDE AND 15 <> 0 THEN Inc(RDE, 16);
  712.   RDE := RDE SHR 4;
  713.   IF (Spc = 2) AND (RDE AND 1 = 0) THEN Inc(RDE);
  714.   BPB.RDE := RDE SHL 4;
  715.   CASE Sec OF
  716.     0..8:   New1E := @Para08;
  717.     9:      New1E := @Para09;
  718.     10:     New1E := @Para10;
  719.     11:     New1E := @Para11;
  720.     12..15: New1E := @Para15;
  721.     17:     New1E := @Para17;
  722.     18:     IF LWSec > 17 THEN
  723.               New1E := @Para18
  724.             ELSE
  725.               New1E := @Para18a;
  726.     19..20: New1E := @Para20;
  727.     21:     New1E := @Para21;
  728.     22..255:New1E := @Para22;
  729.   END;
  730.   IF GpL <> 0 THEN New1E^[7] := GpL ELSE GpL := New1E^[7];
  731.   WriteLn;
  732.   Write(Text08, Chr(Lw + $41), ': ');
  733.   IF HD THEN WriteLn('High-Density') ELSE WriteLn('Double-Density');
  734.   WriteLn(Hds, Text09, Trk, Text10, Sec, Text11, 'Interleave: ', Il, Text68, GpL);
  735.   WriteLn(BPB.RDE, Text12, Spc, Text13, ShiftT, ':', ShiftH);
  736.   BTTCount := 0;
  737.   WITH Regs DO BEGIN
  738.     FOR i := 1 TO 25 DO BEGIN
  739.       Table[i].f := 2;
  740.       Table2[i]:=0;
  741.     END;
  742.     i := 1;
  743.     n := 1;
  744.     REPEAT
  745.       REPEAT
  746.         WHILE Table2[n] <> 0 DO Inc(n);
  747.         IF n > Sec THEN n := 1;
  748.       UNTIL Table2[n] = 0;
  749.       Table2[n] := i;
  750.       n := n + Il;
  751.       Inc(i);
  752.     UNTIL i > Sec;
  753.     AX := 0;
  754.     BX := 0;
  755.     DL := Lw;
  756.     IF At80 THEN BEGIN
  757.       IF (Trk > 43) AND (Sec > 11) AND (Sec < 16) THEN ATSetDrive(Lw, 79, LWSec,  V12, $14, 5);
  758.       IF (Trk > 43) AND (Sec > 11) AND (Sec > 15) THEN ATSetDrive(Lw, 79, LWSec, V144, $14, 5);
  759.       IF (DosDrive IN [0, 1]) AND (Trk > 43) AND (Sec < 12) THEN ATSetDrive(Lw, 79, 9, V720, $53, 4);
  760.       IF (DosDrive IN [2, 7]) AND (Trk > 43) AND (Sec < 12) THEN ATSetDrive(Lw, 79, 9, V720, $97, 4);
  761.       IF (Trk < 44) AND (Sec > 11) THEN ATSetDrive(Lw, 39, LWSec, 0, $34, 3);
  762.       IF (DosDrive IN [2, 7]) AND (Trk < 44) AND (Sec < 12) THEN ATSetDrive(Lw, 39, 9, V360, $B7, 2);
  763.       IF (DosDrive IN [0, 1]) AND (Trk < 44) AND (Sec < 12) THEN ATSetDrive(Lw, 39, 9, V360, $73, 2);
  764.     END;
  765.     IF At80 AND NOT(BIOS) THEN BEGIN
  766.       Write(Text67);
  767.       CASE (DiskId AND $C0) OF
  768.         $00: Write('500');
  769.         $40: Write('300');
  770.         $80: Write('250');
  771.         $C0: Write('???');
  772.       END;
  773.       Write(' kBaud, Double-Stepping: ');
  774.       IF (DiskId AND 32) = 0 THEN
  775.         Write(Text73, ', ')
  776.       ELSE
  777.         Write(Text72, ', ');
  778.     END;
  779.     BPB.Jmp[1] := $EB;
  780.     BPB.Jmp[2] := $40;
  781.     BPB.Jmp[3] := 144;
  782.     BPB.SpT := Sec;
  783.     BPB.Hds := Hds;
  784.     BPB.SHH := 0;
  785.     BPB.BpS := 512;
  786.     BPB.Spc := Spc;
  787.     BPB.Res := 1;
  788.     BPB.FAT := 2;
  789.     BPB.Sec := Sec * BPB.Hds * Trk;
  790.     BPB.Boot_Code := Boot;
  791.     IF ForceMedia = 0 THEN BEGIN
  792.       CASE BPB.Spc OF
  793.         1:   IF (Trk > 44) AND (BPB.SpT IN [12..17]) THEN
  794.                BPB.MDs := $F9
  795.              ELSE
  796.                BPB.MDs := $F0;
  797.         2:   IF Trk IN [1..43] THEN BPB.MDs := $FD ELSE BPB.MDs := $F9;
  798.         ELSE BPB.MDs := $F8;
  799.       END;
  800.     END
  801.     ELSE BPB.MDs := ForceMedia;
  802.     BPB.SpF := Trunc(BPB.Sec * 1.5 / 512 / BPB.Spc) + 1;
  803.     WriteLn('Media-Byte: ', HexF(BPB.MDs, 2)); WriteLn;
  804.     DL := Lw;
  805.     AX := 0;
  806.     REPEAT Int13 UNTIL NOT Again;
  807.     n := 0;
  808.     FillChar(Buffer, SizeOf(Buffer), #0);
  809.     FOR Track := Trk - 1 DOWNTO 0 DO BEGIN
  810.       IF Track <> Trk-1 THEN n := n + ShiftT;
  811.       FOR Head := Hds - 1 DOWNTO 0 DO BEGIN
  812.         IF Head <> Hds - 1 THEN n := n + ShiftH;
  813.         n := n MOD Sec;
  814.         FOR i := 1 TO Sec DO
  815.           Table[i].s := Table2[(i + n - 1) MOD Sec + 1];
  816.         Write(Text14, Head, Text15, Track);
  817.         x := SectorLogical(Head, Track, 1);
  818.         x := Cluster(x);
  819.         FOR i := 1 TO Sec DO BEGIN
  820.           Table[i].t := Track;
  821.           Table[i].h := Head;
  822.         END;
  823.         REPEAT
  824.           AH := 5;
  825.           AL := Sec;
  826.           DL := Lw;
  827.           DH := Head;
  828.           CH := Track;
  829.           CL := 1;
  830.           ES := Seg(Table);
  831.           BX := Ofs(Table);
  832.           Write('  F   '#8#8#8);
  833.           Mem[$40:$41] := 0;
  834.           Int13;
  835.           Write(#8,'V                         '); Write(#13);
  836.           IF NOT(Again OR NoVerify) OR (Track < 3) THEN BEGIN
  837.             AH := 3;
  838.             AL := Sec;
  839.             DL := Lw;
  840.             DH := Head;
  841.             CH := Track;
  842.             CL := 1;
  843.             ES := Seg(Buffer);
  844.             BX := Ofs(Buffer);
  845.             Int13;
  846.           END;
  847.         UNTIL NOT Again;
  848.         IF (FCarry AND Flags) <> 0 THEN BEGIN
  849.           IF (x < 2) OR (x > 10000) THEN BEGIN
  850.             WriteLn(Text17);
  851.             Halt(2);
  852.           END;
  853.           Inc(BTTCount);
  854.           IF BTTCount>20 THEN BEGIN
  855.             WriteLn(Text18, 20 * Sec, Text19);
  856.             Halt(2);
  857.           END;
  858.           BTT[BTTCount].Track := Track;
  859.           BTT[BTTCount].Head := Head;
  860.           WriteLn(Text14, Head, Text15, Track, Text20, #10#13);
  861.         END;
  862.       END;
  863.     END;
  864.   END;
  865. END;
  866.  
  867. PROCEDURE WriteBootSect;
  868. BEGIN
  869.   WITH Regs DO BEGIN
  870.     WriteLn;
  871.     BPB.OEM:='(C)DMV91';
  872.     WriteLn;
  873.     WriteLn(Text21, BPB.OEM); WriteLn(Text22, BPB.Sec);
  874.     WriteLn(Text23, BPB.SpT); WriteLn(Text24, BPB.Hds);
  875.     WriteLn(Text25, BPB.BpS); WriteLn(Text26, BPB.SHH);
  876.     WriteLn(Text27, BPB.Res); WriteLn(Text28, BPB.FAT);
  877.     WriteLn(Text29, BPB.SpF); WriteLn(Text30, Cluster(BPB.Sec) - 2);
  878.     DH := 0;
  879.     DL := Lw;
  880.     CH := 0;
  881.     CL := 1;
  882.     AL := 1;
  883.     AH := 3;
  884.     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;   (* Das kann man auch anders machen !!! *)
  928. VAR
  929.   ComSpec: STRING[40];
  930. BEGIN
  931.   ComSpec := GetEnv('COMSPEC');
  932.   Exec(ComSpec, '/C SYS ' + Chr(Lw + $41) + ':');
  933.   Exec(ComSpec,'/C COPY '+ ComSpec + ' ' + Chr(Lw + $41) + ':\ > NUL');
  934. END;
  935.  
  936. PROCEDURE WriteLabel(x: STRING);
  937. VAR i: BYTE;
  938. BEGIN
  939.   WITH Regs DO BEGIN
  940.     IF x = '' THEN BEGIN
  941.       REPEAT
  942.         Write(Text74);
  943.         ReadLn(x);
  944.       UNTIL Length(x) < 12;
  945.     END;
  946.     IF x <> '' THEN BEGIN
  947.       IF Length(x)>8 THEN Insert('.',x,9);
  948.       x := Chr(Lw + $41) + ':\' + x;
  949.       x[Length(x) + 1] := #0;
  950.       CX := 8;
  951.       DS := Seg(x);
  952.       DX := Ofs(x) + 1;
  953.       AH := $3C;
  954.       MsDos(Regs);
  955.       IF (FCarry AND Flags) <> 0 THEN BEGIN
  956.         WriteLn(Text75);
  957.         Exit;
  958.       END;
  959.       BX := AX;
  960.       AH := $3E;
  961.       MsDos(Regs);
  962.       IF (FCarry AND Flags) <> 0 THEN BEGIN
  963.         WriteLn(Text75);
  964.         Halt(32);
  965.       END;
  966.     END;
  967.   END;
  968. END;
  969.  
  970. PROCEDURE DrivePrt;
  971. BEGIN
  972.   WriteLn;
  973.   IF LWTrk = 0 THEN BEGIN
  974.     WriteLn(Text34);
  975.     Exit;
  976.   END;
  977.   Write(Text35, Chr(Lw + $41));
  978.   IF LWHd THEN
  979.     Write(': High-Density, ')
  980.   ELSE
  981.     Write(': Double-Density, ');
  982.   WriteLn(LWTrk + 1, Text10, LWSec, Text11);
  983.   Write(Text36);
  984.   IF PC80 = $20 THEN WriteLn(Text37);
  985.   IF PC80 = $40 THEN WriteLn(Text38);
  986.   IF At80 THEN WriteLn(Text39);
  987.   IF NOT(At80) AND (PC80=0) THEN WriteLn(Text40);
  988.   WriteLn;
  989. END;
  990.  
  991. PROCEDURE SyntaxError;
  992. BEGIN
  993.   WriteLn;
  994.   WriteLn(Text41);
  995.   WriteLn;
  996.   WriteLn(Text42);
  997.   WriteLn(Text43);
  998.   WriteLn;
  999.   WriteLn(Text44);
  1000.   WriteLn;
  1001.   WriteLn(Text45);
  1002.   WriteLn(Text46);
  1003.   WriteLn(Text47);
  1004.   WriteLn(Text48);
  1005.   WriteLn(Text49);
  1006.   WriteLn(Text50);
  1007.   WriteLn(Text51);
  1008.   WriteLn(Text52);
  1009.   WriteLn(Text53);
  1010.   WriteLn(Text69);
  1011.   WriteLn(Text70);
  1012.   WriteLn;
  1013.   WriteLn(Text71);
  1014.   Halt(1);
  1015. END;
  1016.  
  1017. PROCEDURE CheckDos;
  1018. VAR Version: WORD;
  1019. BEGIN
  1020.   Version := Swap(DosVersion);
  1021.   IF Version < $314 THEN BEGIN
  1022.     WriteLn(Text54);
  1023.     Halt(128);
  1024.   END;
  1025. END;
  1026.  
  1027. BEGIN (* Main *)
  1028.   WriteLn;
  1029.   WriteLn(Text55);
  1030.   WriteLn(Text56);
  1031.   CheckDos;
  1032.   GetIntVec($1E, Old1E);
  1033.   New1E := Old1E;
  1034.   Parse;
  1035.   NoVerify := FALSE;
  1036.   IF (Length(Para[1]) <> 2) OR (Para[1, 2] <> ':') THEN SyntaxError;
  1037.   Lw:=Ord(UpCase(Para[1, 1])) - $41;
  1038.   ShiftT := 0;
  1039.   ShiftH := 0;
  1040.   CfgRead;
  1041.   DriveTyp(Lw, LWHd, LWTrk, LWSec);
  1042.   DrivePrt;
  1043.   IF (LWTrk = 0) AND (Para[1] <> '') THEN Halt(1);
  1044.   RDE := 0;
  1045.   Il  := 0;
  1046.   Spc := 0;
  1047.   GpL := 0;
  1048.   SetLabel := FALSE;
  1049.   Sys := FALSE;
  1050.   ForceType  := 0;
  1051.   ForceMedia := 0;
  1052.   Batch      := FALSE;
  1053.   Trk        := LWTrk + 1;
  1054.   Sec        := LWSec;
  1055.   Hds        := 2;
  1056.   FOR i := 2 TO PCount DO
  1057.     IF Para[i] <> '' THEN BEGIN
  1058.       CHX := Para[i, 1];
  1059.       IF UpCase(CHX) = 'V' THEN BEGIN
  1060.         DLabel := '';
  1061.         SetLabel := TRUE;
  1062.         DLabel := Copy(Para[i], 2, 11);
  1063.       END ELSE IF Length(Para[i]) = 1 THEN BEGIN
  1064.         CASE UpCase(CHX) OF
  1065.           'P': BEGIN END;
  1066.           'R': NoVerify := TRUE;
  1067.           'O': BEGIN
  1068.                    Trk := 80;
  1069.                    Sec := 9;
  1070.                    RDE := 144;
  1071.                  END;
  1072.             '4': BEGIN
  1073.                    Trk := 40;
  1074.                    Sec := 9;
  1075.                  END;
  1076.             '1': BEGIN
  1077.                    Hds := 1;
  1078.                  END;
  1079.             '8': BEGIN
  1080.                    Sec := 8;
  1081.                  END;
  1082.             'S': BEGIN
  1083.                    Sys := TRUE;
  1084.                  END;
  1085.             'K': BEGIN
  1086.                    Batch := TRUE;
  1087.                  END;
  1088.           ELSE SyntaxError;
  1089.         END;
  1090.       END ELSE BEGIN
  1091.         IF Para[i, 2]= '$' THEN BEGIN
  1092.           n := DezH(Copy(Para[i], 3, 255));
  1093.           j := BaseError
  1094.         END ELSE Val(Copy(Para[i], 2, 255), n, j);
  1095.         IF j <> 0 THEN SyntaxError;
  1096.         CASE UpCase(Para[i, 1]) OF
  1097.           'T': Trk := n;
  1098.           'H': Hds := n;
  1099.           'N': Sec := n;
  1100.           'S': Sec := n;
  1101.           'M': ForceMedia := n;
  1102.           'D': RDE := n;
  1103.           'C': Spc := n;
  1104.           'I': Il := n;
  1105.           'G': GpL := n;
  1106.           'X': ShiftH := n;
  1107.           'Y': ShiftT := n;
  1108.           'B': ForceType := n;
  1109.           'F': BEGIN
  1110.                  Found := FALSE;
  1111.                  FOR j := 1 TO MaxForm DO
  1112.                    IF NOT(Found) AND (n = FTab[j].Fmt) THEN BEGIN
  1113.                      Trk := FTab[j].Trk;
  1114.                      Sec := FTab[j].Sec;
  1115.                      Hds := FTab[j].Hds;
  1116.                      Found := TRUE;
  1117.                    END;
  1118.                  IF NOT(Found) THEN SyntaxError;
  1119.                END;
  1120.           ELSE SyntaxError;
  1121.         END;
  1122.       END;
  1123.     END;
  1124.   IF Sec > 11 THEN HD := TRUE ELSE HD := FALSE;
  1125.   IF RDE = 0 THEN
  1126.     CASE HD OF
  1127.       TRUE:  RDE := 224;
  1128.       FALSE: RDE := 112;
  1129.     END;
  1130.   IF Spc = 0 THEN
  1131.     CASE HD OF
  1132.       TRUE:  Spc := 1;
  1133.       FALSE: Spc := 2;
  1134.     END;
  1135.   IF Il = 0 THEN
  1136.     IF Sec - LWSec IN [3..8] THEN Il := 2 ELSE Il := 1;
  1137.   IF NOT (Hds IN [1..2]) THEN BEGIN
  1138.     WriteLn(Text57);
  1139.     Halt(1);
  1140.   END;
  1141.   IF Trk < 1 THEN BEGIN
  1142.     WriteLn(Text58);
  1143.     Halt(1);
  1144.   END;
  1145.   IF Il >= Pred(Sec) THEN BEGIN
  1146.     WriteLn(Text59, Pred(Sec), Text60);
  1147.     Halt(1);
  1148.   END;
  1149.   IF NOT(Spc IN [1..2]) THEN
  1150.     WriteLn(Text61);
  1151.   IF SHORTINT(Trk - LWTrk) > 4 THEN
  1152.     WriteLn(Text62);
  1153.   IF RDE > 240 THEN
  1154.     WriteLn(Text63);
  1155.   IF NOT(Batch) THEN BEGIN
  1156.     WriteLn;
  1157.     WriteLn(Text64, Chr(Lw + $41),Text65);
  1158.     WriteLn(Text66);
  1159.     CHX := ReadKey;
  1160.   END;
  1161.   Format;
  1162.   WriteBootSect;
  1163.   IF Sys THEN WriteSys;
  1164.   IF SetLabel THEN WriteLabel(DLabel);
  1165. END. (* Main *)
  1166.  
  1167. (*------------------------------------------------------------*)
  1168.