home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* DISKTSR.PAS *)
- (* Ermöglicht in TSR-Prozessen ungeniert mit DOS und BIOS *)
- (* Funktionen einschl. Diskettenzugriffen zu arbeiten *)
- (* (c) 1990 E.v.Pappenheim & TOOLBOX *)
- (* ------------------------------------------------------ *)
- {$R-,S-,I-,D-,F-,V-,B-,N-}
- UNIT DiskTSR;
-
- INTERFACE
-
- USES Dos;
-
- (* Erwartet in "popup" die Adresse der aufzurufenden *)
- (* Prozedur, in "hotkey" den Tastaturcode der "heißen *)
- (* Taste *)
-
- PROCEDURE MakeResident(popup : POINTER; hotkey : WORD);
-
- IMPLEMENTATION
-
- VAR
- systemSP, (* Speichert aktuellen Stackpointer *)
- systemSS, (* Speichert aktuelles Stacksegment *)
- popupSS, (* Turbo - Stacksegment *)
- popupSP, (* Turbo - Stackpointer *)
- progseg, (* Turbo - Codesegment *)
- hotkey_,
- indosseg, (* Segment - Adresse und ... *)
- indosofs, (* Offset des InDOS - Bytes *)
- altdta, (* Offset und ... *)
- altdtas, (* Segment - Adresse der DTA *)
- altpsp : WORD; (* Adresse des PSP *)
- currint16,
- popup_,
- int16save,
- int1Bsave,
- int13save,
- int21save : POINTER;
- request,
- aktiv,
- biosdiskaktiv : BOOLEAN;
- regs : Registers;
-
- (* Neuer Disk Transfer Block *)
- DiskBuffer : ARRAY [0..63] OF WORD;
-
- (* Ruft im FAR-Modell kompilierte Prozedur auf *)
-
- PROCEDURE CallPopup_;
- INLINE ($FF/$1E/popup_); (* call far popup_ *)
-
- (* Schaltet auf den Popup-Programm Stack um *)
-
- PROCEDURE SwitchStack;
- INLINE ($8C/$16/systemSS/$89/$26/systemSP/$FA/
- $8E/$16/popupSS/$8B/$26/popupSP/$FB);
-
- (* Schaltet zurück *)
-
- PROCEDURE SwitchBack;
- INLINE ($FA/$8E/$16/systemSS/$8B/$26/systemSP/$FB);
-
- (* Prüft das InDosByte auf Aktivität einer *)
- (* DOS-Funktion *)
-
- FUNCTION InDos : BOOLEAN;
- BEGIN
- InDos := (Mem[InDosSeg:InDosOfs] <> 0);
- END;
-
- (* Sichert Program Segment Prefix und Disc Transfer *)
- (* Address und setzt sie auf eigene Puffer *)
-
- PROCEDURE SaveDiskBuf;
- BEGIN
- WITH Regs DO BEGIN
- ax := $2F00; (* Get DTA *)
- MsDos(Regs);
- AltDTA := bx;
- AltDTAS := es;
- ax := $6200; (* Get PSP *)
- MsDos(Regs);
- AltPSP := bx;
- ax := $1a00; (* Set DTA *)
- ds := DSeg;
- dx := Ofs(DiskBuffer);
- MsDos(Regs);
- ax := $5000; (* Set PSP *)
- bx := ProgSeg;
- MsDos(Regs);
- END;
- END;
-
- (* Macht die o.g. Änderungen wieder rückgängig *)
-
- PROCEDURE RestoreDiskBuf;
- VAR
- Regs : Registers;
- BEGIN
- WITH Regs DO BEGIN
- ax := $1a00;
- ds := AltDTAS;
- dx := AltDTA;
- MsDos(Regs);
- ax := $5000;
- bx := AltPSP;
- MsDos(Regs);
- END;
- END;
-
- (* Veranlaßt Umschalten auf eigenen Puffer und Stack *)
- (* setzt alten Int. $16, ruft das Popup-Programm und *)
- (* schaltet wieder zurück *)
-
- PROCEDURE CallPopUp;
- BEGIN
- request := FALSE;
- aktiv := TRUE;
- SaveDiskBuf;
- GetIntVec($16, currint16);
- SetIntVec($16, Int16Save);
- CallPopUp_;
- SetIntVec($16, currint16);
- RestoreDiskBuf;
- aktiv := FALSE;
- END;
-
- (* Der Typ intregisters und die Prozedur "chainint" *)
- (* stammen aus dem Resident-Manager von *)
- (* Karsten Ginselmann (TOOLBOX 12'88) *)
-
- {$F+}
- TYPE
- intregisters = RECORD
- CASE BYTE OF
- 1 : (bp, es, ds, di, si, dx, cx, bx,
- ax, ip, cs, flags : WORD);
- 2 : (dummy : ARRAY [1..5] OF WORD;
- dl, dh, cl, ch, bl,
- bh, al, ah : BYTE);
- END;
-
- PROCEDURE chainint(Regs : intregisters;
- address : pointer);
- INLINE($5b/ { POP BX }
- $58/ { POP AX }
- $5e/ { POP SI }
- $1f/ { POP DS }
- $87/$5c/$0e/ { XCHG BX,[SI+0E] }
- $87/$44/$10/ { XCHG AX,[SI+10] }
- $8b/$54/$16/ { MOV DX,[SI+16] }
- $52/ { PUSH DX }
- $9d/ { POPF }
- $8c/$da/ { MOV DX,DS }
- $fa/ { CLI }
- $8e/$d2/ { MOV SS,DX }
- $89/$f4/ { MOV SP,SI }
- $fb/ { STI }
- $5d/ { POP BP }
- $07/ { POP ES }
- $1f/ { POP DS }
- $5f/ { POP DI }
- $5e/ { POP SI }
- $5a/ { POP DX }
- $59/ { POP CX }
- $cb); { RETF }
-
- (* Die Prozedur Int13 wird vor den Biosinterrupt für *)
- (* die Disketten-/Festplatten-Routinen geschaltet und *)
- (* sorgt über den Schalter biosdiskaktiv dafür, daß das *)
- (* TSR-Programm in keine Plattenzugriffe hineinpfuscht *)
-
- PROCEDURE int13(flags, cs, ip, ax, bx, cx, dx,
- si, di, ds, es, bp : WORD);
- INTERRUPT;
- BEGIN
- biosdiskaktiv := TRUE;
- INLINE($8b/$46/$10/ (* MOV AX,[BP+10] (ax) *)
- $9c/ (* PUSHF *)
- $ff/$1e/int13save/ (* CALL FAR int13save *)
- $89/$46/$10/ (* MOV [BP+10],AX *)
- $9c/ (* PUSHF *)
- $58/ (* POP AX *)
- $89/$46/$16); (* MOV [BP+16], ax (flags)*)
- biosdiskaktiv := FALSE;
- END;
-
- (* Int21 sorgt dafür, daß das TSR - Programm nur aufge- *)
- (* rufen wird, BEVOR eine (nicht reentrante) DOS-Funk- *)
- (* tion in Aktion tritt *)
-
- PROCEDURE int21(bp : WORD); INTERRUPT;
- VAR
- Regs : intregisters ABSOLUTE bp;
- BEGIN
- IF Request AND (NOT aktiv) THEN BEGIN
- SwitchStack;
- CallPopUp;
- SwitchBack;
- END;
- ChainInt(Regs, int21save);
- END;
-
- (* Siehe Pascal u.a. 5/88 *)
- (* Lauert auf den Hotkey ... *)
-
- FUNCTION KeyFromOldInt16 : WORD;
- INLINE ($31/$C0/$9C/$FF/$1E/int16save);
-
- PROCEDURE int16(flags, cs, ip, ax, bx, cx, dx,
- si, di, ds, es, bp : WORD);
- INTERRUPT;
-
- PROCEDURE ExitOldInt16;
- INLINE($A1/int16save+2/$87/$46/$10/$8B/$1E/int16save/
- $87/$5E/$0E/$5D/$07/$1F/$5F/$5E/$5A/$59/$CB);
-
- BEGIN
- IF Request AND (NOT InDos) AND (NOT Aktiv) THEN BEGIN
- SwitchStack;
- CallPopUp;
- SwitchBack;
- END;
- IF (Hi(ax) = 0) THEN BEGIN
- ax := KeyFromOldInt16;
- IF ax = Hotkey_ THEN Request := TRUE;
- END ELSE
- ExitOldInt16;
- END;
- {$F-}
-
- PROCEDURE MakeResident(PopUp : POINTER; HotKey : WORD);
- BEGIN
- popup_ := popup;
- hotkey_ := hotkey;
- GetIntVec($16, int16save); (* Tastatur Interrupt *)
- GetIntVec($21, int21save); (* DOS - Interrupt *)
- GetIntVec($13, int13save); (* Disketten - Interrupt *)
- SetIntVec($13, @int13);
- SetIntVec($16, @int16);
- SetIntVec($21, @int21);
- SetIntVec($1B, int1bsave); (* Control - Break *)
- {$IFDEF VER50} (* Wenn Version 5.0 dann *)
- SwapVectors; (* Turbo - Vectoren *)
- {$ENDIF} (* zurücksetzen *)
- Keep(0) (* Resident machen *)
- END;
-
- BEGIN
- Request := FALSE;
- aktiv := FALSE;
- Regs.ax := $3400; (* Get InDosByte - Address *)
- MsDos(Regs);
- InDosSeg := Regs.es;
- InDosOfs := Regs.bx;
- Regs.ax := $6200; (* Get PSP - Address *)
- MsDos(Regs);
- ProgSeg := Regs.bx;
- PopupSS := SSeg; (* Programm - Stacksegment *)
- PopupSP := SPtr+4; (* und Offset sichern *)
- GetIntVec($1B, int1bsave);
- END.
- (* ------------------------------------------------------ *)
- (* Ende von DISKTSR.PAS *)