home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / MAGAZINE / DDJMAG / DDJ9104.ZIP / C_PROG.ASC < prev    next >
Text File  |  1991-03-15  |  7KB  |  248 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /* --------- tsr.c --------- */
  8.  
  9. /*
  10.  * A Terminate and Stay Resident (TSR) engine
  11.  */
  12.  
  13. #include <dos.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include "mouse.h"
  17. #include "keys.h"
  18.  
  19. void tsr_program(void);
  20.  
  21. #define KEYMASK  8
  22. #define SCANCODE 52
  23.  
  24. extern unsigned _stklen = 1024;
  25. extern unsigned _heaplen = 8192;
  26.  
  27. /* ------- the interrupt function registers -------- */
  28. typedef struct {
  29.     int bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,fl;
  30. } IREGS;
  31.  
  32. /* --- vectors ---- */
  33. #define DISK    0x13
  34. #define CTRLBRK 0x1b
  35. #define INT28   0x28
  36. #define CRIT    0x24
  37. #define CTRLC   0x23
  38. #define TIMER   8
  39. #define KYBRD   9
  40. #define DOS     0x21
  41.  
  42. unsigned highmemory;
  43.  
  44. /* ------ interrupt vector chains ------ */
  45. static void (interrupt *oldtimer)(void);
  46. static void (interrupt *old28)(void);
  47. static void (interrupt *oldkb)(void);
  48. static void (interrupt *olddisk)(void);
  49.  
  50. /* ------ ISRs for the TSR ------- */
  51. static void interrupt newtimer(void);
  52. static void interrupt new28(void);
  53. static void interrupt newdisk(IREGS);
  54. static void interrupt newkb(void);
  55. static void interrupt newcrit(IREGS);
  56. static void interrupt newbreak(void);
  57.  
  58. static unsigned sizeprogram; /* TSR's program size     */
  59. unsigned dossegmnt;          /* DOS segment address    */
  60. unsigned dosbusy;            /* offset to InDOS flag   */
  61. static int diskflag;         /* Disk BIOS busy flag    */
  62. unsigned mcbseg;             /* address of 1st DOS mcb */
  63. static char far *mydta;      /* TSR's DTA              */
  64.  
  65. int hotkeyhit = FALSE;
  66. int tsrss;          /* TSR's stack segment */
  67. int tsrsp;          /* TSR's stack pointer */
  68.  
  69. /* -------------- context for the popup ---------------- */
  70. unsigned intpsp;            /* Interrupted PSP address   */
  71. int running;                /* TSR running indicator     */
  72. char far *intdta;           /* interrupted DTA           */
  73. unsigned intsp;             /*     "       stack pointer */
  74. unsigned intss;             /*     "       stack segment */
  75. unsigned ctrl_break;        /* Ctrl-Break setting        */
  76. void (interrupt *oldcrit)(void);
  77. void (interrupt *oldbreak)(void);
  78. void (interrupt *oldctrlc)(void);
  79.  
  80. /* ------- local prototypes -------- */
  81. static void resident_psp(void);
  82. static void interrupted_psp(void);
  83. static void popup(void);
  84.  
  85. void main(void)
  86. {
  87.     unsigned es, bx;
  88.     /* ---------- compute memory parameters ------------ */
  89.     highmemory = _SS + ((_SP + 256) / 16);
  90.     /* ------ get address of DOS busy flag ---- */
  91.     _AH = 0x34;
  92.     geninterrupt(DOS);
  93.     dossegmnt = _ES;
  94.     dosbusy = _BX;
  95.     /* ---- get the seg addr of 1st DOS MCB ---- */
  96.     _AH = 0x52;
  97.     geninterrupt(DOS);
  98.     es = _ES;
  99.     bx = _BX;
  100.     mcbseg = peek(es, bx-2);
  101.     /* ----- get address of resident program's dta ----- */
  102.     mydta = getdta();
  103.     /* ------------ prepare for residence ------------ */        
  104.     tsrss = _SS;
  105.     tsrsp = _SP;
  106.     oldtimer = getvect(TIMER);
  107.     old28 = getvect(INT28);
  108.     oldkb = getvect(KYBRD);
  109.     olddisk = getvect(DISK);
  110.  
  111.     /* ----- attach vectors to resident program ----- */
  112.     setvect(KYBRD, newkb);
  113.     setvect(INT28, new28);
  114.     setvect(DISK, newdisk);
  115.     setvect(TIMER, newtimer);
  116.     /* ------ compute program size ------- */
  117.     sizeprogram = highmemory - _psp + 1;
  118.     /* ----- terminate and stay resident ------- */
  119.     _DX = sizeprogram;
  120.     _AX = 0x3100;
  121.     geninterrupt(DOS);
  122. }
  123.  
  124. /* ---------- break handler ------------ */
  125. static void interrupt newbreak(void)
  126. {
  127.     return;
  128. }
  129.  
  130. /* -------- critical error ISR ---------- */
  131. static void interrupt newcrit(IREGS ir)
  132. {
  133.     ir.ax = 0;            /* ignore critical errors */
  134. }
  135.  
  136. /* ------ BIOS disk functions ISR ------- */
  137. static void interrupt newdisk(IREGS ir)
  138. {
  139.     diskflag++;
  140.     (*olddisk)();
  141.     ir.ax = _AX;        /* for the register returns */
  142.     ir.cx = _CX;
  143.     ir.dx = _DX;
  144.     ir.es = _ES;
  145.     ir.di = _DI;
  146.     ir.fl = _FLAGS;
  147.     --diskflag;
  148. }
  149.  
  150. /* ----- keyboard ISR ------ */
  151. static void interrupt newkb(void)
  152. {
  153.     static unsigned char kbval;
  154.  
  155.     kbval = inportb(0x60);
  156.     if (!hotkeyhit && !running)
  157.         if ((peekb(0, 0x417) & 0xf) == KEYMASK)
  158.             if (SCANCODE == kbval)    {
  159.                 hotkeyhit = TRUE;
  160.                 /* --- reset the keyboard ---- */
  161.                 kbval = inportb(0x61);
  162.                 outportb(0x61, kbval | 0x80);
  163.                 outportb(0x61, kbval);
  164.                 outportb(0x20, 0x20);
  165.                 return;
  166.             }
  167.     (*oldkb)();
  168. }
  169.  
  170. /* ----- timer ISR ------- */
  171. static void interrupt newtimer(void)
  172. {
  173.     (*oldtimer)();
  174.     if (hotkeyhit && (peekb(dossegmnt, dosbusy) == 0) &&
  175.             !diskflag)
  176.         popup();
  177. }
  178.  
  179. /* ----- 0x28 ISR -------- */
  180. static void interrupt new28(void)
  181. {
  182.     (*old28)();
  183.     if (hotkeyhit)
  184.         popup();
  185. }
  186.  
  187. /* ------ switch psp context from interrupted to TSR ----- */
  188. static void resident_psp(void)
  189. {
  190.     intpsp = getpsp();
  191.     _AH = 0x50;
  192.     _BX = _psp;
  193.     geninterrupt(DOS);
  194. }
  195.  
  196. /* ---- switch psp context from TSR to interrupted ---- */
  197. static void interrupted_psp(void)
  198. {
  199.      _BX = intpsp;
  200.      _AH = 0x50;
  201.     geninterrupt(DOS);
  202. }
  203.  
  204. /* ------ execute the resident program ------- */
  205. static void popup(void)
  206. {
  207.     running = TRUE;
  208.     hotkeyhit = FALSE;
  209.     intsp = _SP;
  210.     intss = _SS;
  211.     _SP = tsrsp;
  212.     _SS = tsrss;
  213.     oldcrit = getvect(CRIT);    /* redirect critical err  */
  214.     oldbreak = getvect(CTRLBRK);
  215.     oldctrlc = getvect(CTRLC);
  216.     setvect(CRIT, newcrit);
  217.     setvect(CTRLBRK, newbreak);
  218.     setvect(CTRLC, newbreak);
  219.     ctrl_break = getcbrk();     /* get ctrl break setting */
  220.     setcbrk(0);                 /* turn off ctrl break    */
  221.     intdta = getdta();          /* get interrupted dta    */
  222.     setdta(mydta);              /* set resident dta       */
  223.     resident_psp();             /* swap psps              */
  224.     intercept_mouse();          /* intercept the mouse    */
  225.     /* ------ save the video cursor configuration ------- */
  226.     savecursor();
  227.     normalcursor();
  228.     unhidecursor();
  229.     enable();
  230.     tsr_program();              /* call the TSR C program */
  231.     disable();
  232.     /* ----- restore the video cursor configuration ----- */
  233.     restorecursor();
  234.     restore_mouse();            /* restore the mouse      */
  235.     interrupted_psp();          /* reset interrupted psp  */
  236.     setdta(intdta);             /* reset interrupted dta  */
  237.     setvect(CRIT, oldcrit);     /* reset critical error   */
  238.     setvect(CTRLBRK, oldbreak);
  239.     setvect(CTRLC, oldctrlc);
  240.     setcbrk(ctrl_break);        /* reset ctrl break       */
  241.     disable();
  242.     _SP = intsp;                /* reset interrupted stack*/
  243.     _SS = intss;
  244.     running = FALSE;            /* reset semaphore        */
  245. }
  246.  
  247.  
  248.