home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
1991
/
05
/
ldm
/
edd.pas
< prev
Wrap
Pascal/Delphi Source File
|
1991-02-25
|
26KB
|
815 lines
(*--------------------------------------------------------*)
(* 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 *)