home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 04 / tricks / disktsr.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-01-12  |  8.8 KB  |  266 lines

  1. (* ------------------------------------------------------ *)
  2. (*                     DISKTSR.PAS                        *)
  3. (* Ermöglicht in TSR-Prozessen ungeniert mit DOS und BIOS *)
  4. (* Funktionen einschl. Diskettenzugriffen zu arbeiten     *)
  5. (*         (c) 1990 E.v.Pappenheim  &  TOOLBOX            *)
  6. (* ------------------------------------------------------ *)
  7. {$R-,S-,I-,D-,F-,V-,B-,N-}
  8. UNIT DiskTSR;
  9.  
  10. INTERFACE
  11.  
  12. USES Dos;
  13.  
  14.   (* Erwartet in "popup" die Adresse der aufzurufenden    *)
  15.   (* Prozedur, in "hotkey" den Tastaturcode der "heißen   *)
  16.   (* Taste                                                *)
  17.  
  18.   PROCEDURE MakeResident(popup : POINTER; hotkey : WORD);
  19.  
  20. IMPLEMENTATION
  21.  
  22. VAR
  23.   systemSP,          (* Speichert aktuellen Stackpointer  *)
  24.   systemSS,          (* Speichert aktuelles Stacksegment  *)
  25.   popupSS,           (* Turbo - Stacksegment              *)
  26.   popupSP,           (* Turbo - Stackpointer              *)
  27.   progseg,           (* Turbo - Codesegment               *)
  28.   hotkey_,
  29.   indosseg,          (* Segment - Adresse und ...         *)
  30.   indosofs,          (* Offset des InDOS - Bytes          *)
  31.   altdta,            (* Offset und ...                    *)
  32.   altdtas,           (* Segment - Adresse der DTA         *)
  33.   altpsp     : WORD; (* Adresse des PSP                   *)
  34.   currint16,
  35.   popup_,
  36.   int16save,
  37.   int1Bsave,
  38.   int13save,
  39.   int21save     : POINTER;
  40.   request,
  41.   aktiv,
  42.   biosdiskaktiv : BOOLEAN;
  43.   regs          : Registers;
  44.  
  45.                      (* Neuer Disk Transfer Block         *)
  46.   DiskBuffer    : ARRAY [0..63] OF WORD;
  47.  
  48.            (* Ruft im FAR-Modell kompilierte Prozedur auf *)
  49.  
  50.   PROCEDURE CallPopup_;
  51.   INLINE ($FF/$1E/popup_);         (* call far popup_     *)
  52.  
  53.            (* Schaltet auf den Popup-Programm Stack um    *)
  54.  
  55.   PROCEDURE SwitchStack;
  56.   INLINE ($8C/$16/systemSS/$89/$26/systemSP/$FA/
  57.           $8E/$16/popupSS/$8B/$26/popupSP/$FB);
  58.  
  59.            (* Schaltet zurück                             *)
  60.  
  61.   PROCEDURE SwitchBack;
  62.   INLINE ($FA/$8E/$16/systemSS/$8B/$26/systemSP/$FB);
  63.  
  64.            (* Prüft das InDosByte auf Aktivität einer     *)
  65.            (* DOS-Funktion                                *)
  66.  
  67.   FUNCTION InDos : BOOLEAN;
  68.   BEGIN
  69.     InDos := (Mem[InDosSeg:InDosOfs] <> 0);
  70.   END;
  71.  
  72.   (* Sichert Program Segment Prefix und Disc Transfer     *)
  73.   (* Address und setzt sie auf eigene Puffer              *)
  74.  
  75.   PROCEDURE SaveDiskBuf;
  76.   BEGIN
  77.     WITH Regs DO BEGIN
  78.       ax      := $2F00;                       (* Get DTA  *)
  79.       MsDos(Regs);
  80.       AltDTA  := bx;
  81.       AltDTAS := es;
  82.       ax      := $6200;                       (* Get PSP  *)
  83.       MsDos(Regs);
  84.       AltPSP  := bx;
  85.       ax      := $1a00;                       (* Set DTA  *)
  86.       ds      := DSeg;
  87.       dx      := Ofs(DiskBuffer);
  88.       MsDos(Regs);
  89.       ax      := $5000;                       (* Set PSP  *)
  90.       bx      := ProgSeg;
  91.       MsDos(Regs);
  92.     END;
  93.   END;
  94.  
  95.   (* Macht die o.g. Änderungen wieder rückgängig          *)
  96.  
  97.   PROCEDURE RestoreDiskBuf;
  98.   VAR
  99.     Regs : Registers;
  100.   BEGIN
  101.     WITH Regs DO BEGIN
  102.       ax := $1a00;
  103.       ds := AltDTAS;
  104.       dx := AltDTA;
  105.       MsDos(Regs);
  106.       ax := $5000;
  107.       bx := AltPSP;
  108.       MsDos(Regs);
  109.     END;
  110.   END;
  111.  
  112.   (* Veranlaßt Umschalten auf eigenen Puffer und Stack    *)
  113.   (* setzt alten Int. $16, ruft das Popup-Programm und    *)
  114.   (* schaltet wieder zurück                               *)
  115.  
  116.   PROCEDURE CallPopUp;
  117.   BEGIN
  118.     request := FALSE;
  119.     aktiv := TRUE;
  120.     SaveDiskBuf;
  121.     GetIntVec($16, currint16);
  122.     SetIntVec($16, Int16Save);
  123.     CallPopUp_;
  124.     SetIntVec($16, currint16);
  125.     RestoreDiskBuf;
  126.     aktiv := FALSE;
  127.   END;
  128.  
  129.   (* Der Typ intregisters und die Prozedur "chainint"     *)
  130.   (* stammen aus dem Resident-Manager von                 *)
  131.   (* Karsten Ginselmann (TOOLBOX 12'88)                   *)
  132.  
  133. {$F+}
  134. TYPE
  135.   intregisters = RECORD
  136.                    CASE BYTE OF
  137.                      1 : (bp, es, ds, di, si, dx, cx, bx,
  138.                           ax, ip, cs, flags : WORD);
  139.                      2 : (dummy : ARRAY [1..5] OF WORD;
  140.                           dl, dh, cl, ch, bl,
  141.                           bh, al, ah        : BYTE);
  142.                  END;
  143.  
  144.   PROCEDURE chainint(Regs    : intregisters;
  145.                      address : pointer);
  146.   INLINE($5b/                    { POP  BX         }
  147.        $58/                      { POP  AX         }
  148.        $5e/                      { POP  SI         }
  149.        $1f/                      { POP  DS         }
  150.        $87/$5c/$0e/              { XCHG BX,[SI+0E] }
  151.        $87/$44/$10/              { XCHG AX,[SI+10] }
  152.        $8b/$54/$16/              { MOV  DX,[SI+16] }
  153.        $52/                      { PUSH DX         }
  154.        $9d/                      { POPF            }
  155.        $8c/$da/                  { MOV  DX,DS      }
  156.        $fa/                      { CLI             }
  157.        $8e/$d2/                  { MOV  SS,DX      }
  158.        $89/$f4/                  { MOV  SP,SI      }
  159.        $fb/                      { STI             }
  160.        $5d/                      { POP  BP         }
  161.        $07/                      { POP  ES         }
  162.        $1f/                      { POP  DS         }
  163.        $5f/                      { POP  DI         }
  164.        $5e/                      { POP  SI         }
  165.        $5a/                      { POP  DX         }
  166.        $59/                      { POP  CX         }
  167.        $cb);                     { RETF            }
  168.  
  169.   (* Die Prozedur Int13 wird vor den Biosinterrupt für    *)
  170.   (* die Disketten-/Festplatten-Routinen geschaltet und   *)
  171.   (* sorgt über den Schalter biosdiskaktiv dafür, daß das *)
  172.   (* TSR-Programm in keine Plattenzugriffe hineinpfuscht  *)
  173.  
  174.   PROCEDURE int13(flags, cs, ip, ax, bx, cx, dx,
  175.                              si, di, ds, es, bp : WORD);
  176.   INTERRUPT;
  177.   BEGIN
  178.     biosdiskaktiv := TRUE;
  179.     INLINE($8b/$46/$10/         (* MOV  AX,[BP+10]  (ax)  *)
  180.            $9c/                 (* PUSHF                  *)
  181.            $ff/$1e/int13save/   (* CALL FAR int13save     *)
  182.            $89/$46/$10/         (* MOV  [BP+10],AX        *)
  183.            $9c/                 (* PUSHF                  *)
  184.            $58/                 (* POP  AX                *)
  185.            $89/$46/$16);        (* MOV [BP+16], ax (flags)*)
  186.      biosdiskaktiv := FALSE;
  187.   END;
  188.  
  189.   (* Int21 sorgt dafür, daß das TSR - Programm nur aufge- *)
  190.   (* rufen wird, BEVOR eine (nicht reentrante) DOS-Funk-  *)
  191.   (* tion in Aktion tritt                                 *)
  192.  
  193.   PROCEDURE int21(bp : WORD); INTERRUPT;
  194.   VAR
  195.     Regs : intregisters ABSOLUTE bp;
  196.   BEGIN
  197.     IF Request AND (NOT aktiv) THEN BEGIN
  198.       SwitchStack;
  199.       CallPopUp;
  200.       SwitchBack;
  201.     END;
  202.     ChainInt(Regs, int21save);
  203.   END;
  204.  
  205.   (* Siehe Pascal u.a. 5/88                               *)
  206.   (* Lauert auf den Hotkey ...                            *)
  207.  
  208.   FUNCTION KeyFromOldInt16 : WORD;
  209.   INLINE ($31/$C0/$9C/$FF/$1E/int16save);
  210.  
  211.   PROCEDURE int16(flags, cs, ip, ax, bx, cx, dx,
  212.                                  si, di, ds, es, bp : WORD);
  213.   INTERRUPT;
  214.  
  215.     PROCEDURE ExitOldInt16;
  216.     INLINE($A1/int16save+2/$87/$46/$10/$8B/$1E/int16save/
  217.            $87/$5E/$0E/$5D/$07/$1F/$5F/$5E/$5A/$59/$CB);
  218.  
  219.      BEGIN
  220.        IF Request AND (NOT InDos) AND (NOT Aktiv) THEN BEGIN
  221.          SwitchStack;
  222.          CallPopUp;
  223.          SwitchBack;
  224.        END;
  225.        IF (Hi(ax) = 0) THEN BEGIN
  226.          ax := KeyFromOldInt16;
  227.          IF ax = Hotkey_ THEN Request := TRUE;
  228.        END ELSE
  229.          ExitOldInt16;
  230.   END;
  231. {$F-}
  232.  
  233.   PROCEDURE MakeResident(PopUp : POINTER; HotKey : WORD);
  234.   BEGIN
  235.     popup_ := popup;
  236.     hotkey_ := hotkey;
  237.     GetIntVec($16, int16save);  (* Tastatur Interrupt     *)
  238.     GetIntVec($21, int21save);  (* DOS - Interrupt        *)
  239.     GetIntVec($13, int13save);  (* Disketten - Interrupt  *)
  240.     SetIntVec($13, @int13);
  241.     SetIntVec($16, @int16);
  242.     SetIntVec($21, @int21);
  243.     SetIntVec($1B, int1bsave);  (* Control - Break        *)
  244.     {$IFDEF VER50}              (* Wenn Version 5.0 dann  *)
  245.     SwapVectors;                (* Turbo - Vectoren       *)
  246.     {$ENDIF}                    (* zurücksetzen           *)
  247.     Keep(0)                     (* Resident machen        *)
  248.   END;
  249.  
  250. BEGIN
  251.   Request  := FALSE;
  252.   aktiv    := FALSE;
  253.   Regs.ax  := $3400;           (* Get InDosByte - Address *)
  254.   MsDos(Regs);
  255.   InDosSeg := Regs.es;
  256.   InDosOfs := Regs.bx;
  257.   Regs.ax  := $6200;           (* Get PSP - Address       *)
  258.   MsDos(Regs);
  259.   ProgSeg  := Regs.bx;
  260.   PopupSS  := SSeg;            (* Programm - Stacksegment *)
  261.   PopupSP  := SPtr+4;          (* und Offset sichern      *)
  262.   GetIntVec($1B, int1bsave);
  263. END.
  264. (* ------------------------------------------------------ *)
  265. (*                Ende von DISKTSR.PAS                    *)
  266.