home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / tc-book.zip / RESIDENT.C < prev    next >
Text File  |  1987-08-20  |  8KB  |  311 lines

  1. /* -------- resident.c --------- */
  2.  
  3. #include <dos.h>
  4. #include <stdio.h>
  5.  
  6. static union REGS rg;
  7. static struct SREGS seg;
  8. static unsigned mcbseg;
  9. static unsigned dosseg;
  10. static unsigned dosbusy;
  11. static unsigned enddos;
  12. char far *intdta;
  13. static unsigned intsp;
  14. static unsigned intss;
  15. static char far *mydta;
  16. static unsigned myss;
  17. static unsigned stack;
  18. static unsigned ctrl_break;
  19. static unsigned mypsp;
  20. static unsigned intpsp;
  21. static unsigned pids[2];
  22. static int pidctr = 0;
  23. static int pp;
  24. static void interrupt (*oldtimer)();
  25. static void interrupt (*old28)();
  26. static void interrupt (*oldkb)();
  27. static void interrupt (*olddisk)();
  28. static void interrupt (*oldcrit)();
  29. extern void interrupt (*ZeroDivVector)();
  30. void interrupt newtimer();
  31. void interrupt new28();
  32. void interrupt newkb();
  33. void interrupt newdisk();
  34. void interrupt newcrit();
  35. extern unsigned sizeprogram;
  36. extern unsigned scancode;
  37. extern unsigned keymask;
  38. static int resoff = 0;
  39. static int running = 0;
  40. static int popflg = 0;
  41. static int diskflag = 0;
  42. static int kbval;
  43. static int cflag;
  44.  
  45. void dores(), pidaddr();
  46.  
  47. /* -------- establish & declare residency --------- */
  48. void resinit()
  49. {
  50.     segread(&seg);
  51.     myss = seg.ss;
  52.     /* ------ get address of DOS busy flag ---- */
  53.     rg.h.ah = 0x34;
  54.     intdos(&rg, &rg);
  55.     dosseg = _ES;
  56.     dosbusy = rg.x.bx;
  57.     /* ----- get address of resident program's dta ----- */
  58.     mydta = getdta();
  59.     /* -------- get addresses of PID in DOS ------- */
  60.     pidaddr();
  61.     /* ----- get original interrupt vectors ----- */
  62.     oldtimer = getvect(0x1c);
  63.     old28 = getvect(0x28);
  64.     oldkb = getvect(9);
  65.     olddisk = getvect(0x13);
  66.     /* ----- attach vectors to resident program ----- */
  67.     setvect(0x1c, newtimer);
  68.     setvect(9, newkb);
  69.     setvect(0x28, new28);
  70.     setvect(0x13, newdisk);
  71.     /* ------ compute stack pointer ------- */
  72.     stack = (sizeprogram - (seg.ds - seg.cs)) * 16 - 300;
  73.     /* ---- restore zero divide interrupt vector --- */
  74.     setvect(0, ZeroDivVector);
  75.     /* ----- terminate and stay resident ------- */
  76.     rg.x.ax = 0x3100;
  77.     rg.x.dx = sizeprogram;
  78.     intdos(&rg, &rg);
  79. }
  80.  
  81. /* ------ BIOS disk functions ISR ------- */
  82. void interrupt newdisk(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flgs)
  83. {
  84.     diskflag++;
  85.     (*olddisk)();
  86.     ax = _AX;        /* for the ax return */
  87.     newcrit();        /* to get current flags register */
  88.     flgs = cflag;
  89.     --diskflag;
  90. }
  91.  
  92. /* -------- critical error ISR ---------- */
  93. void interrupt newcrit(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flgs)
  94. {
  95.     ax = 0;
  96.     cflag = flgs;    /* for newdisk */
  97. }
  98.  
  99. /* ----- keyboard ISR ------ */
  100. void interrupt newkb()
  101. {
  102.     if (inportb(0x60) == scancode)    {
  103.         kbval = peekb(0, 0x417);
  104.         if (!resoff && ((kbval & keymask) ^ keymask) == 0)    {
  105.             /* --- reset the keyboard ---- */
  106.             kbval = inportb(0x61);
  107.             outportb(0x61, kbval | 0x80);
  108.             outportb(0x61, kbval);
  109.             disable();
  110.             outportb(0x20, 0x20);
  111.             enable();
  112.             /* ---- set hotkey indicator ---- */
  113.             if (!running)
  114.                 popflg = 1;
  115.             return;
  116.         }
  117.     }
  118.     (*oldkb)();
  119. }
  120.  
  121. /* ----- timer ISR ------- */
  122. void interrupt newtimer()
  123. {
  124.     (*oldtimer)();
  125.     if (popflg && peekb(dosseg, dosbusy) == 0)
  126.         if (diskflag == 0)    {
  127.             outportb(0x20, 0x20);
  128.             popflg = 0;
  129.             dores();
  130.         }
  131. }
  132.  
  133. /* ----- DOSOK ISR -------- */
  134. void interrupt new28()
  135. {
  136.     (*old28)();
  137.     if (popflg && peekb(dosseg, dosbusy) != 0)    {
  138.         popflg = 0;
  139.         dores();
  140.     }
  141. }
  142.  
  143. /* ------ switch psp context from interrupted to TSR ----- */
  144. resident_psp()
  145. {
  146.     /* ------ save interrupted program's psp ----- */
  147.     intpsp = peek(dosseg, *pids);
  148.     /* ----- set resident program's psp ----- */
  149.     for (pp = 0; pp < pidctr; pp++)
  150.         poke(dosseg, pids [pp], mypsp);
  151. }
  152.  
  153. /* ---- switch psp context from TSR to interrupted ---- */
  154. interrupted_psp()
  155. {
  156.     /* ----- reset interrupted program's psp ----- */
  157.     for (pp = 0; pp < pidctr; pp++)
  158.         poke(dosseg, pids [pp], intpsp);
  159. }
  160.  
  161. /* ------ execute the resident program ------- */
  162. void dores()
  163. {
  164.     running = 1;
  165.     disable();
  166.     intsp = _SP;
  167.     intss = _SS;
  168.     _SP = stack;
  169.     _SS = myss;
  170.     enable();
  171.     oldcrit = getvect(0x24);/* redirect critical error     */
  172.     setvect(0x24, newcrit);
  173.     rg.x.ax = 0x3300;        /* get ctrl break setting      */
  174.     intdos(&rg, &rg);
  175.     ctrl_break = rg.h.dl;
  176.     rg.x.ax = 0x3301;        /* turn off ctrl break logic   */
  177.     rg.h.dl = 0;
  178.     intdos(&rg, &rg);
  179.     intdta = getdta();        /* get interrupted dta         */
  180.     setdta(mydta);            /* set resident dta            */
  181.     resident_psp();            /* swap psps                   */
  182.     popup();                /* execute resident program    */
  183.     interrupted_psp();        /* reset interrupted psp       */
  184.     setdta(intdta);            /* reset interrupted dta       */
  185.     setvect(0x24, oldcrit);    /* reset critical error        */
  186.     rg.x.ax = 0x3301;        /* reset ctrl break            */
  187.     rg.h.dl = ctrl_break;
  188.     intdos(&rg, &rg);
  189.     disable();                /* reset interrupted stack     */
  190.     _SP = intsp;
  191.     _SS = intss;
  192.     enable();
  193.     running = 0;
  194. }
  195. /*page*/
  196. static int avec = 0;
  197.  
  198. /* ------- test to see if the program is already resident
  199.       if not, attach to an available interrupt ---------- */
  200. unsigned resident(signature, ifunc)
  201. char *signature;
  202. void interrupt (*ifunc)();
  203. {
  204.     char *sg;
  205.     unsigned df;
  206.     int vec;
  207.  
  208.     segread(&seg);
  209.     df = seg.ds-seg.cs;
  210.     for (vec = 0x60; vec < 0x68; vec++)    {
  211.         if (getvect(vec) == NULL)    {
  212.             if (!avec)
  213.                 avec = vec;
  214.             continue;
  215.         }
  216.         for (sg = signature; *sg; sg++)
  217.             if (*sg!=peekb(peek(0,2+vec*4)+df,(unsigned)sg))
  218.                 break;
  219.         if (!*sg)
  220.             return vec;
  221.     }
  222.     if (avec)
  223.         setvect(avec, ifunc);
  224.     return 0;
  225. }
  226. /*page*/
  227. /* -------- find address of PID ---------- */
  228. static void pidaddr()
  229. {
  230.     unsigned adr = 0;
  231.  
  232.     /* ------- get the current pid --------- */
  233.     rg.h.ah = 0x51;
  234.     intdos(&rg, &rg);
  235.     mypsp = rg.x.bx;
  236.     /* ----- find the end of the DOS segment ------- */
  237.     rg.h.ah = 0x52;
  238.     intdos(&rg, &rg);
  239.     enddos = _ES;
  240.     enddos = peek(enddos, rg.x.bx-2);
  241.     /* ---- search for matches on the pid in dos ---- */
  242.     while (pidctr < 2 &&
  243.             (unsigned)((dosseg<<4) + adr) < (enddos<<4))    {
  244.         if (peek(dosseg, adr) == mypsp)    {
  245.             rg.h.ah = 0x50;
  246.             rg.x.bx = mypsp + 1;
  247.             intdos(&rg, &rg);
  248.             if (peek(dosseg, adr) == mypsp+1)
  249.                 pids[pidctr++] = adr;
  250.             /* ---- reset the original pid ------ */
  251.             rg.h.ah = 0x50;
  252.             rg.x.bx = mypsp;
  253.             intdos(&rg, &rg);
  254.         }
  255.         adr++;
  256.     }
  257. }
  258. /*page*/
  259. #undef peekb    /* to overcome TC 1.0 bug */
  260. /* ------- terminate function ----------- */
  261. static resterm()
  262. {
  263.     closefiles();    /*  close TSR files */
  264.     /* ----- restore the interrupt vectors ----- */
  265.     setvect(0x1c, oldtimer);
  266.     setvect(9, oldkb);
  267.     setvect(0x28, old28);
  268.     setvect(0x13, olddisk);
  269.     setvect(avec, (void interrupt (*)()) 0);
  270.     /* ---- get the seg addr of 1st DOS MCB ---- */
  271.     rg.h.ah = 0x52;
  272.     intdos(&rg, &rg);
  273.     mcbseg = _ES;
  274.     mcbseg = peek(mcbseg, rg.x.bx-2);
  275.     /* ---- walk thru mcb chain & release memory ----- */
  276.     segread(&seg);
  277.     while (peekb(mcbseg, 0) == 0x4d)    {
  278.         if (peek(mcbseg, 1) == mypsp)    {
  279.             rg.h.ah = 0x49;
  280.             seg.es = mcbseg+1;
  281.             intdosx(&rg, &rg, &seg);
  282.         }
  283.         mcbseg += peek(mcbseg, 3) + 1;
  284.     }
  285. }
  286. /* --------- terminate the resident program --------- */
  287. terminate()
  288. {
  289.     if (getvect(0x13) == (void interrupt (*)()) newdisk)
  290.         if (getvect(9) == newkb)
  291.             if (getvect(0x28) == new28)
  292.                 if (getvect(0x1c) == newtimer)    {
  293.                     resterm();
  294.                     return;
  295.                 }
  296.     resoff = 1;    /* another TSR is above us, merely suspend */
  297. }
  298.  
  299. /* ------------- restart the resident program --------- */
  300. restart()
  301. {
  302.     resoff = 0;
  303. }
  304.  
  305. /* ------- put the program on hold -------- */
  306. wait()
  307. {
  308.     resoff = 1;
  309. }
  310.  
  311.