home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / dos / programo / pmw120.exe / EXAMPLES.ZIP / EXAMPLE3.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-28  |  3.8 KB  |  128 lines

  1. /*****************************************************************************
  2.  
  3.   This is an example of how to set up a real mode callback and hook the BIOS
  4. timer tick interrupt (INT 1Ch) in protected mode. For speed purposes, PMODE/W
  5. does not normally pass this interrupt up to protected mode automatically from
  6. real mode. Therefore, it must be hooked in real mode first and then passed up
  7. to protected mode by way of a DPMI callback. In this example, a character is
  8. incremented in the upper right hand corner of the screen on every tick (in
  9. protected mode). This will ONLY work under PMODE/W if there are DPMI callbacks
  10. available (specified in PMWSETUP). If PMODE/W is running under the control of
  11. a DPMI host, the DPMI host must provide PMODE/W with real mode callbacks.
  12. Under DOS/4GW this is not necessary since DOS/4GW passes up 1Ch all the time.
  13. PMODE/W does not pass it up in order to prevent redundant mode switches which
  14. consequently slow down the system. Hooking INT 8 for timing is a much better
  15. idea.
  16.  
  17. *****************************************************************************/
  18.  
  19. #include <stdio.h>
  20. #include <dos.h>
  21.  
  22. void (__interrupt __far timerproc) (void);
  23.  
  24. #pragma aux intp =\
  25.         "push eax",\
  26.         "mov ax,[esi]",\
  27.         "mov es:[edi+2ah],ax",\
  28.         "mov ax,[esi+2]",\
  29.         "mov es:[edi+2ch],ax",\
  30.         "mov ax,[esi+4]",\
  31.         "mov es:[edi+20h],ax",\
  32.         "add word ptr es:[edi+2eh],6",\
  33.         "pop eax",\
  34.         "int 1ch",\
  35.         "iretd",\
  36.         modify [eax];
  37.  
  38. void main (void)
  39. {
  40.   union REGS r;
  41.   unsigned   rmvector;
  42.  
  43.   r.x.eax = 0x205;
  44.   r.h.bl = 0x1c;
  45.   r.x.ecx = FP_SEG (timerproc);
  46.   r.x.edx = FP_OFF (timerproc);
  47.   int386 (0x31, &r, &r);                /* Hook Protected Mode INT 1Ch */
  48.  
  49.   setpassup_1C (&rmvector);             /* Initialize 1Ch Passup Handler */
  50.   getch ();
  51.   resetpassup_1C (&rmvector);           /* Reset 1Ch Passup Handler */
  52. }
  53.  
  54. void (__interrupt __far timerproc) (void)
  55. {
  56.   static char *vidmem = (char *)0xb8000;
  57.  
  58.   vidmem[158] ++;
  59. }
  60.  
  61. int setpassup_1C (unsigned *oldvector)
  62. {
  63.   void int1C_handler (void);
  64.  
  65.   union REGS   pr;
  66.   struct SREGS psr;
  67.  
  68.   unsigned short cbseg, cboff;
  69.   char           regbuf[0x32];
  70.  
  71.   pr.x.eax = 0x303;
  72.   psr.ds = FP_SEG (int1C_handler);
  73.   pr.x.esi = FP_OFF (int1C_handler);
  74.   psr.es = FP_SEG (regbuf);
  75.   pr.x.edi = FP_OFF (regbuf);
  76.   int386x (0x31, &pr, &pr, &psr);       /* Allocate A Realmode Callback */
  77.  
  78.   if (pr.x.cflag != 0)                  /* Exit If Error Allocating Callback */
  79.     return -1;
  80.  
  81.   cbseg = (unsigned short)pr.x.ecx;
  82.   cboff = (unsigned short)pr.x.edx;
  83.  
  84.   pr.x.eax = 0x200;
  85.   pr.h.bl = 0x1c;
  86.   int386 (0x31, &pr, &pr);              /* Save The Realmode INT 1Ch Vector */
  87.  
  88.   *((unsigned short *)oldvector+1) = pr.x.ecx;
  89.   *((unsigned short *)oldvector) = pr.x.edx;
  90.  
  91.   pr.x.eax = 0x201;
  92.   pr.h.bl = 0x1c;
  93.   pr.x.ecx = cbseg;
  94.   pr.x.edx = cboff;
  95.   int386 (0x31, &pr, &pr);              /* Point INT 1Ch To Callback Address */
  96.  
  97.   return 0;
  98. }
  99.  
  100. int resetpassup_1C(unsigned *oldvector)
  101. {
  102.   union REGS pr;
  103.  
  104.   pr.x.eax = 0x201;
  105.   pr.h.bl = 0x1c;
  106.   pr.x.ecx = *((unsigned short *)oldvector+1);
  107.   pr.x.edx = *((unsigned short *)oldvector);
  108.   int386 (0x31, &pr, &pr);              /* Reset Old Realmode INT 1Ch Vector */
  109.  
  110.   return 0;
  111. }
  112.  
  113. /* This handler is called by the realmode INT 1Ch by way of a DPMI callback.
  114.    It takes the return address & flags from the realmode stack (DS:ESI) and
  115.    places them into the DPMI register structure (ES:EDI) so that the routine
  116.    may return to the proper place on termination. It then initiates an INT 1Ch
  117.    in protected mode before returning control with an IRETD */
  118.  
  119. #pragma off (check_stack);
  120.  
  121. void int1C_handler (void)
  122. {
  123.   intp ();
  124. }
  125.  
  126. #pragma on (check_stack);
  127.  
  128.