home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / turbopas / stay42.arc / CLKRES.430 < prev    next >
Text File  |  1986-08-14  |  26KB  |  516 lines

  1. {$R+}
  2. {$C-}
  3. {-----------------------------------------------------------------------------}
  4. {         "  Look, Dave, I know you're trying to be helpful. But              }
  5. {           the fault is either in the ... system - or in YOUR                }
  6. {           test procedures.  My information processing is perfectly          }
  7. {           normal. "                                                         }
  8. {                                        Arthur C. Clark  -  " 2001 "         }
  9. {-----------------------------------------------------------------------------}
  10. { Stayres Version 4.15 }
  11. {
  12.   Copyright (C) LaneFerris 1985,1986.
  13.   Distributed to the Public Domain for use without Profit.
  14.  
  15.   A  Turbo  "stay-resident" program clobbers the Dos register stack.  It
  16.   jumps over the Turbo run-time initialization code that would set up the
  17.   program registers  and environment.   Secondly,  a  Turbo TSR (Terminate
  18.   and stay-resident) could not ordinarily issue file I/O since that would
  19.   clobber Dos interrupt registers.
  20.  
  21.   Therefore,  the following code proposes an inline solution, recovering the
  22.   Turbo entry  stack  for  "stay-resident" programs  and allowing those
  23.   programs to issue Dos I/O and other interrupts.
  24.  
  25.   This Turbo stay-resident demo has been put together to perform both Dos I/O
  26.   and Bios interrupts. It has been tested for re-entrancy and recursiveness
  27.   on an IBM PC with PCDOS 2.0, 2.1, 3.0, 3.1 .
  28.  
  29.   R_U_N   I_N_S_T_R_U_C_T_I_O_N_S
  30.   Separate the include files, compile to a COM file using STAYRES.420 (or the
  31.   current release level) as the  Main file. Then execute the command file
  32.   from the DOS prompt.
  33.  
  34.   Use the Turbo Compiler Options window to set the Maximum free dynamic
  35.   memory  between 300-400 paragraphs. If you get $FF runtine errors or
  36.   "allocation error", "cannot load Command.Com", then adjust the mAximum free
  37.   value to something reasonable but less than your maximum memory (minus
  38.   20K). This program can ONLY run as a COM file.
  39.  
  40.    Activate with the default hotkey (Alt-F9).  Stayres will also free its
  41.    memory and return to Dos with the Cntl-F9 key at the last "Press a key"
  42.    prompt (Illustrated in the Stayxit routine).
  43.  
  44.  
  45.                       The Hunter's Helper
  46.  
  47.                       Lane Ferris
  48.                       4268 26th St
  49.                       San Francisco,Ca. 94131
  50.                       Compuserv 70357,2716
  51.  
  52.  If you find this program useful, $15 will aid in its evolution and upkeep.
  53.  
  54. }
  55. { Authors: Lane  Ferris   (Stay Resident/Exit Code)         }
  56. {          Neil J. Rubenking (Directory code and ideas)     }
  57. {          Karson W. Morrison (Stay Resident modifications) }
  58. {          Lynn A. Canning (Window coding revisions)        }
  59. {          Bela Lubkin (INT24 processing)                   }
  60. {          Other Public Gurus on whose shoulders we stand.  }
  61. {
  62.  PURPOSE:
  63.        This code will serve as a template to create other "Stay  Resident"
  64.        programs  in  Turbo  Pascal(tm).   This  code  intercepts  Int  16,
  65.        (or INT 9) displacing the original Interrupt Vector  to a Turbo inline
  66.        service procedure. During  execution  of  other  programs,  it  can be
  67.        invoked by the special key combination  specified  by  "Our_HotKey"
  68.        (in  this  case Alt-F9.) }
  69.  
  70. {
  71.  Modifications:
  72.           7.85 - Replace Windows with a more simple form/less code.
  73.                     Replace Window Array with Pointers/Heap form.
  74.                     Re-issue termination Keyboard Read / pass back to user
  75.                     Would like to back up Instruction Ptr by two bytes before
  76.                     the Int 16 ($CD16) but it might be a "long call" by
  77.                     some other Kbd interceptor (chirp chirp chrip)... and
  78.                     thats "trouble in River City".
  79.                     Clean up RmWin "incorrect" attribute bugs. If screen
  80.                     isnt cleared, we get border attribute, not text attrb.
  81.                     Remove last window at Termination Time (Ctrl-Home).
  82.           8.85 - Version 3.10 Changes
  83.                     1) Save 40 words in StaySave/Rstr to avoid clobbering
  84.                        Dos Stack when entering Dos with Turbo Write(ln) caused
  85.                        by Int 21 Function 5  (Writln(Lst,..)) which re-issues
  86.                        Int 16.
  87.                     2) Change Int 68 to Int 67 to Avoid collisions with
  88.                        Dos 3.1 on an AT.
  89.                     3) Correct "Press a Key..." to accept any "Key..."
  90.                        (not just Cr).
  91.                     4) Check Int16 function. Jmp directly to Int16 if not
  92.                        a character request. Avoids 40 word Save/Restore
  93.                        overhead.
  94.           9.85 - Version 3.20 changes
  95.                     When returning to user program, pass back a fake
  96.                     "Ctrl-key" scan code to allow immediate re-execution
  97.                     of the TSR (Terminate Stay Resident) program. Also
  98.                     solves SideKick incessant bird caws.
  99.           9.85 - Version 3.2C
  100.                     When saving/restoring the stack, save 40 words or less
  101.                     depending on stack size (0-Sp = stack size) to avoid
  102.                     overflowing into SS:0 when stack is less than 40 words.
  103.                     Put back the "wait for user key logic" at Demo end.
  104.                     Beep like SuperKick if Key is OurKey
  105.           9.85 - Version 3.31
  106.                     Futz around with the "wait for user key logic", allow
  107.                     the Our_key to pass, but beep user to show we aint
  108.                     gonna activate, cuz our InUse bit is still set.
  109.                     Clean up the documentation and duplicate instructions in
  110.                     StaySave/Rstr.
  111.                     Change Int67 to Int60 for Fun and Profit and get around
  112.                     Mark Stanock's use of those locations.
  113.           9.85 - Version 3.32
  114.                     Changes made by Karson W. Morrison
  115.                     Modified the STAYRES.331 version to remove all coding
  116.                     that was not necessary for the stayres routines.
  117.                     The coding associated with the demo was put into
  118.                     seperate include files.  The coding for a revised windo.inc
  119.                     file was placed into the stayres program.  The windo
  120.                     routines were changed to allow background and forground
  121.                     colors and to allow borders of one line, two lines, or
  122.                     no lines.  Read the doc info. in the windo.inc file.
  123.                     Revisions for the windo.inc file were made by
  124.                     Lynn A. Canning.  The windo routine will now allow a
  125.                     window of 1,1,80,25.
  126.          10.85 - Version 3.33     l.ferris
  127.                     Correct inverted parameters in Stay Windo include file
  128.                     Delete unused variables and code in demo code.
  129.                     Rename files to keep with Version/Release/Modification
  130.                     numbering scheme.
  131.                     Remove necessity for using User Interrupt locations in
  132.                     low storage. Use Far calls to original interrupt.
  133.                     Change Alt-F10 to Alt-F9 to avoid common conflicts.
  134.                     Change Cntl-Home to Cntl-F9 keys to avoid common conflicts.
  135.          12.85 - Version 3.40   l.ferris
  136.                     Clean up Window errors, add 3rd window options. Correct
  137.                     Alpa/Beta errors. Say Thanks to Neil once again.
  138.           4.86 - Version 4.00
  139.                     Rewrite stay-resident interface. Avoid manipulating
  140.                     DOS or Users interrupted stack.
  141.                     Intercepts Interrupts 9, 8, 13, 21, 28
  142.           6.86 -    Replace INT 9 processing with an INT 16 equivalent.
  143.                     Works better with mutitasking environments. Leave
  144.                     INT 9 as an option.
  145.                - Version 4.10
  146.                     Addition of Neil RubenKing's Clock Demonstration.
  147.                     Great work Neil. Thanks! Corrections from beta tests.
  148.                     Documentation cleanup.
  149.                     Enable interrupts within INT21 service routine.
  150.           7.26 - Version 4.11 Stayi8 missing ES:Lodsb instr
  151.                - Version 4.12 Special for NJR/TRG/LTW
  152.           7.28 - Version 4.13 Stayi8 change Add to OR
  153.                      BP not being protected from BIOS usage
  154.           8.02 - Version 4.14 Attempt to solve Exit Crashes
  155.                     Exit thru stack restore, not INT $20
  156.                     Correct Ctlc-C crashes. INT23 was set to zeros
  157.                     Change SetCtlc,GetCtlc parameters to call-by-name
  158.           8.04 - Version 4.15 Save Indos Primary stack for recursive
  159.                      entries to DOS functions [0..C] (Writeln(LST or AUX))
  160.                      Rework Staysave,Stayrstr
  161.           8.14 - Version 4.20 Public Release of 4.1.+ fixes
  162. }
  163. Program Stay_Resident;
  164.  
  165. { * * * * * * * CONSTANTS * * * * * * * * * * * * * * * * * * * * * * }
  166.   const
  167. {      the next field is needed for the windo.inc routines }
  168.     MaxWin          = 2;       { Max number of windows open at one time }
  169.     Esc             = #27;     {character equivalent of Escape Key}
  170.     Alt_F9          = #112;    {Alt Function 9 Scan code        }
  171.     Ctrl_F9         = #229;    {Ctl-F9 (#102+127)  Key  code    }
  172.     Quit_Key        = Ctrl_F9; {Quit and Release Memory}
  173.  
  174.     Alt             = 08;      {Shift bits at 40:17 }
  175.     Ctrl            = 04;
  176.     Left_Shift      = 02;
  177.     Rght_Shift      = 01;
  178.  
  179.     BIOSI8          = 8;       {Bios Timer interrupt}
  180.     BIOSI16         = $16;     {Bios Keyboard interrupt}
  181.     BIOSI13         = $13;     {Bios Disk interrupt}
  182.     DOSI21          = $21;     {DOS service router interrupt}
  183.     DOSI28          = $28;     {DOS Idle interrupt}
  184. {------------- T Y P E    D E C L A R A T I O N S ----------------------}
  185.   Type
  186.     Regtype     = record Ax,Bx,Cx,Dx,Bp,Si,Di,Ds,Es,Flags:integer  end;
  187.     HalfRegtype = record Al,Ah,Bl,Bh,Cl,Ch,Dl,Dh:byte              end;
  188.     filename_type = string[64];
  189.     Vector   = record             { Interrupt Vector type   }
  190.        IP,CS :integer ;
  191.           end ;
  192.  
  193. {-------------- T Y P E D   C O N S T A N T S --------------------------}
  194.   Const
  195.  
  196.     Our_HotKey   : byte = 112; { scan code for Alt-F9}
  197.  
  198.       { This table marks those INT 21 functions which must be passed     }
  199.       { without modification. They either never return, fetch parameters }
  200.       { from the stack, or may be interrupted by a TSR                   }
  201.  
  202.       Functab    : array[0..$6F] of byte =
  203.                    (1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0,  {0-C}
  204.                     0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
  205.                     0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,0,1,  {26,2F}
  206.                     0,1,1,1, 1,1,0,0, 0,0,0,0, 0,0,0,0,  {31-35}
  207.                     0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,0,0,  {48-4D}
  208.                     1,1,1,1, 0,1,0,0, 1,0,0,0, 0,1,1,1,  {50-53,55,58,5D-5F}
  209.                     1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1); {60-62}
  210.  
  211.       Intr_Flags : byte = 0;           {Active interrupts flags}
  212.          INT13_on  =  04;               {Disk  interrupt is active}
  213.          INT21_on  =  08;               {DOS Service router is active}
  214.       Status     : byte = 0;           {Status of current TSR activity}
  215.          Hotkey_on =  01;               {Received the HotKey}
  216.          Inuse     =  02;               {TSR is active}
  217.          Foxs      = $FF;               {workaround for inline hex FF}
  218.       DosVersion : byte = 0;           {Current Version of DOS}
  219.       WaitCount  : byte = 0;           {Wait to activate count}
  220.       UserProgram :integer = 0;        {Offset to Users Program Code}
  221.  
  222.       OurDSeg: integer = 0;            {Turbo Data Segment Value  }
  223.       OurSSeg: integer = 0;            {Turbo Stack Segment Value   }
  224.  
  225.       DosDSeg: integer = 0;            {Dos Datasegment value     }
  226.       DosSSeg: integer = 0;            {Dos Stack Segment Value   }
  227.       DosSPtr: integer = 0;            {Dos Stack pointer value   }
  228.       DosSsiz: integer = 0;            {Dos Stack size in words }
  229.  
  230.       UsrDSeg: integer = 0;            {Interrupted Datasegment value     }
  231.       UsrSSeg: integer = 0;            {Interrupted Stack Segment Value   }
  232.       UsrSPtr: integer = 0;            {Interrupted Stack pointer value   }
  233.       OurPSP : integer = 0;
  234.  
  235.  
  236.     { The following  constants *MUST* remain in the IP:CS order.   }
  237.     { StaySave uses them as  JMP targets                           }
  238.  
  239.       BIOS_INT8   : vector = (IP:0;CS:0);  {BIOS Timer Interrupt Vector }
  240.       BIOS_INT16  : vector = (IP:0;CS:0);  {BIOS Keyboard Interrupt Vector }
  241.       BIOS_INT13  : vector = (IP:0;CS:0);  {BIOS Disk Interrupt Vector    }
  242.       DOS_INT21   : vector = (IP:0;CS:0);  {DOS Sevice Interrupt Vector}
  243.       DOS_INT28   : vector = (IP:0;CS:0);  {DOS idle Service interrupt Vector}
  244.       DOSStat1    : vector = (IP:0;CS:0);  {Pointer to INDOS byte}
  245.       DOSStat2    : vector = (IP:0;CS:0);  {Pointer to CRITICAL byte}
  246.  
  247.       Version  :string[4] = '4.15';      { Current Version number }
  248.  
  249.  {-------------- V A R I A B L E S ----------------------------------------}
  250.     Var
  251.  
  252.       Regs       : regtype;
  253.       HalfRegs   : halfregtype absolute regs;
  254.       Keychr     : char ;
  255.       Bytecount  : integer;
  256.  
  257.       SavedPSP   : integer;          { Program Segment Prefix pointers }
  258.       Error      : integer;          { I/O results }
  259.       Good       : boolean;          { I/O results switch }
  260.       Terminate  : boolean;          { Exit stayRes Flag  }
  261.  
  262.       OurDTA   :Array [1..2] Of integer; {Local DTA pointer}
  263.       SavedDTA :Array [1..2] of integer; {Interrupted DTA pointer}
  264.  
  265. {-----------------------------------------------------------------------------}
  266. {                 W  I  N  D  O  W     R  O  U  T  I  N  E                    }
  267. {---------------------------------------------------------------------------- }
  268. {$I STAYWNDO.341}
  269. {----------------------------------------------------------------------}
  270. {            S  T  A  Y  E  X  I  T                                    }
  271. {----------------------------------------------------------------------}
  272. {$I STAYXIT.420}
  273. {*****************************************************************************}
  274. {-----------------------------------------------------------------------------}
  275. {            THE FOLLOWING ARE THE USER INCLUDE ROUTINES                      }
  276. {-----------------------------------------------------------------------------}
  277. {*****************************************************************************}
  278. {$I STAYSUBS.420}
  279.     {-------------------------------------------------------------}
  280.     {           S T A Y D E M         Demo Routines               }
  281.     {-------------------------------------------------------------}
  282.     { comment out the next line to use the Rubenking Background Clock }
  283. (****{$I STAYDEM.420}***)
  284.     {-------------------------------------------------------------}
  285.     {          C L O C K D E M O       Demo Routines              }
  286.     {-------------------------------------------------------------}
  287.     { Substitute the following lines for the Clock Demo by Neil Rubenking.
  288.      Comment or remove the $I STAYDEM.... line above
  289.      See additional comment at interrupt 8 inline procedure Stay_INT8.}
  290. {$I CLKDEM.420}
  291. {-----------------------------------------------------------------------------}
  292. {            THE ABOVE ARE THE USER INCLUDE ROUTINES                          }
  293. {-----------------------------------------------------------------------------}
  294.  
  295. {-----------------------------------------------------------------------------}
  296. {              P R O C E S S   I N T E R R U P T                              }
  297. {-----------------------------------------------------------------------------}
  298. {  PURPOSE:
  299.       The following procedures  displace  standard interrupts.
  300.  
  301.       Do not put Variables or Constants in this Procedure. It will
  302.       cause registers to be clobbered during the Interrupt routine
  303.       when Turbo attempts to allocate  storage for local variables
  304.       or parameters.
  305.  
  306. }
  307.  
  308. Procedure STAY_INT16;       {Keyboard Interrupt 16 Service Routine}
  309. {
  310.       If anything but "Our_HotKey" is pressed,  the key is  passed
  311.       to the standard  keyboard service routine.  B_U_T,  when Our
  312.       HotKey is recognized, a hotkey bit is set.
  313. }
  314. Begin
  315. {$I Stayi16.410}
  316. End; {STAY_INT16}
  317.  
  318. Procedure STAY_INT13;       {BIOS Disk interrupt  Routine}
  319. Begin                       {Sets a flag while disk is active}
  320. {$I Stayi13.410}
  321. End; {STAY_INT13}
  322.  
  323. Procedure STAY_INT21;       {DOS interrupt 21 Service Routine}
  324. Begin                       {Sets a flag while INT 21 is active}
  325. {$I Stayi21.410}
  326. End; {STAY_INT21}
  327.  
  328.  
  329. Procedure Stay_INT8;        {Timer Interrupt 8 Service Routine}
  330.                             {Activates Stayres during pgm execution}
  331. Begin                       {when safe to do so.}
  332. { add the following include for the Clock Demonstration by Neil Rubenking }
  333. {$I ClkI8.410}
  334.  
  335. {$I Stayi8.420}
  336. End;{Stay_Int8}
  337.  
  338. Procedure Stay_INT28;       {Idle Interrupt 28 Service Routine}
  339. Begin                       {Invokes Stayres from the DOS prompt}
  340. {$I Stayi28.410}            {and allows background activity to  }
  341. End;{Stay_Int28}            {continue}
  342.  
  343. Procedure StaySave;         {Prolog to Resident Turbo Code}
  344. Begin
  345. {$I StaySave.420}
  346.  
  347.    GetDTA(SavedDTA[1],SavedDTA[2]);         {Save callers DTA address}
  348.  
  349.    GetPSP(SavedPSP);                        {Save callers PSP Segment}
  350.    SetPSP(OurPSP);                          {Set our PSP Segment}
  351.  
  352.    SetDTA(OurDTA[1],OurDTA[2]);             {Set our DTA address}
  353.  
  354.    NewCtlc[2] := CSeg;
  355.       NewCtlc[1] := Ofs(IRET);
  356.    GetCtlC(SavedCtlc); SetCtlC(NewCtlc);    {Get/Save the users Ctrl-C vector}
  357.  
  358.    INT24On;                                 {Trap Dos Critical Errors}
  359.  
  360.         {-------------------------------------------------------}
  361.         {              INVOKE USER PROCEDURE HERE               }
  362.         {-------------------------------------------------------}
  363. {            .
  364.              .
  365.              .  Your
  366.              .      Program
  367.              .             Goes
  368.              .                 Here
  369.              .
  370. }
  371.         Demo ;  {Replace Demo with your procedures}
  372.  
  373. (*** Writeln(Lst,'.... Demonstrate auxilary device usage ....'); ***)
  374.  
  375.         {----------------------------------------------------------}
  376.         {             END USER PROCEDURE HERE                      }
  377.         {----------------------------------------------------------}
  378.  
  379.    SetPSP(SavedPSP);                   { Restore Callers PSP Segment}
  380.  
  381.    SetDTA(SavedDTA[1],SavedDTA[2]);    { Restore the users DTA}
  382.    SetCtlC(SavedCtlC);                 { Restore the users Ctrl-C Vector}
  383.  
  384.    INT24Off;                           { Remove Our Critical Error routine}
  385.    If (Terminate = true) then Stay_Xit;{ If exit key, restore Int Vectors }
  386. {---------------------------------------------------------------------------}
  387. {             BEGINNING OF THE STAYRSTR ROUTINE                             }
  388. {---------------------------------------------------------------------------}
  389. {$I Stayrstr.420}      { RETURN TO CALLER }
  390.           {---------------------------------------------------}
  391.           {        END OF THE STAYRSTR ROUTINE                }
  392.           {---------------------------------------------------}
  393.  
  394. End ;{StaySave}
  395.  
  396. {-------------------------------------------------------------------------}
  397. {                             M  A  I  N                                  }
  398. {-------------------------------------------------------------------------}
  399.           { The main program installs the new interrupt routine }
  400.           { and makes it permanently resident as the keyboard   }
  401.           { interrupt.  The old keyboard interrupt Vector is    }
  402.           { stored in Variables , so they can be used in Far    }
  403.           { Calls.                                              }
  404.           {                                                     }
  405.           { The following dos calls are used:                   }
  406.           { Function 25 - Install interrupt address             }
  407.           {               input al = int number,                }
  408.           {               ds:dx = address to install            }
  409.           { Function 35 - get interrupt address                 }
  410.           {               input al = int number                 }
  411.           {               output es:bx = address in interrupt   }
  412.           { Function 31 - terminate and stay resident           }
  413.           {               input dx = size of resident program   }
  414.           {               obtained from the memory              }
  415.           {               allocation block at [Cs:0 - $10 + 3]  }
  416.           { Function 49 - Free Allocated Memory                 }
  417.           {               input Es = Block Segment to free      }
  418.           {-----------------------------------------------------}
  419. Begin                                  {**main**}
  420.  
  421.   Writeln('Turbo Stayres Version ',Version,' initializing.');
  422.  
  423.   OurDseg:= Dseg;           { Save the Data Segment Address for Interrupts }
  424.   OurSseg:= Sseg;           { Save our Stack Segment for Interrupts        }
  425.   GetPSP(OurPSP);           { Local PSP Segment             }
  426.  
  427.  
  428.   GetDTA(OurDTA[1],OurDTA[2]); { Record our DTA address }
  429.  
  430.   UserProgram:=Ofs(Staysave); {Set target of call instruction}
  431.       Regs.Ax := $3000 ;            {Obtain the DOS Version number}
  432.       Intr(DosI21,Regs);
  433.       DosVersion := Halfregs.Al;    { 0=1+, 2=2.0+, 3=3.0+ }
  434.  
  435.                                     {Obtain the DOS Indos status location}
  436.         Regs.Ax := $3400;
  437.         Intr(DosI21,Regs);
  438.         DosStat1.IP  := Regs.BX;
  439.         DosStat1.CS  := Regs.ES;
  440.         DosStat2.CS  := Regs.ES;
  441.         DosSSeg      := Regs.ES;
  442.  
  443.       Bytecount := 0;         { Search for CMP [critical flag],00 instruction }
  444.       While (Bytecount < $2000)        { then Mov SP,stackaddr instruction }
  445.          and (Memw[DosStat2.CS:Bytecount] <> $3E80)
  446.             do Bytecount := Succ(Bytecount);
  447.  
  448.       If Bytecount = $2000 then begin   { Couldn't find critical flag addr }
  449.          Writeln('StayRes incompatiblity with Operating System');
  450.          Writeln('StayRes will not install correctly..Halting');
  451.          Halt; end;
  452.  
  453.          { Search for the DOS Critical Status Byte address.       }
  454.          { Bytecount contains offset from DosStat1.CS of the      }
  455.          {        CMP [critical flag],00                          }
  456.          {        JNZ ....                                        }
  457.          {        Mov SP,indos stack address                      }
  458.  
  459.       If Mem[DosStat2.CS:Bytecount+7] = $BC    {MOV SP,xxxx}
  460.          then BEGIN
  461.          DosStat2.IP := Memw[DosStat2.CS:Bytecount+2];
  462.          DosSptr     := Memw[DosStat2.CS:bytecount+8]; {INDOS Stack address}
  463.          END
  464.       else BEGIN
  465.          Writeln('Cannot Find Dos Critical byte...Halting');
  466.          Halt;
  467.          end;
  468.  
  469.       Inline($FA);                       {Disable interrupts}
  470.  
  471.               { Setup Our Interrupt Service Routines }
  472.  
  473.       Setup_Interrupt(BIOSI16, BIOS_Int16, Ofs(Stay_INT16)); {keyboard}
  474.       Setup_Interrupt(BIOSI8, BIOS_Int8, Ofs(Stay_INT8));    {timer}
  475.       Setup_Interrupt(BIOSI13, BIOS_Int13, Ofs(Stay_INT13)); {disk}
  476.       Setup_Interrupt(DOSI21, DOS_Int21, Ofs(Stay_INT21));   {DOSfunction}
  477.       Setup_Interrupt(DOSI28, DOS_Int28, Ofs(Stay_INT28));   {DOS idle}
  478.  
  479.       Inline($FB);                        {Re-enable interrupts}
  480. {****************************************************************************}
  481. {----------------------------------------------------------------------------}
  482. {                INITIALIZE YOUR PROGRAM HERE                                }
  483. {----------------------------------------------------------------------------}
  484. {****************************************************************************}
  485.       { Initialize Your Progam Here since you wont get control again
  486.         until "Our_HotKey" is entered from the Keyboard.               }
  487.  
  488.       Terminate := false;             { Clear the program exit flags }
  489.       Writeln(' Author: The Hunter''s Helper');
  490.       Writeln('   LaneFerris, Compuserv 70357,2716');
  491.       Writeln('     Alt-F9 activates : Ctrl-F9 deactivates');
  492.      {------------------------------------------------------------}
  493.      {           END OF INITALIZE PROGRAM CODE                    }
  494.      {------------------------------------------------------------}
  495. {
  496.       Now terminate and stay resident.   The following Call utilizes the
  497.       DOS Terminate & Stay Resident function.  We get the amount of
  498.       memory by fetching the memory allocation paragraphs from the Memory
  499.       Control Block.  This was set by Turbo initialization during Int
  500.       21/function 4A (shrink block), calculated from the mInimum and mAximum
  501.       options menu. The MCB sits one paragraph above the PSP.
  502.  
  503. }
  504.                                           { Pass return code of zero    }
  505.       Regs.Ax := $3100 ;                  { Terminate and Stay Resident }
  506.       Regs.Dx := MemW [Cseg-1:0003]+1 ;   { Prog_Size from Allocation Blk}
  507.       Write('      Using ',Regs.Dx /64 :4:1,'K');
  508.       Write('  Code:',(Dseg-Cseg)/64 :4:1,'K');
  509.       Write('  Data:',(SSeg-Dseg)/64 :4:1,'K');
  510.       Write('  Heap:',(Cseg+Regs.Dx-SSeg)/64 :4:1,'K');
  511.      Intr (DosI21,Regs);
  512.  
  513.  
  514.        { END OF RESIDENCY CODE }
  515. end.
  516.