[Back to TSR SWAG index] [Back to Main SWAG index] [Original]

    {
    CHRIS PRIEDE

    > Can anyone give me any samples of TSR routines?

        My old example of a generic keyboard TSR has mysteriously
    disappeared, so I had to write a new one. This is as simple TSR as it
    can be: no stack switching, no DOS reentrancy check. In the form
    presented here it simply beeps when you press Shift-Esc. Set your own
    hotkey and rewrite TsrMain to turn it into something useful.

        Use Crt unit for screen writes and don't try to access files. Since
    it uses foreground program's stack, you shouldn't use deeply nested or
    recursive function calls, or declare large local variables. This is more
    on demo side, but will get you started.
    }

    program GenericKeyboardTSR;
    {$M 0, 0, 512}      { reduce memory size }
    {$S-,R-}         { can't use stack or range checking in TSR }

    uses
      Dos, Crt;

    Const
      RtShift       = $01;
      LtShift       = $02;
      AnyShift      = RtShift + LtShift;
      Ctrl          = $04;
      Alt           = $08;

      HotKey        = $01;      { Hotkey scan code, Esc }
      HotShiftState = AnyShift; { Hotkey shift state }
      FakeFlags     = 0;        { Fake flags for interrupt call }

    type
      IntProc = procedure(Flags : word);

    var
      OldInt09 : IntProc;
      Popped   : boolean;

    procedure Enable; Inline($FB);      { inline macro -- STI }

    procedure TsrMain;      { TSR main procedure, executed on hotkey }
    begin
      Sound(400);           { Make noise (replace with something useful) }
      Delay(100);
      NoSound;
    end;

    procedure NewInt09; interrupt;
    begin
      Enable;               { Allow other interrupts }
      if (not Popped) and (Port[$60] = HotKey) and  { if not in TSR already }
         (Mem[$40 : $17] and $0F = HotShiftState) then { and hotkey detected }
      begin
        Popped := true;     { set Popped to avoid re-entry }
        Port[$61] := Port[$61] or $80;      { reset keyboard }
        Port[$61] := Port[$61] and not $80;
        Port[$20] := $20;   { signal end of interrupt }
        TsrMain;            { run TSR main procedure }
        Popped := false;    { clear Popped and return }
      end
      else
        OldInt09(FakeFlags); { call old handler }
    end;

    begin           { installation }
      Popped := false;
      GetIntVec($09, pointer(@OldInt09)); { Install int. handler}
      SetIntVec($09, @NewInt09);
      Keep(0);    { stay resident }
    end.

[Back to TSR SWAG index] [Back to Main SWAG index] [Original]