home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* NOTHALT.PAS *)
- (* (c) 1990 Richard Bernheine & TOOLBOX *)
- (* ------------------------------------------------------ *)
- {$S-,R-,B-}
-
- PROGRAM Nothalt;
-
- USES Dos;
-
- CONST
- RShift = 1;
- LShift = 2;
- Ctrl = 4;
- Alt = 8;
- HotFlag = Ctrl + Alt;
- HotScan = $47;
- Hotkeyname = '<Ctrl-Alt-Home>';
- Active : BOOLEAN = FALSE;
-
- VAR
- Int09Save : POINTER;
- Interrupts : ARRAY [0..255] OF POINTER ABSOLUTE 0:0;
- SaveInterrupts : ARRAY [0..255] OF POINTER;
- Regs : Registers;
- SaveMode, B : BYTE;
-
- FUNCTION VideoMode : BYTE;
- BEGIN
- Regs.ah := 15;
- Intr($10, Regs);
- VideoMode := Regs.al;
- END;
-
- PROCEDURE SetVideoMode(mode : BYTE);
- BEGIN
- Regs.ax := mode;
- Intr($10, Regs);
- IF mode = 7 THEN Regs.cx := $0B0C
- ELSE Regs.cx := $0607;
- Regs.ah := 1;
- Intr($10, Regs);
- END;
-
- PROCEDURE SetPSP(psp : WORD);
- BEGIN
- Regs.ah := $50;
- Regs.bx := psp;
- MsDos(Regs);
- END;
-
- PROCEDURE DiskReset;
- BEGIN
- Regs.ah := 0;
- Regs.dl := $80;
- Intr($13, Regs);
- END;
-
- PROCEDURE ReleaseMemAbove;
- VAR
- MCB : WORD;
- i : BYTE;
- BEGIN
- Regs.ah := $52;
- MsDos(Regs);
- MCB := MemW[Regs.es:Regs.bx-2];
- REPEAT
- Inc(MCB, Succ(MemW[MCB:3])); { nächster MCB }
- IF (MemW[MCB:1] > PrefixSeg) THEN BEGIN
- SetPSP(MemW[MCB:1]);
- FOR i := 0 TO 19 DO BEGIN { Alle Dateien schließen }
- Regs.ah := $3E;
- Regs.bx := i;
- MsDos(Regs);
- END;
- Regs.ah := $49;
- Regs.es := Succ(MCB);
- MsDos(Regs);
- END;
- UNTIL Mem[MCB:0] = Byte('Z');
- END;
-
- PROCEDURE CLI; INLINE($FA);
-
- PROCEDURE STI; INLINE($FB);
-
- FUNCTION KeyFlag : BYTE;
- { liefert das Rom-Bios Keyboardflag }
- INLINE($B4/$02/$CD/$16);
-
- PROCEDURE BackToDos;
- VAR
- temp : BYTE;
- BEGIN
- ReleaseMemAbove;
- SetVideomode(SaveMode);
- DiskReset;
- SetPSP(PrefixSeg); { Wichtig!, andernfalls werden die }
- { Interrupts 22h-24h nicht korrekt }
- { zurückgespeichert }
- WriteLn('Speicher nach letztem NOTHALT freigegeben.');
- CLI;
- Interrupts[9] := Int09Save;
- STI;
- Regs.ax := $4C00;
- MsDos(Regs);
- END;
-
- PROCEDURE Int09; INTERRUPT;
-
- PROCEDURE ChangeStack; { Stack im Datensegment anlegen }
- INLINE($8C/$D8/$8E/$D0/$8B/$26/saveinterrupts+1024);
-
- PROCEDURE ExitOldInt09;
- { Register wieder herstellen, Stack freigeben und
- zur alten Interruptprozedur springen }
- INLINE ($A1/int09save+2/$87/$46/$10/$8B/$1E/int09save/
- $87/$5E/$0E/$5D/$07/$1F/$5F/$5E/$5A/$59/$CB);
-
- BEGIN
- CLI;
- IF (Hotflag = (keyflag AND 15)) AND
- (Port[$60] = HotScan) THEN BEGIN
- { Die folgenden Zeilen teilen der Tastatur
- mit, daß der Scancode empfangen wurde }
- b := Port[$61];
- Port[$61] := (b OR $80);
- Port[$61] := b;
- Port[$20] := $20; { EOI an Interrupt-Controller }
- IF (NOT Active) THEN BEGIN
- Active := TRUE;
- Move(SaveInterrupts,Interrupts,SizeOf(interrupts));
- ChangeStack;
- STI; { Interrupts wieder zulassen }
- BackToDos;
- END;
- END ELSE
- ExitOldInt09;
- END;
-
- BEGIN
- Savemode := Videomode;
- { Alle Interrupts zurückspeichern, die von
- Turbo verbogen wurden: (Versionsabhängig !) }
- CLI;
- Interrupts[0] := SaveInt00;
- Interrupts[$3F] := SaveInt3F;
- { Neue ISR für Interrupt 09h installieren: }
- Int09Save := Interrupts[9];
- Interrupts[9] := @int09;
- Move(Interrupts, SaveInterrupts, SizeOf(interrupts));
- STI;
- Writeln('Nothalt ist installiert.');
- Writeln('Aktivieren durch ', HotKeyName);
- { Keep mit Freigabe des Stacks und des Heaps: }
- Regs.ax := $3100;
- Regs.dx := SSeg - PrefixSeg;
- MsDos(Regs);
- END.
- (* ------------------------------------------------------ *)
- (* Ende von NOTHALT.PAS *)