Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <mem.h>
- #include <i86.h>
- #include <process.h>
- #include <dos.h>
- #include <malloc.h>
- #include <io.h>
- #include <stdint.h>
- //
- // From Heretic / Hexen source code, definition of the structure that an
- // external input driver must fill and button action flags.
- //
- #define EBT_FIRE 1
- #define EBT_OPENDOOR 2
- #define EBT_SPEED 4
- #define EBT_STRAFE 8
- #define EBT_MAP 0x10
- #define EBT_INVENTORYLEFT 0x20
- #define EBT_INVENTORYRIGHT 0x40
- #define EBT_USEARTIFACT 0x80
- #define EBT_FLYDROP 0x100
- #define EBT_CENTERVIEW 0x200
- #define EBT_PAUSE 0x400
- #define EBT_WEAPONCYCLE 0x800
- #define EBT_JUMP 0x1000
- typedef _Packed struct
- {
- int16_t vector; // Interrupt vector
- int8_t moveForward; // forward/backward (-50 to 50)
- int8_t moveSideways; // strafe (-50 to 50)
- int16_t angleTurn; // turning speed (640 [slow] 1280 [fast])
- int16_t angleHead; // head angle (+2080 [left] : 0 [center] : -2048 [right])
- int8_t pitch; // look up/down (-110 : +90)
- int8_t flyDirection; // flyheight (+1/-1)
- uint16_t buttons; // EBT_* flags
- }
- externdata_t;
- #define MOUSE_INTNUM 0x33
- #define MOUSE_RESET 0
- #define MOUSE_GETMICKEYS 11
- #define MOUSE_GETBUTTONS 3
- #define MY_DEFAULT_INTNUM 0x64
- #define DEFAULT_HSENS 40
- #define DEFAULT_VSENS 1
- #define DEFAULT_DCLICKTICS 20
- externdata_t extdata;
- void interrupt (*saved_vector) (void);
- int vector_is_hooked = 0;
- union REGPACK regs;
- // these can be changed from the config file or command line
- int myintnum = MY_DEFAULT_INTNUM;
- int h_sensitivity = DEFAULT_HSENS;
- int v_sensitivity = DEFAULT_VSENS;
- int dclicktics = DEFAULT_DCLICKTICS;
- #define NUM_BUTTONS 3
- // left right middle
- int clickactions[NUM_BUTTONS] = {EBT_FIRE, EBT_STRAFE, 0};
- int dclickactions[NUM_BUTTONS] = {0, EBT_OPENDOOR, EBT_CENTERVIEW};
- // need to know this to time double clicks properly
- int ticdup;
- int myargc;
- char **myargv;
- void Error (char *error, ...)
- {
- va_list argptr;
- if (vector_is_hooked)
- _dos_setvect (myintnum, saved_vector);
- printf ("Error: ");
- va_start (argptr,error);
- vprintf (error,argptr);
- va_end (argptr);
- printf ("\n");
- exit(-1);
- }
- int CheckParmWithArgs(char *parm, int num_args)
- {
- int i;
- for (i = 1; i < myargc-num_args; i++)
- {
- if (!stricmp(parm, myargv[i]))
- return i;
- }
- return 0;
- }
- int CheckParm (char *parm)
- {
- return CheckParmWithArgs (parm, 0);
- }
- int InitMouse (void)
- {
- regs.w.ax = MOUSE_RESET;
- intr (MOUSE_INTNUM, ®s);
- if (regs.w.ax == 0xFFFF)
- return 1; // mouse driver installed
- else
- return 0; // not installed
- }
- void interrupt ControlISR (void)
- {
- static int pitch = 0;
- static int dclicktime[NUM_BUTTONS]={0,0,0};
- static int dclickstate[NUM_BUTTONS]={0,0,0};
- static int dclicks[NUM_BUTTONS]={0,0,0};
- int mbuttons[NUM_BUTTONS]={0,0,0};
- int i;
- long int mxmove, mymove;
- extdata.buttons = 0;
- regs.w.ax = MOUSE_GETBUTTONS;
- intr (MOUSE_INTNUM, ®s);
- if (regs.w.bx & 1) mbuttons[0] = 1;
- if (regs.w.bx & 2) mbuttons[1] = 1;
- if (regs.w.bx & 4) mbuttons[2] = 1;
- for (i=0; i<NUM_BUTTONS; i++)
- {
- if (mbuttons[i])
- extdata.buttons |= clickactions[i];
- if (mbuttons[i] != dclickstate[i] && dclicktime[i] > 1)
- {
- dclickstate[i] = mbuttons[i];
- if (dclickstate[i])
- dclicks[i]++;
- if (dclicks[i]==2)
- {
- extdata.buttons |= dclickactions[i];
- dclicks[i] = 0;
- }
- else
- dclicktime[i] = 0;
- }
- else
- {
- dclicktime[i] += ticdup;
- if (dclicktime[i] > dclicktics)
- {
- dclicks[i] = 0;
- dclickstate[i] = 0;
- }
- }
- }
- regs.w.ax = MOUSE_GETMICKEYS;
- intr (MOUSE_INTNUM, ®s);
- extdata.angleTurn = regs.w.cx * h_sensitivity;
- // must be inverted when not strafing
- if (!(extdata.buttons & EBT_STRAFE))
- extdata.angleTurn = -extdata.angleTurn;
- if (extdata.buttons & EBT_CENTERVIEW)
- pitch = 0;
- else
- {
- pitch -= regs.w.dx * v_sensitivity;
- if (pitch < -110)
- pitch = -110;
- else if (pitch > 90)
- pitch = 90;
- }
- extdata.pitch = pitch;
- return;
- }
- int main (int argc, char **argv)
- {
- unsigned long flataddr;
- unsigned char far *vector;
- char *launchcmd;
- char **spawnargs;
- int p;
- printf ("\n"\
- "RAVMOUSE - External mouse driver with mouselook for Heretic/Hexen\n"\
- "by xttl@dwf, built on " __DATE__ " " __TIME__ "\n"\
- "\n");
- myargc = argc;
- myargv = argv;
- if (CheckParm("-?"))
- {
- printf ("-rmvec int......: Specify alternate interrupt vector (default 0x%02X).\n", myintnum);
- printf ("-hs/-vs num.....: Change horizontal/vertical sensitivity (defaults %i/%i).\n", h_sensitivity, v_sensitivity);
- printf ("-game/-exe/-exec: Specify game launch command other than \"heretic\"/\"hexen\".\n");
- printf ("-dctics num.....: Change double click timing window (default is %i gametics).\n", dclicktics);
- printf ("-mb#/-db# flags.: Change button single click (-mb#) or double click (-db#)\n"\
- " action flags. Left mouse button is #1, right button is #2\n"\
- " and middle button is #3. Defaults are MB1=fire, MB2=strafe,\n"\
- " MB3=do nothing, DB1=do nothing, DB2=open/use, and\n"\
- " DB3=center view.\n");
- printf ("\n"\
- "Action flags: 0x0001 = fire 0x0002 = use\n"\
- " 0x0004 = run 0x0008 = strafe\n"\
- " 0x0010 = automap 0x0020 = inventory left\n"\
- " 0x0040 = inventory right 0x0080 = use artifact\n"\
- " 0x0100 = stop flying 0x0200 = center view\n"\
- " 0x0400 = toggle pause 0x0800 = cycle weapons\n"\
- " 0x1000 = jump (Hexen only) \n"\
- " * Flags can be added together if you want to bind multiple actions to a\n"\
- " single mouse button. For example: -mb3 0x81 = fire AND use artifact\n"\
- " when you press the middle button.\n");
- return -1;
- }
- if (!InitMouse())
- Error ("Mouse driver not detected.");
- // must know this to time double clicks properly
- p = CheckParmWithArgs("-dup", 1);
- if (p)
- sscanf(myargv[p+1], "%i", &ticdup);
- else
- ticdup = 1;
- p = CheckParmWithArgs("-dctics", 1);
- if (p)
- dclicktics = atoi(myargv[p+1]);
- p = CheckParmWithArgs("-rmvec", 1);
- if (p)
- sscanf(myargv[p+1], "0x%x", &myintnum);
- p = CheckParmWithArgs("-hs",1);
- if (p)
- h_sensitivity = atoi(myargv[p+1]);
- p = CheckParmWithArgs("-vs", 1);
- if (p)
- v_sensitivity = atoi(myargv[p+1]);
- p = CheckParmWithArgs("-mb1",1);
- if (p) sscanf(myargv[p+1], "0x%x", &clickactions[0]);
- p = CheckParmWithArgs("-mb2",1);
- if (p) sscanf(myargv[p+1], "0x%x", &clickactions[1]);
- p = CheckParmWithArgs("-mb3",1);
- if (p) sscanf(myargv[p+1], "0x%x", &clickactions[2]);
- p = CheckParmWithArgs("-db1",1);
- if (p) sscanf(myargv[p+1], "0x%x", &dclickactions[0]);
- p = CheckParmWithArgs("-db2",1);
- if (p) sscanf(myargv[p+1], "0x%x", &dclickactions[1]);
- p = CheckParmWithArgs("-db3",1);
- if (p) sscanf(myargv[p+1], "0x%x", &dclickactions[2]);
- memset (&extdata, 0, sizeof(externdata_t));
- extdata.vector = myintnum;
- // add extra args for passing the address of the buffer to the game
- // and also to disable the game's internal mouse support
- spawnargs = malloc ((myargc+4)*sizeof(char*));
- memcpy (spawnargs, myargv, myargc*sizeof(char*));
- spawnargs[myargc] = "-externdriver";
- spawnargs[myargc+1] = alloca(32);
- flataddr = (long)FP_SEG(&extdata)*16 + (unsigned)(&extdata);
- sprintf (spawnargs[myargc+1], "%li", flataddr);
- spawnargs[myargc+2] = "-nomouse";
- spawnargs[myargc+3] = NULL;
- // custom game launch command specified?
- p = CheckParmWithArgs("-exec", 1);
- if (!p) p = CheckParmWithArgs("-game", 1);
- if (!p) p = CheckParmWithArgs("-exe", 1);
- if (p)
- launchcmd = myargv[p+1];
- // else try the defaults
- else
- {
- if (!access("HERETIC.EXE", 0) || !access("HERETIC.COM", 0))
- launchcmd = "heretic";
- else if (!access("HEXEN.EXE", 0) || !access("HEXEN.COM", 0))
- launchcmd = "hexen";
- else
- {
- Error ("No Heretic or Hexen executables in current directory and no\n"\
- "alternate launch command was specified.");
- }
- }
- // hook the interrupt
- vector = *(char far * far *)(myintnum*4);
- if (vector != NULL && *vector != 0xCF) // 0xCF = x86 IRET
- Error ("Interrupt vector 0x%02X is already hooked.", myintnum);
- saved_vector = _dos_getvect (myintnum);
- _dos_setvect (myintnum, (void interrupt (*)(void))MK_FP(FP_SEG(ControlISR),(int)ControlISR));
- vector_is_hooked = 1;
- // launch the game
- if (spawnv (P_WAIT, launchcmd, (const char **)spawnargs) == -1)
- printf ("spawnv(%s) failed: %i (%s)\n", launchcmd, errno, strerror(errno));
- // restore interrupt
- _dos_setvect (myintnum, saved_vector);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement