home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 05 / tricks / nothalt.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1990-02-12  |  4.2 KB  |  162 lines

  1. (* ------------------------------------------------------ *)
  2. (*                    NOTHALT.PAS                         *)
  3. (*        (c) 1990 Richard Bernheine & TOOLBOX            *)
  4. (* ------------------------------------------------------ *)
  5. {$S-,R-,B-}
  6.  
  7. PROGRAM Nothalt;
  8.  
  9. USES Dos;
  10.  
  11. CONST
  12.   RShift     = 1;
  13.   LShift     = 2;
  14.   Ctrl       = 4;
  15.   Alt        = 8;
  16.   HotFlag    = Ctrl + Alt;
  17.   HotScan    = $47;
  18.   Hotkeyname = '<Ctrl-Alt-Home>';
  19.   Active     : BOOLEAN = FALSE;
  20.  
  21. VAR
  22.   Int09Save      : POINTER;
  23.   Interrupts     : ARRAY [0..255] OF POINTER ABSOLUTE 0:0;
  24.   SaveInterrupts : ARRAY [0..255] OF POINTER;
  25.   Regs           : Registers;
  26.   SaveMode, B    : BYTE;
  27.  
  28.   FUNCTION VideoMode : BYTE;
  29.   BEGIN
  30.     Regs.ah := 15;
  31.     Intr($10, Regs);
  32.     VideoMode := Regs.al;
  33.   END;
  34.  
  35.   PROCEDURE SetVideoMode(mode : BYTE);
  36.   BEGIN
  37.     Regs.ax := mode;
  38.     Intr($10, Regs);
  39.     IF mode = 7 THEN Regs.cx := $0B0C
  40.                 ELSE Regs.cx := $0607;
  41.     Regs.ah := 1;
  42.     Intr($10, Regs);
  43.   END;
  44.  
  45.   PROCEDURE SetPSP(psp : WORD);
  46.   BEGIN
  47.     Regs.ah := $50;
  48.     Regs.bx := psp;
  49.     MsDos(Regs);
  50.   END;
  51.  
  52.   PROCEDURE DiskReset;
  53.   BEGIN
  54.     Regs.ah := 0;
  55.     Regs.dl := $80;
  56.     Intr($13, Regs);
  57.   END;
  58.  
  59.   PROCEDURE ReleaseMemAbove;
  60.   VAR
  61.     MCB : WORD;
  62.     i   : BYTE;
  63.   BEGIN
  64.     Regs.ah := $52;
  65.     MsDos(Regs);
  66.     MCB := MemW[Regs.es:Regs.bx-2];
  67.     REPEAT
  68.       Inc(MCB, Succ(MemW[MCB:3]));          { nächster MCB }
  69.       IF (MemW[MCB:1] > PrefixSeg) THEN BEGIN
  70.         SetPSP(MemW[MCB:1]);
  71.         FOR i := 0 TO 19 DO BEGIN { Alle Dateien schließen }
  72.           Regs.ah := $3E;
  73.           Regs.bx := i;
  74.           MsDos(Regs);
  75.         END;
  76.         Regs.ah := $49;
  77.         Regs.es := Succ(MCB);
  78.         MsDos(Regs);
  79.       END;
  80.     UNTIL Mem[MCB:0] = Byte('Z');
  81.   END;
  82.  
  83.   PROCEDURE CLI; INLINE($FA);
  84.  
  85.   PROCEDURE STI; INLINE($FB);
  86.  
  87.   FUNCTION KeyFlag : BYTE;
  88.                        { liefert das Rom-Bios Keyboardflag }
  89.   INLINE($B4/$02/$CD/$16);
  90.  
  91.   PROCEDURE BackToDos;
  92.   VAR
  93.     temp : BYTE;
  94.   BEGIN
  95.     ReleaseMemAbove;
  96.     SetVideomode(SaveMode);
  97.     DiskReset;
  98.     SetPSP(PrefixSeg);  { Wichtig!, andernfalls werden die }
  99.                         { Interrupts 22h-24h nicht korrekt }
  100.                         { zurückgespeichert                }
  101.     WriteLn('Speicher nach letztem NOTHALT freigegeben.');
  102.     CLI;
  103.     Interrupts[9] := Int09Save;
  104.     STI;
  105.     Regs.ax := $4C00;
  106.     MsDos(Regs);
  107.   END;
  108.  
  109.   PROCEDURE Int09; INTERRUPT;
  110.  
  111.     PROCEDURE ChangeStack; { Stack im Datensegment anlegen }
  112.     INLINE($8C/$D8/$8E/$D0/$8B/$26/saveinterrupts+1024);
  113.  
  114.     PROCEDURE ExitOldInt09;
  115.     { Register wieder herstellen, Stack freigeben und
  116.       zur alten Interruptprozedur springen }
  117.     INLINE ($A1/int09save+2/$87/$46/$10/$8B/$1E/int09save/
  118.             $87/$5E/$0E/$5D/$07/$1F/$5F/$5E/$5A/$59/$CB);
  119.  
  120.   BEGIN
  121.     CLI;
  122.     IF (Hotflag = (keyflag AND 15)) AND
  123.        (Port[$60] = HotScan) THEN BEGIN
  124.        { Die folgenden Zeilen teilen der Tastatur
  125.          mit, daß der Scancode empfangen wurde  }
  126.       b := Port[$61];
  127.       Port[$61] := (b OR $80);
  128.       Port[$61] := b;
  129.       Port[$20] := $20;      { EOI an Interrupt-Controller }
  130.       IF (NOT Active) THEN BEGIN
  131.         Active := TRUE;
  132.         Move(SaveInterrupts,Interrupts,SizeOf(interrupts));
  133.         ChangeStack;
  134.         STI;                  { Interrupts wieder zulassen }
  135.         BackToDos;
  136.       END;
  137.     END ELSE
  138.       ExitOldInt09;
  139.   END;
  140.  
  141. BEGIN
  142.   Savemode := Videomode;
  143.                 { Alle Interrupts zurückspeichern, die von
  144.                Turbo verbogen wurden: (Versionsabhängig !) }
  145.   CLI;
  146.   Interrupts[0]   := SaveInt00;
  147.   Interrupts[$3F] := SaveInt3F;
  148.                 { Neue ISR für Interrupt 09h installieren: }
  149.   Int09Save       := Interrupts[9];
  150.   Interrupts[9]   := @int09;
  151.   Move(Interrupts, SaveInterrupts, SizeOf(interrupts));
  152.   STI;
  153.   Writeln('Nothalt ist installiert.');
  154.   Writeln('Aktivieren durch ', HotKeyName);
  155.              { Keep mit Freigabe des Stacks und des Heaps: }
  156.   Regs.ax := $3100;
  157.   Regs.dx := SSeg - PrefixSeg;
  158.   MsDos(Regs);
  159. END.
  160. (* ------------------------------------------------------ *)
  161. (*                Ende von NOTHALT.PAS                    *)
  162.