home *** CD-ROM | disk | FTP | other *** search
- (*--------------------------------------------------------*)
- (* EDD.PAS *)
- (* Expanded DiskDoubler v1.51 *)
- (* (c) 1991 Michael Winter & TOOLBOX *)
- (* Compiler: Quick Pascal 1.0, Turbo Pascal 5.x/6.0 *)
- (*--------------------------------------------------------*)
- {$A-,B-,D-,F-,G-,I-,L-,N-,R-,S-,V-,M 4096, 0, 655360}
- {$IFDEF VER10} {$M-} {$ENDIF}
-
- PROGRAM ExpandedDiskDoubler;
-
- USES
- Crt, Dos;
-
- TYPE
- Zeiger = ^List;
- List = RECORD (* Liste der Spuren im Heap *)
- Element : Pointer;
- Next : Zeiger;
- END;
- BSec = RECORD (* Aufbau des Bootsektors *)
- Jump : ARRAY [1..3] OF BYTE;
- Name : ARRAY [1..8] OF BYTE;
- BpS : WORD;
- SpC : BYTE;
- SecR : WORD;
- FatS : BYTE;
- Root, SecC : WORD;
- Media : BYTE;
- SecF, SpS,
- Heads, DiS : WORD;
- STrap : ARRAY [1..482] OF BYTE;
- END;
- FormatPuffer = RECORD (* wird zum Formatieren benötigt *)
- Spur,
- Seite,
- Sektor,
- LaengenTyp : BYTE;
- END;
- LWParamRec = RECORD (* Laufwerksparametertabelle *)
- StepTime,
- DMA,
- MotorEnd,
- BpS,
- SpS,
- GapTime,
- DataTransferLen,
- Gap,
- FormatFillChar,
- HeadPause,
- MotorStart : BYTE;
- END;
- {$IFNDEF VER10}
- CString = STRING[255]; (* nur für Turbo-Pascal *)
- {$ENDIF}
- EMMName = ARRAY [1..8] OF CHAR; (* Name des EMM *)
- EMMNaPtr = ^EMMName; (* Zeiger auf den Namen *)
- PageRec = RECORD (* benötigt für EMM-Funktion 50h *)
- Logical, Physical : WORD;
- END;
- CONST
- Copyright : STRING[65] = 'EDD - Expanded DiskDoubler'
- + ' v1.5 (C) 1991 Michael Winter & TOOLBOX';
- Disk : BOOLEAN = FALSE;
- EMS : BOOLEAN = FALSE;
- HeapOnly : BOOLEAN = FALSE;
- TempFName : STRING[12] = 'TEMPFILE.EDD';
- Format : BOOLEAN = FALSE;
- Verify : BOOLEAN = FALSE;
- Name : EMMName = 'EMMXXXX0';
- CRLF = #13#10;
-
- VAR
- Source, drive,
- Target : BYTE;
- Buffer : Pointer;
- Help, Top, LP: Zeiger;
- TempFile : FILE;
- Temp : STRING;
- Regs : Registers;
- OldDir : DirStr;
- s, t : STRING[2];
- BootSector : BSec;
- SpS, Sides,
- Tracks, Media,
- BpS, i : WORD;
- Size,
- HdAvail : LONGINT;
- DoFormat : BOOLEAN;
- FormatBuf : ARRAY [1..18] OF FormatPuffer;
- ParamTab : ^LWParamRec; (* Laufwerksparametertab. *)
- PageFrame, (* Segment des Pageframes *)
- Handle : WORD; (* Handle f. Zugriff auf EMS-Page *)
- Spuren : LONGINT;
- Versuche : BYTE;
- ch : CHAR;
- OldEnd : Pointer; (* Zeiger auf alte Exitproc.*)
- {$IFDEF VER10}
- OldTab : LWParamRec; (* Alte Parametertabelle *)
- {$ELSE} (* Unterschied Turbo-/Quick-Pascal *)
- OldTab : Pointer;
- {$ENDIF}
- PageBuffer : ARRAY [0..3] OF PageRec;
-
- PROCEDURE ClearBuffer; (* Löschen des Tastaturpuffers *)
- VAR
- x : CHAR;
- BEGIN
- WHILE KeyPressed DO x := ReadKey;
- END;
-
- FUNCTION ExistEMM: BOOLEAN; (* Test auf EMM *)
- BEGIN
- Regs.AX := $3567; (* GetIntVec $67 *)
- MsDos(Regs); (* wenn Zeiger auf Null: kein EM-Manager *)
- ExistEMM := (EMMNaPtr(Ptr(Regs.ES, 10))^ = Name);
- END;
-
- FUNCTION EMSAvail : LONGINT; (* Speichergröße feststellen *)
- VAR
- h : LONGINT;
- BEGIN
- IF ExistEMM THEN WITH Regs DO BEGIN (* EMS vorhanden *)
- AH := $42;
- Intr($67, Regs); (* EMS-Interrupt *)
- h := (BX DIV 4) * 4;
- EMSAvail := h * $4000; (* Größe EMS *)
- AH := $46;
- Intr($67, Regs);
- IF AL < $40 THEN EMSAvail := 0; (* zu wenig oder *)
- END ELSE EMSAvail := 0; (* kein EMS *)
- END;
-
- FUNCTION Exist(Datei: STRING): BOOLEAN;
- VAR
- f: SearchRec;
- BEGIN
- FindFirst(Datei, AnyFile, f); Exist := (DosError = 0);
- END;
-
- PROCEDURE DeleteFile(Name : CString);
- (* Datei löschen über DOS-Funktion 41h *)
- BEGIN
- Regs.AH := $41;
- Regs.DS := Seg(Name);
- Regs.DX := Ofs(Name);
- MsDos(Regs);
- END;
-
- PROCEDURE Error(Number : BYTE);
- (* Ausgabe eines Diskettenfehlers, evtl. Programmabbruch *)
- VAR
- Str : STRING[80];
- BEGIN
- IF Number IN [$08, $20, $BB, $FF] THEN BEGIN
- CASE Number OF
- $08: Str := 'DMA-Überlauf';
- $20: Str := 'Diskettencontroller-Fehler';
- $BB: Str := 'BIOS-Fehler / BIOS-Inkompatibilität';
- $FF: Str := 'nicht aufschlüsselbarer Fehler';
- END;
- WriteLn('Fataler Fehler Nr. ', Number, ':', CRLF + Str);
- Halt(Number);
- END;
- CASE Number OF
- $02: Str := 'Sektorkennung nicht gefunden';
- $03: Str := 'Diskette ist schreibgeschützt';
- $04: Str := 'Sektor nicht gefunden';
- $06: Str := 'Diskette nicht im Laufwerk';
- $10: Str := 'Lesefehler';
- $40: Str := 'Spur nicht gefunden';
- $80: Str := 'Laufwerk antwortet nicht';
- ELSE Str := '';
- END;
- GotoXY(1, WhereY); ClrEoL;
- GotoXY(1, WhereY); Write(Str);
- IF Number = $09 THEN BEGIN
- IF DosVersion = $1F03 THEN (* DR-DOS 3.41, DR-DOS 5.0 *)
- ELSE BEGIN
- WriteLn('Fataler Fehler Nummer 9:');
- WriteLn('DMA-Segmentgrenzen-Überschreitung');
- Halt(Number);
- END;
- END;
- ClearBuffer;
- IF Number IN [$03, $04, $06, $80] THEN BEGIN
- CASE Number OF
- $03: Str := 'Schreibschutz entfernen';
- $04: Str := 'neue Diskette einlegen';
- $06: Str := 'andere Diskette einlegen';
- $80: Str := 'Diskette einlegen';
- END;
- Write(#7' - ' + Str + ' und Taste drücken ');
- REPEAT UNTIL KeyPressed;
- ch := ReadKey;
- IF ch IN [#3, #27] THEN Halt(0);
- Inc(Versuche);
- GotoXY(1, WhereY); ClrEoL;
- END;
- END;
-
- PROCEDURE EMSError(Number : BYTE); (* Fehler des EMM *)
- BEGIN
- GotoXY(1, WhereY); ClrEoL;
- GotoXY(1, WhereY); Write(Number);
- WriteLn(' - Fehlfunktion des EMM oder der EMS-Hardware');
- WriteLn('Kopiervorgang abbrechen (J/N)? ');
- REPEAT
- ClearBuffer; ch := UpCase(ReadKey);
- UNTIL ch IN ['J', 'Y', 'N'];
- IF ch IN ['J', 'Y'] THEN Halt(Number);
- END;
-
- PROCEDURE InitTab;
- (* Diskettenparameter zur Laufwerksbeschleunigung patchen *)
- BEGIN (* und Diskettentyp festlegen *)
- WITH ParamTab^ DO BEGIN
- StepTime := 223; MotorEnd := 25;
- SpS := Lo(BootSector.SpS); GapTime := 27;
- FormatFillChar := 246; HeadPause := 1;
- MotorStart := 0;
- END;
- END;
-
- PROCEDURE HelpDisp; (* bei Parameter '/?' Hilfe ausgeben *)
- BEGIN
- HighVideo; WriteLn(CRLF + Copyright); LowVideo; WriteLn;
- WriteLn('Edd [A:|B:] [A:|B:] [/F[ORMAT]] [/V[ERIFY]]');
- WriteLn('Voreinstellung: A: A:' + CRLF);
- WriteLn('Optionen:' + CRLF);
- WriteLn('/FORMAT: Zieldiskette wird immer formatiert':50);
- WriteLn('/VERIFY: Nach dem Schreiben einer Spur wird':50);
- WriteLn('diese nochmals überprüft':40);
- WriteLn('/? : diese Hilfeanzeige':34, CRLF); Halt(1);
- END;
-
- PROCEDURE CheckParameters; (* Kommandozeile überprüfen *)
- VAR
- Next : BOOLEAN;
- Hilf : STRING[128];
- i, j : BYTE;
- BEGIN
- t := ''; s := '';
- FOR i := 1 TO ParamCount DO BEGIN
- Hilf := ParamStr(i);
- FOR j := 1 TO Length(Hilf) DO
- IF Hilf[j] = '-' THEN Hilf[j] := '/'
- ELSE Hilf[j] := UpCase(Hilf[j]);
- IF Pos('/F', Hilf) > 0 THEN Format := TRUE;
- IF Pos('/V', Hilf) > 0 THEN Verify := TRUE;
- IF Pos('/?', Hilf) > 0 THEN HelpDisp;
- END;
- IF ParamCount = 0 THEN BEGIN
- Source := 0; Target := 0; s := 'A:'; t := 'A:';
- END;
- IF ParamCount = 1 THEN BEGIN
- Hilf := ParamStr(1);
- FOR i := 1 TO Length(Hilf) DO
- Hilf[i] := UpCase(Hilf[i]);
- IF (Pos('/F', Hilf) > 0) OR (Pos('/V', Hilf) > 0) THEN
- s := 'A:' ELSE s := Hilf;
- t := s;
- IF ((s <> 'A:') AND (s <> 'B:')) THEN HelpDisp;
- END;
- IF ParamCount > 1 THEN BEGIN
- i := 1; Next := FALSE;
- REPEAT
- Hilf := ParamStr(i);
- FOR j := 1 TO Length(Hilf) DO
- Hilf[j] := UpCase(Hilf[j]);
- IF (Hilf = 'A:') OR (Hilf = 'B:') THEN BEGIN
- s := Hilf; Next := TRUE;
- END;
- Inc(i);
- UNTIL (i = ParamCount + 1) OR Next;
- Next := FALSE;
- REPEAT
- Hilf := ParamStr(i);
- FOR j := 1 TO Length(Hilf) DO
- Hilf[j] := UpCase(Hilf[j]);
- IF (Hilf = 'A:') OR (Hilf = 'B:') THEN BEGIN
- t := Hilf; Next := TRUE;
- END;
- Inc(i);
- UNTIL (i = ParamCount + 1) OR Next;
- IF t = '' THEN t := s;
- END;
- IF ((s = '') OR (t = '')) THEN HelpDisp;
- Source := Ord(UpCase(s[1])) - 65;
- Target := Ord(UpCase(t[1])) - 65;
- END;
-
- PROCEDURE DiskTest(Source : BYTE);
- (* Testen, ob Laufwerk bereit ist und Bootsektor einlesen *)
- VAR (* danach Diskettentyp festlegen *)
- ch : CHAR;
- Ok : BOOLEAN;
- Hilfe : BYTE;
- BEGIN
- Versuche := 3; Ok := TRUE;
- WriteLn('Bitte die QUELLDISKETTE in Laufwerk '
- + Chr(Source + 65) + ': einlegen');
- Write('Wenn bereit, beliebige Taste drücken . . .');
- REPEAT
- ClearBuffer;
- ch := ReadKey;
- WriteLn;
- IF ch IN [#3, #27] THEN Halt(1);
- REPEAT
- ChDir(s + '\');
- IF IOResult <> 0 THEN Error(6) (* Laufwerk nicht *)
- UNTIL IOResult = 0; (* bereit *)
- ChDir(OldDir);
- WITH Regs DO BEGIN
- AH := $02;
- DL := Source;
- DH := 0;
- CH := 0;
- CL := 1;
- AL := 1;
- ES := Seg(BootSector);
- BX := Ofs(BootSector);
- Intr($13, Regs);
- Dec(Versuche);
- END;
- UNTIL (Regs.AH = 0) OR (Versuche = 0);
- IF Regs.AH <> 0 THEN Error(Regs.AH);
- BpS := BootSector.BpS;
- SpS := BootSector.SpS;
- Media := BootSector.Media;
- CASE BootSector.Media OF
- $F0: BEGIN Sides := 2; Tracks := 80; SpS := 18; END;
- $F9: BEGIN Sides := 2; Tracks := 80; END;
- $FA: BEGIN Sides := 1; Tracks := 80; SpS := 8; END;
- $FB: BEGIN Sides := 2; Tracks := 80; SpS := 8; END;
- $FC: BEGIN Sides := 1; Tracks := 40; SpS := 9; END;
- $FD: BEGIN Sides := 2; Tracks := 40; SpS := 9; END;
- $FE: BEGIN Sides := 1; Tracks := 40; SpS := 8; END;
- $FF: BEGIN Sides := 2; Tracks := 40; SpS := 8; END;
- ELSE BEGIN
- WriteLn('Unbekanntes Diskettenformat!'); Halt(1);
- END;
- END;
- WriteLn(CRLF + 'Kopiere ', Sides, ' Seite(n), ', Tracks,
- ' Spuren zu ', SpS,' Sektoren.');
- Size := DiskSize(Source + 1);
- (* Speicherverwaltungsstrategie festlegen: *)
- IF MemAvail > Size THEN HeapOnly := TRUE
- ELSE IF (MemAvail + EMSAvail > Size) THEN BEGIN
- HeapOnly := FALSE; EMS := TRUE;
- END ELSE IF (MemAvail + HdAvail > Size) THEN BEGIN
- HeapOnly := FALSE; Disk := TRUE;
- END ELSE BEGIN
- WriteLn(CRLF + 'Nicht genügend Pufferspeicher ' +
- 'vorhanden' + CRLF);
- Halt(1);
- END;
- Write('Puffere Daten ');
- IF HeapOnly THEN WriteLn('im Hauptspeicher . . .');
- IF EMS THEN WriteLn('im Expanded Memory . . .');
- IF Disk THEN WriteLn('in der Datei ' + Temp + TempFName);
- FOR i := 1 TO SpS DO BEGIN
- FormatBuf[i].Sektor := i;
- CASE BootSector.BpS OF
- $080: FormatBuf[i].LaengenTyp := 0;
- $100: FormatBuf[i].LaengenTyp := 1;
- $200: FormatBuf[i].LaengenTyp := 2;
- $400: FormatBuf[i].LaengenTyp := 3;
- ELSE BEGIN
- WriteLn(CRLF + 'Unbekanntes Diskettenformat!');
- Halt(1);
- END;
- END;
- END;
- InitTab;
- END;
-
- PROCEDURE TestTarget(Target : BYTE); (* Laufwerkstest *)
- VAR
- ch : CHAR;
- y, Result, Hilfe : BYTE;
- BEGIN
- DoFormat := FALSE;
- WriteLn;
- y := WhereY;
- FOR i := y TO 23 DO BEGIN GotoXY(1, i); ClrEoL; END;
- GotoXY(1, y);
- WriteLn(CRLF + 'Bitte die ZIELDISKETTE in Laufwerk ' +
- Chr(Target + 65) + ': einlegen');
- IF Source = Target THEN BEGIN
- Write('Wenn bereit, beliebige Taste drücken . . .');
- ClearBuffer;
- ch := ReadKey; WriteLn; IF ch IN [#3, #27] THEN Halt(1);
- END ELSE WriteLn;
- Versuche := 3;
- InitTab;
- REPEAT (* Test, ob die Diskette bereits formatiert ist *)
- WITH Regs DO BEGIN
- AH := $00;
- DL := Target;
- Intr($13, Regs);
- AH := $02;
- DL := Target;
- DH := 0;
- CH := 0;
- CL := 1;
- AL := 1;
- ES := Seg(BootSector);
- BX := Ofs(BootSector);
- Intr($13, Regs);
- IF AH <> 0 THEN BEGIN
- Hilfe := AH;
- AH := $00;
- DL := Target;
- Intr($13, Regs);
- AH := Hilfe;
- END;
- Dec(Versuche);
- END;
- UNTIL (Versuche = 0) OR (Regs.AH = 0);
- IF (Regs.AH <> 0) OR (BootSector.SpS <> SpS) OR
- (BootSector.Media <> Media) OR Format THEN BEGIN
- DoFormat := TRUE;
- WriteLn('Formatieren beim Schreiben . . .');
- END;
- END;
-
- PROCEDURE DiskCopy; (* Diskette wird kopiert *)
- VAR
- Counter,
- i, j, z : LONGINT;
- DoDisk,
- First : BOOLEAN;
- AktPage, k,
- Pages,
- Offset : WORD;
- DoEMS : BOOLEAN;
- AHPuffer, y : BYTE;
- BEGIN
- IF EMS THEN BEGIN
- WITH Regs DO BEGIN (* Freie EMS-Pages ermitteln *)
- AH := $42;
- Intr($67, Regs);
- Pages := BX;
- IF AH <> 0 THEN EMSError(AH);
- (* EMS Speicher allokieren - Standard Pages *)
- AH := $5A;
- AL := $00;
- BX := Pages;
- Intr($67, Regs);
- IF AH <> 0 THEN EMSError(AH);
- Handle := DX; (* Mapping sichern *)
- AH := $47;
- DX := Handle;
- Intr($67, Regs);
- IF AH <> 0 THEN EMSError(AH);
- END;
- Spuren := 65536 DIV (SpS * BpS);
- (* Wieviele Spuren passen auf den Pageframe? *)
- Offset := 0;
- Counter := 1;
- AktPage := 0;
- FOR k := 0 TO 3 DO BEGIN (* Erste 4 S. in Pageframe *)
- WITH PageBuffer[k] DO BEGIN
- Physical := k; Logical := Physical;
- END;
- WITH Regs DO BEGIN
- AH := $50;
- AL := $00;
- CX := 4;
- DX := Handle;
- DS := Seg(PageBuffer);
- SI := Ofs(PageBuffer);
- Intr($67, Regs);
- END;
- END;
- END;
- First := TRUE; DoDisk := FALSE; DoEMS := FALSE;
- IF Disk THEN BEGIN (* Temporärdatei anlegen *)
- Assign(TempFile, Temp + TempFName);
- ReWrite(TempFile, SpS * BpS);
- END;
- First := TRUE; InitTab;
- y := WhereY;
- FOR j := 0 TO Tracks - 1 DO
- FOR i := 0 TO Sides - 1 DO BEGIN
- GotoXY(1, y); Write(i, ':', j);
- IF (MemAvail > SpS * BpS + 8) AND
- (MaxAvail > SpS * BpS) THEN BEGIN
- IF First THEN BEGIN (* Speicherblockliste anlegen *)
- New(LP);
- GetMem(LP^.Element, SpS * BpS); LP^.Next := NIL;
- Top := LP; Help := LP; First := FALSE;
- END ELSE BEGIN (* ... und Liste erweitern *)
- New(LP); GetMem(LP^.Element, SpS * BpS);
- LP^.Next := NIL; Top^.Next := LP; Top := LP;
- END;
- END ELSE IF Disk THEN DoDisk := TRUE
- ELSE IF EMS THEN DoEMS := TRUE;
- Versuche := 3;
- WITH Regs DO BEGIN
- REPEAT (* Spur lesen *)
- AH := $02;
- DL := Source;
- DH := i;
- CH := j;
- CL := 1;
- AL := SpS;
- IF (NOT DoDisk) AND (NOT DoEMS) THEN BEGIN
- ES := Seg(LP^.Element^); (* Daten in der *)
- BX := Ofs(LP^.Element^); (* Liste ablegen *)
- END ELSE BEGIN
- ES := Seg(Buffer^); (* Daten im Puffer ablegen*)
- BX := Ofs(Buffer^); (* zur Übergabe an HD/EMS *)
- END;
- Intr($13, Regs);
- Dec(Versuche);
- UNTIL (AH = 0) OR (Versuche = 0);
- IF AH <> 0 THEN Error(AH);
- END;
- IF DoDisk THEN BlockWrite(TempFile, Buffer^, 1);
- IF DoEMS THEN BEGIN
- Move(Buffer^, Ptr(PageFrame, Offset)^, SpS * BpS);
- IF Counter = Spuren THEN BEGIN
- Inc(AktPage, 4);
- Offset := 0; Counter := 1;
- FOR k := 0 TO 3 DO BEGIN
- WITH PageBuffer[k] DO BEGIN
- Physical := k; Logical := k + AktPage;
- END;
- WITH Regs DO BEGIN
- AH := $50;
- AL := $00;
- CX := 4;
- DX := Handle;
- DS := Seg(PageBuffer);
- SI := Ofs(PageBuffer);
- Intr($67, Regs);
- END;
- END;
- END ELSE BEGIN
- Inc(Offset, (SpS * BpS)); Inc(Counter);
- END;
- END;
- END;
- IF Disk THEN Close(TempFile);
- REPEAT
- TestTarget(Target);
- Offset := 0; Counter := 1; AktPage := 0;
- IF EMS THEN (* Erste vier Seiten in den Pageframe *)
- FOR k := 0 TO 3 DO BEGIN
- WITH PageBuffer[k] DO BEGIN
- Physical := k; Logical := Physical;
- END;
- WITH Regs DO BEGIN
- AH := $50;
- AL := $00;
- CX := 4;
- DX := Handle;
- DS := Seg(PageBuffer);
- SI := Ofs(PageBuffer);
- Intr($67, Regs);
- END;
- END;
- IF Disk THEN BEGIN
- Assign(TempFile, Temp + TempFName);
- Reset(TempFile, SpS * BpS);
- END;
- WITH Regs DO BEGIN
- AH := $00; (* Disketten-Reset *)
- DL := Target;
- Intr($13, Regs);
- AH := $17;
- (* Diskettentyp für die Formatierung festlegen: *)
- IF (SpS = 15) AND (Tracks = 80) THEN AL := 3;
- IF (SpS = 9) AND (Tracks = 40) THEN AL := 2;
- IF (SpS = 18) AND (Tracks = 80) THEN AL := 5;
- IF (SpS = 9) AND (Tracks = 80) THEN AL := 4;
- Intr($13, Regs);
- IF AH <> 0 THEN Error(AH);
- END;
- y := WhereY; DelLine; DelLine;
- LP := Help;
- InitTab;
- FOR j := 0 TO Tracks - 1 DO
- FOR i := 0 TO Sides - 1 DO BEGIN
- GotoXY(1, y); Write(i, ':', j);
- IF DoFormat THEN BEGIN
- FOR k := 1 TO SpS DO BEGIN
- FormatBuf[k].Spur := j; FormatBuf[k].Seite := i;
- END;
- WITH Regs DO BEGIN
- Versuche := 3;
- REPEAT
- AH := $05; (* Diskette formatieren *)
- DL := Target;
- DH := i;
- CH := j;
- AL := SpS;
- ES := Seg(FormatBuf[1]);
- BX := Ofs(FormatBuf[1]);
- Intr($13, Regs);
- Dec(Versuche);
- IF AH = $03 THEN Error(AH);
- UNTIL (AH = 0) OR (Versuche = 0);
- IF AH <> 0 THEN Error(AH);
- END;
- END;
- IF LP = NIL THEN
- IF Disk THEN BlockRead(TempFile, Buffer^, 1);
- WITH Regs DO BEGIN
- Versuche := 3;
- REPEAT
- AH := $03;
- DL := Target;
- DH := i;
- CH := j;
- CL := 1;
- AL := SpS;
- IF LP = NIL THEN BEGIN (* Spur aus Speicher *)
- IF Disk THEN BEGIN (* holen *)
- ES := Seg(Buffer^);
- BX := Ofs(Buffer^);
- END ELSE BEGIN
- Move(Ptr(PageFrame, Offset)^, Buffer^,
- SpS * BpS);
- ES := Seg(Buffer^);
- BX := Ofs(Buffer^);
- END;
- END ELSE BEGIN
- ES := Seg(LP^.Element^);
- BX := Ofs(LP^.Element^);
- END;
- Intr($13, Regs);
- IF Verify THEN BEGIN
- AH := $04; (* Verify: Puffer = Disk? *)
- DL := Target;
- DH := i;
- CH := j;
- CL := 1;
- AL := SpS;
- Intr($13, Regs);
- END;
- Dec(Versuche);
- IF AH = $03 THEN Error(AH);
- IF AH <> 0 THEN InitTab;
- IF (AH <> 0) AND (Versuche = 1) THEN BEGIN
- AHPuffer := AH;
- FOR k := 1 TO SpS DO BEGIN
- FormatBuf[k].Spur := j;
- FormatBuf[k].Seite := i;
- END;
- WITH Regs DO BEGIN
- AH := $00;
- DL := Target;
- Intr($13, Regs);
- AH := $17;
- IF (SpS = 15) AND (Tracks = 80) THEN
- AL := 3;
- IF (SpS = 9) AND (Tracks = 40) THEN AL := 2;
- IF (SpS = 18) AND (Tracks = 80) THEN
- AL := 5;
- IF (SpS = 9) AND (Tracks = 80) THEN AL := 4;
- Intr($13, Regs);
- AH := $05;
- DL := Target;
- DH := i;
- CH := j;
- AL := SpS;
- ES := Seg(FormatBuf[1]);
- BX := Ofs(FormatBuf[1]);
- Intr($13, Regs);
- END;
- AH := AHPuffer;
- END;
- UNTIL (AH = 0) OR (Versuche = 0);
- IF LP <> NIL THEN LP := LP^.Next
- ELSE IF EMS THEN BEGIN
- IF Counter = Spuren THEN BEGIN
- Inc(AktPage, 4);
- Offset := 0;
- Counter := 1;
- FOR k := 0 TO 3 DO BEGIN
- WITH PageBuffer[k] DO BEGIN
- Physical := k; Logical := k + AktPage;
- END;
- WITH Regs DO BEGIN
- AH := $50;
- AL := $00;
- CX := 4;
- DX := Handle;
- DS := Seg(PageBuffer);
- SI := Ofs(PageBuffer);
- Intr($67, Regs);
- END;
- END;
- END ELSE BEGIN
- Inc(Counter); Inc(Offset, (SpS * BpS));
- END;
- END;
- IF AH <> 0 THEN Error(AH);
- END;
- END;
- IF Disk THEN Close(TempFile);
- Write(CRLF+ 'Noch eine Kopie von der Diskette (J/N)? ');
- REPEAT
- ClearBuffer; ch := UpCase(ReadKey);
- UNTIL ch IN ['J', 'Y', 'N'];
- Write(ch);
- UNTIL ch = 'N';
- END;
-
- PROCEDURE ReleaseEMS; (* EMS freigeben *)
- BEGIN
- IF EMS THEN BEGIN (* nur wenn EMS benutzt wurde *)
- EMS := FALSE; (* EMS ist leer *)
- Regs.AH := $48; (* gesich. Mapp. restaurieren *)
- Regs.DX := Handle;
- Intr($67, Regs);
- Regs.AH := $45; (* Handle freigeben *)
- Regs.DX := Handle;
- Intr($67, Regs);
- END;
- END;
-
- PROCEDURE ClearList(wo : Zeiger); (* Heap aufräumen *)
- BEGIN
- IF (wo <> NIL) AND ((SpS * BpS) > 0) THEN BEGIN
- LP := wo;
- FreeMem(LP^.Element, SpS * BpS);
- LP := LP^.Next;
- Dispose(wo);
- ClearList(LP); (* Rekursion! *)
- END;
- END;
-
- {$F+}
- PROCEDURE NewEnd;
- BEGIN
- ExitProc := OldEnd;
- ReleaseEMS; (* EMS freigeben *)
- IF Disk THEN Erase(TempFile); (* Swapdatei löschen *)
- IF Help <> NIL THEN ClearList(Help); Help := NIL;
- IF Buffer <> NIL THEN BEGIN (* Puffer löschen *)
- FreeMem(Buffer, BpS * SpS); Buffer := NIL;
- END;
- {$IFDEF VER10}
- ParamTab^ := OldTab; (* Alte Laufwerksparameter *)
- {$ELSE}
- SetIntVec($1E, OldTab); (* restaurieren *)
- {$ENDIF}
- ChDir(OldDir);
- END;
- {$F-}
-
- BEGIN (* Hauptprogramm *)
- IF Lo(DosVersion) >= 10 THEN BEGIN
- Write('This program requires DOS'); Halt(2); (* OS/2 *)
- END ELSE IF Lo(DosVersion) < 3 THEN BEGIN
- Write('Falsche DOS-Version'); Halt(2); (* DOS 2.XX *)
- END;
- OldEnd := ExitProc;
- ExitProc := @NewEnd;
- {$IFNDEF VER10}
- GetIntVec($1E, OldTab);
- ParamTab := OldTab; (* Turbo-Pascal *)
- {$ELSE}
- GetIntVec($1E, ParamTab);
- OldTab := ParamTab^; (* Quick-Pascal *)
- {$ENDIF}
- InitTab; Help := NIL; Buffer := NIL; GetDir(0, OldDir);
- Temp := GetEnv('TEMP'); (* Temporärpfad aus Environment *)
- IF Temp = '' THEN Temp := OldDir;
- FOR i := 1 TO Length(Temp) DO Temp[i] := UpCase(Temp[i]);
- ChDir(Temp);
- IF IOResult <> 0 THEN Temp := 'C:\';
- ChDir(OldDir);
- IF Temp[Length(Temp)] <> '\' THEN Temp := Temp + '\';
- IF Exist(Temp + TempFName) THEN
- DeleteFile(Temp + TempFName);
- CheckParameters;
- IF Temp[1] = '\' THEN drive := 0
- ELSE drive := Ord(Temp[1]) - 64;
- HdAvail := DiskFree(drive);
- IF ExistEMM THEN WITH Regs DO BEGIN
- AH := $40; (* EMM-Status ermitteln *)
- Intr($67, Regs);
- IF AH <> 0 THEN EMSError(AH);
- AH := $41; (* Pageframe-Segment ermitteln *)
- Intr($67, Regs);
- IF AH <> 0 THEN EMSError(AH);
- PageFrame := BX;
- END;
- REPEAT
- ClrScr; HighVideo; WriteLn(Copyright + CRLF); NormVideo;
- DiskTest(Source);
- GetMem(Buffer, SpS * BpS); (* Puffer zuweisen *)
- IF Buffer = NIL THEN BEGIN
- Write(#7 + CRLF + 'Zu wenig Speicher zur Verfügung');
- ClearBuffer;
- REPEAT UNTIL KeyPressed;
- Halt(1);
- END;
- DiskCopy;
- ReleaseEMS; ClearList(Help); (* ordentlich aufräumen *)
- Help := NIL; FreeMem(Buffer, SpS * BpS); Buffer := NIL;
- Write(CRLF + 'Eine weitere Diskette kopieren (J/N)? ');
- REPEAT
- ClearBuffer; ch := UpCase(ReadKey);
- UNTIL ch IN ['J', 'Y', 'N'];
- WriteLn(ch);
- UNTIL ch = 'N';
- END.
- (*--------------------------------------------------------*)
- (* Ende von EDD.PAS *)