Advertisement
Guest User

ravmouse (external mouse driver for Hexen/Heretic)

a guest
Aug 21st, 2016
1,098
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.34 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. #include <stdlib.h>
  4. #include <mem.h>
  5. #include <i86.h>
  6. #include <process.h>
  7. #include <dos.h>
  8. #include <malloc.h>
  9. #include <io.h>
  10. #include <stdint.h>
  11.  
  12. //
  13. // From Heretic / Hexen source code, definition of the structure that an
  14. // external input driver must fill and button action flags.
  15. //
  16.  
  17. #define EBT_FIRE             1
  18. #define EBT_OPENDOOR         2
  19. #define EBT_SPEED            4
  20. #define EBT_STRAFE           8
  21. #define EBT_MAP              0x10
  22. #define EBT_INVENTORYLEFT    0x20
  23. #define EBT_INVENTORYRIGHT   0x40
  24. #define EBT_USEARTIFACT      0x80
  25. #define EBT_FLYDROP          0x100
  26. #define EBT_CENTERVIEW       0x200
  27. #define EBT_PAUSE            0x400
  28. #define EBT_WEAPONCYCLE      0x800
  29. #define EBT_JUMP             0x1000
  30.  
  31. typedef _Packed struct
  32. {
  33.   int16_t  vector;              // Interrupt vector
  34.   int8_t   moveForward;         // forward/backward (-50 to 50)
  35.   int8_t   moveSideways;        // strafe (-50 to 50)
  36.   int16_t  angleTurn;           // turning speed (640 [slow] 1280 [fast])
  37.   int16_t  angleHead;           // head angle (+2080 [left] : 0 [center] : -2048 [right])
  38.   int8_t   pitch;               // look up/down (-110 : +90)
  39.   int8_t   flyDirection;        // flyheight (+1/-1)
  40.   uint16_t buttons;             // EBT_* flags
  41. }
  42. externdata_t;
  43.  
  44. #define MOUSE_INTNUM 0x33
  45. #define MOUSE_RESET 0
  46. #define MOUSE_GETMICKEYS 11
  47. #define MOUSE_GETBUTTONS 3
  48.  
  49. #define MY_DEFAULT_INTNUM 0x64
  50. #define DEFAULT_HSENS 40
  51. #define DEFAULT_VSENS 1
  52. #define DEFAULT_DCLICKTICS 20
  53.  
  54. externdata_t extdata;
  55. void interrupt (*saved_vector) (void);
  56. int vector_is_hooked = 0;
  57. union REGPACK regs;
  58.  
  59. // these can be changed from the config file or command line
  60. int myintnum = MY_DEFAULT_INTNUM;
  61. int h_sensitivity = DEFAULT_HSENS;
  62. int v_sensitivity = DEFAULT_VSENS;
  63. int dclicktics = DEFAULT_DCLICKTICS;
  64.  
  65. #define NUM_BUTTONS 3
  66. //                                left       right         middle
  67. int clickactions[NUM_BUTTONS]  = {EBT_FIRE, EBT_STRAFE,   0};
  68. int dclickactions[NUM_BUTTONS] = {0,        EBT_OPENDOOR, EBT_CENTERVIEW};
  69.  
  70. // need to know this to time double clicks properly
  71. int ticdup;
  72.  
  73. int myargc;
  74. char **myargv;
  75.  
  76. void Error (char *error, ...)
  77. {
  78.   va_list argptr;
  79.  
  80.   if (vector_is_hooked)
  81.     _dos_setvect (myintnum, saved_vector);
  82.  
  83.   printf ("Error: ");
  84.  
  85.   va_start (argptr,error);
  86.   vprintf (error,argptr);
  87.   va_end (argptr);
  88.  
  89.   printf ("\n");
  90.   exit(-1);
  91. }
  92.  
  93. int CheckParmWithArgs(char *parm, int num_args)
  94. {
  95.   int i;
  96.  
  97.   for (i = 1; i < myargc-num_args; i++)
  98.   {
  99.     if (!stricmp(parm, myargv[i]))
  100.       return i;
  101.   }
  102.  
  103.   return 0;
  104. }
  105.  
  106. int CheckParm (char *parm)
  107. {
  108.   return CheckParmWithArgs (parm, 0);
  109. }
  110.  
  111. int InitMouse (void)
  112. {
  113.   regs.w.ax = MOUSE_RESET;
  114.   intr (MOUSE_INTNUM, &regs);
  115.  
  116.   if (regs.w.ax == 0xFFFF)
  117.     return 1; // mouse driver installed
  118.   else
  119.     return 0; // not installed
  120. }
  121.  
  122. void interrupt ControlISR (void)
  123. {
  124.   static int pitch = 0;
  125.   static int dclicktime[NUM_BUTTONS]={0,0,0};
  126.   static int dclickstate[NUM_BUTTONS]={0,0,0};
  127.   static int dclicks[NUM_BUTTONS]={0,0,0};
  128.   int mbuttons[NUM_BUTTONS]={0,0,0};
  129.   int i;
  130.   long int mxmove, mymove;
  131.  
  132.   extdata.buttons = 0;
  133.  
  134.   regs.w.ax = MOUSE_GETBUTTONS;
  135.   intr (MOUSE_INTNUM, &regs);
  136.  
  137.   if (regs.w.bx & 1) mbuttons[0] = 1;
  138.   if (regs.w.bx & 2) mbuttons[1] = 1;
  139.   if (regs.w.bx & 4) mbuttons[2] = 1;
  140.  
  141.   for (i=0; i<NUM_BUTTONS; i++)
  142.   {
  143.     if (mbuttons[i])
  144.       extdata.buttons |= clickactions[i];
  145.    
  146.     if (mbuttons[i] != dclickstate[i] && dclicktime[i] > 1)
  147.     {
  148.       dclickstate[i] = mbuttons[i];
  149.       if (dclickstate[i])
  150.         dclicks[i]++;
  151.    
  152.       if (dclicks[i]==2)
  153.       {
  154.         extdata.buttons |= dclickactions[i];
  155.     dclicks[i] = 0;
  156.       }
  157.       else
  158.         dclicktime[i] = 0;
  159.     }
  160.     else
  161.     {
  162.       dclicktime[i] += ticdup;
  163.       if (dclicktime[i] > dclicktics)
  164.       {
  165.         dclicks[i] = 0;
  166.     dclickstate[i] = 0;
  167.       }
  168.     }
  169.   }
  170.  
  171.   regs.w.ax = MOUSE_GETMICKEYS;
  172.   intr (MOUSE_INTNUM, &regs);
  173.  
  174.   extdata.angleTurn = regs.w.cx * h_sensitivity;
  175.  
  176.   // must be inverted when not strafing
  177.   if (!(extdata.buttons & EBT_STRAFE))
  178.     extdata.angleTurn = -extdata.angleTurn;
  179.        
  180.   if (extdata.buttons & EBT_CENTERVIEW)
  181.     pitch = 0;
  182.   else
  183.   {
  184.     pitch -= regs.w.dx * v_sensitivity;
  185.  
  186.     if (pitch < -110)
  187.       pitch = -110;
  188.     else if (pitch > 90)
  189.       pitch = 90;
  190.   }
  191.  
  192.   extdata.pitch = pitch;
  193.  
  194.   return;
  195. }
  196.  
  197. int main (int argc, char **argv)
  198. {
  199.   unsigned long flataddr;
  200.   unsigned char far *vector;
  201.   char *launchcmd;
  202.   char **spawnargs;
  203.   int p;
  204.  
  205.   printf ("\n"\
  206.           "RAVMOUSE - External mouse driver with mouselook for Heretic/Hexen\n"\
  207.           "by xttl@dwf, built on " __DATE__ " " __TIME__ "\n"\
  208.           "\n");
  209.  
  210.   myargc = argc;
  211.   myargv = argv;
  212.  
  213.   if (CheckParm("-?"))
  214.   {
  215.     printf ("-rmvec int......: Specify alternate interrupt vector (default 0x%02X).\n", myintnum);
  216.     printf ("-hs/-vs num.....: Change horizontal/vertical sensitivity (defaults %i/%i).\n", h_sensitivity, v_sensitivity);
  217.     printf ("-game/-exe/-exec: Specify game launch command other than \"heretic\"/\"hexen\".\n");
  218.     printf ("-dctics num.....: Change double click timing window (default is %i gametics).\n", dclicktics);
  219.     printf ("-mb#/-db# flags.: Change button single click (-mb#) or double click (-db#)\n"\
  220.             "                  action flags. Left mouse button is #1, right button is #2\n"\
  221.         "                  and middle button is #3. Defaults are MB1=fire, MB2=strafe,\n"\
  222.             "                  MB3=do nothing, DB1=do nothing, DB2=open/use, and\n"\
  223.         "                  DB3=center view.\n");
  224.  
  225.    printf ("\n"\
  226.            "Action flags: 0x0001 = fire              0x0002 = use\n"\
  227.            "              0x0004 = run               0x0008 = strafe\n"\
  228.            "              0x0010 = automap           0x0020 = inventory left\n"\
  229.            "              0x0040 = inventory right   0x0080 = use artifact\n"\
  230.            "              0x0100 = stop flying       0x0200 = center view\n"\
  231.            "              0x0400 = toggle pause      0x0800 = cycle weapons\n"\
  232.            "              0x1000 = jump (Hexen only) \n"\
  233.            " * Flags can be added together if you want to bind multiple actions to a\n"\
  234.            "   single mouse button. For example: -mb3 0x81 = fire AND use artifact\n"\
  235.            "   when you press the middle button.\n");
  236.  
  237.     return -1;
  238.   }
  239.  
  240.   if (!InitMouse())
  241.     Error ("Mouse driver not detected.");
  242.    
  243.   // must know this to time double clicks properly
  244.   p = CheckParmWithArgs("-dup", 1);
  245.   if (p)
  246.     sscanf(myargv[p+1], "%i", &ticdup);
  247.   else
  248.     ticdup = 1;
  249.    
  250.   p = CheckParmWithArgs("-dctics", 1);
  251.   if (p)
  252.     dclicktics = atoi(myargv[p+1]);
  253.  
  254.   p = CheckParmWithArgs("-rmvec", 1);
  255.   if (p)
  256.     sscanf(myargv[p+1], "0x%x", &myintnum);
  257.  
  258.   p = CheckParmWithArgs("-hs",1);
  259.   if (p)
  260.     h_sensitivity = atoi(myargv[p+1]);
  261.  
  262.   p = CheckParmWithArgs("-vs", 1);
  263.   if (p)
  264.     v_sensitivity = atoi(myargv[p+1]);
  265.  
  266.   p = CheckParmWithArgs("-mb1",1);
  267.   if (p) sscanf(myargv[p+1], "0x%x", &clickactions[0]);
  268.   p = CheckParmWithArgs("-mb2",1);
  269.   if (p) sscanf(myargv[p+1], "0x%x", &clickactions[1]);
  270.   p = CheckParmWithArgs("-mb3",1);
  271.   if (p) sscanf(myargv[p+1], "0x%x", &clickactions[2]);
  272.  
  273.   p = CheckParmWithArgs("-db1",1);
  274.   if (p) sscanf(myargv[p+1], "0x%x", &dclickactions[0]);
  275.   p = CheckParmWithArgs("-db2",1);
  276.   if (p) sscanf(myargv[p+1], "0x%x", &dclickactions[1]);
  277.   p = CheckParmWithArgs("-db3",1);
  278.   if (p) sscanf(myargv[p+1], "0x%x", &dclickactions[2]);
  279.  
  280.   memset (&extdata, 0, sizeof(externdata_t));
  281.   extdata.vector = myintnum;
  282.  
  283.   // add extra args for passing the address of the buffer to the game
  284.   // and also to disable the game's internal mouse support
  285.   spawnargs = malloc ((myargc+4)*sizeof(char*));
  286.   memcpy (spawnargs, myargv, myargc*sizeof(char*));
  287.   spawnargs[myargc] = "-externdriver";
  288.   spawnargs[myargc+1] = alloca(32);
  289.   flataddr = (long)FP_SEG(&extdata)*16 + (unsigned)(&extdata);
  290.   sprintf (spawnargs[myargc+1], "%li", flataddr);
  291.   spawnargs[myargc+2] = "-nomouse";
  292.   spawnargs[myargc+3] = NULL;
  293.  
  294.   // custom game launch command specified?
  295.   p = CheckParmWithArgs("-exec", 1);
  296.   if (!p) p = CheckParmWithArgs("-game", 1);
  297.   if (!p) p = CheckParmWithArgs("-exe", 1);
  298.  
  299.   if (p)
  300.     launchcmd = myargv[p+1];
  301.   // else try the defaults
  302.   else
  303.   {
  304.     if (!access("HERETIC.EXE", 0) || !access("HERETIC.COM", 0))
  305.       launchcmd = "heretic";
  306.     else if (!access("HEXEN.EXE", 0) || !access("HEXEN.COM", 0))
  307.       launchcmd = "hexen";
  308.     else
  309.     {
  310.       Error ("No Heretic or Hexen executables in current directory and no\n"\
  311.              "alternate launch command was specified.");
  312.     }
  313.   }
  314.  
  315.   // hook the interrupt
  316.   vector = *(char far * far *)(myintnum*4);
  317.   if (vector != NULL && *vector != 0xCF) // 0xCF = x86 IRET
  318.     Error ("Interrupt vector 0x%02X is already hooked.", myintnum);
  319.  
  320.   saved_vector = _dos_getvect (myintnum);
  321.   _dos_setvect (myintnum, (void interrupt (*)(void))MK_FP(FP_SEG(ControlISR),(int)ControlISR));
  322.   vector_is_hooked = 1;
  323.  
  324.   // launch the game
  325.   if (spawnv (P_WAIT, launchcmd, (const char **)spawnargs) == -1)
  326.     printf ("spawnv(%s) failed: %i (%s)\n", launchcmd, errno, strerror(errno));
  327.  
  328.   // restore interrupt
  329.   _dos_setvect (myintnum, saved_vector);
  330.  
  331.   return 0;
  332. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement