+ if ( !(mstate & (1<<i)) &&
+ (mouse_oldbuttonstate & (1<<i)) )
+ {
+ Key_Event (K_MOUSE1 + i, false);
+ }
+ }
+
+ mouse_oldbuttonstate = mstate;
+ }
+}
+
+
+/*
+===========
+IN_MouseMove
+===========
+*/
+void IN_MouseMove (usercmd_t *cmd)
+{
+ int i, mx, my;
+ DIDEVICEOBJECTDATA od;
+ DWORD dwElements;
+ HRESULT hr;
+
+ if (!mouseactive)
+ {
+ GetCursorPos (¤t_pos);
+ ui_mouseupdate(current_pos.x - window_x, current_pos.y - window_y);
+ return;
+ }
+
+ if (dinput)
+ {
+ mx = 0;
+ my = 0;
+
+ for (;;)
+ {
+ dwElements = 1;
+
+ hr = IDirectInputDevice_GetDeviceData(g_pMouse,
+ sizeof(DIDEVICEOBJECTDATA), &od, &dwElements, 0);
+
+ if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED))
+ {
+ dinput_acquired = true;
+ IDirectInputDevice_Acquire(g_pMouse);
+ break;
+ }
+
+ /* Unable to read data or no data available */
+ if (FAILED(hr) || dwElements == 0)
+ break;
+
+ /* Look at the element to see what happened */
+
+ switch (od.dwOfs)
+ {
+ case DIMOFS_X:
+ mx += od.dwData;
+ break;
+
+ case DIMOFS_Y:
+ my += od.dwData;
+ break;
+
+ case DIMOFS_BUTTON0:
+ if (od.dwData & 0x80)
+ mstate_di |= 1;
+ else
+ mstate_di &= ~1;
+ break;
+
+ case DIMOFS_BUTTON1:
+ if (od.dwData & 0x80)
+ mstate_di |= (1<<1);
+ else
+ mstate_di &= ~(1<<1);
+ break;
+
+ case DIMOFS_BUTTON2:
+ if (od.dwData & 0x80)
+ mstate_di |= (1<<2);
+ else
+ mstate_di &= ~(1<<2);
+ break;
+ }
+ }
+
+ // perform button actions
+ for (i=0 ; i<mouse_buttons ; i++)
+ {
+ if ( (mstate_di & (1<<i)) &&
+ !(mouse_oldbuttonstate & (1<<i)) )
+ {
+ Key_Event (K_MOUSE1 + i, true);
+ }
+
+ if ( !(mstate_di & (1<<i)) &&
+ (mouse_oldbuttonstate & (1<<i)) )
+ {
+ Key_Event (K_MOUSE1 + i, false);
+ }
+ }
+
+ mouse_oldbuttonstate = mstate_di;
+ }
+ else
+ {
+ GetCursorPos (¤t_pos);
+ mx = current_pos.x - window_center_x + mx_accum;
+ my = current_pos.y - window_center_y + my_accum;
+ mx_accum = 0;
+ my_accum = 0;
+ }
+
+ IN_Mouse(cmd, mx, my);
+
+ // if the mouse has moved, force it to the center, so there's room to move
+ if (!dinput && (mx || my))
+ SetCursorPos (window_center_x, window_center_y);
+}
+
+
+/*
+===========
+IN_Move
+===========
+*/
+void IN_Move (usercmd_t *cmd)
+{
+ if (vid_activewindow && !vid_hidden)
+ {
+ IN_MouseMove (cmd);
+ IN_JoyMove (cmd);
+ }
+}
+
+
+/*
+===========
+IN_Accumulate
+===========
+*/
+void IN_Accumulate (void)
+{
+ if (mouseactive)
+ {
+ if (!dinput)
+ {
+ GetCursorPos (¤t_pos);
+
+ mx_accum += current_pos.x - window_center_x;
+ my_accum += current_pos.y - window_center_y;
+
+ // force the mouse to the center, so there's room to move
+ SetCursorPos (window_center_x, window_center_y);
+ }
+ }
+}
+
+
+/*
+===================
+IN_ClearStates
+===================
+*/
+void IN_ClearStates (void)
+{
+ if (mouseactive)
+ {
+ mx_accum = 0;
+ my_accum = 0;
+ mouse_oldbuttonstate = 0;
+ }
+}
+
+
+/*
+===============
+IN_StartupJoystick
+===============
+*/
+void IN_StartupJoystick (void)
+{
+ int numdevs;
+ JOYCAPS jc;
+ MMRESULT mmr;
+ mmr = 0;
+
+ // assume no joystick
+ joy_avail = false;
+
+ // abort startup if user requests no joystick
+ if (COM_CheckParm ("-nojoy") || COM_CheckParm("-safe"))
+ return;
+
+ // verify joystick driver is present
+ if ((numdevs = joyGetNumDevs ()) == 0)
+ {
+ Con_Printf ("\njoystick not found -- driver not present\n\n");
+ return;
+ }
+
+ // cycle through the joystick ids for the first valid one
+ for (joy_id=0 ; joy_id<numdevs ; joy_id++)
+ {
+ memset (&ji, 0, sizeof(ji));
+ ji.dwSize = sizeof(ji);
+ ji.dwFlags = JOY_RETURNCENTERED;
+
+ if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
+ break;
+ }
+
+ // abort startup if we didn't find a valid joystick
+ if (mmr != JOYERR_NOERROR)
+ {
+ Con_Printf ("\njoystick not found -- no valid joysticks (%x)\n\n", mmr);
+ return;
+ }
+
+ // get the capabilities of the selected joystick
+ // abort startup if command fails
+ memset (&jc, 0, sizeof(jc));
+ if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
+ {
+ Con_Printf ("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr);
+ return;
+ }
+
+ // save the joystick's number of buttons and POV status
+ joy_numbuttons = jc.wNumButtons;
+ joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
+
+ // old button and POV states default to no buttons pressed
+ joy_oldbuttonstate = joy_oldpovstate = 0;
+
+ // mark the joystick as available and advanced initialization not completed
+ // this is needed as cvars are not available during initialization
+
+ joy_avail = true;
+ joy_advancedinit = false;
+
+ Con_Printf ("\njoystick detected\n\n");
+}
+
+
+/*
+===========
+RawValuePointer
+===========
+*/
+PDWORD RawValuePointer (int axis)
+{
+ switch (axis)
+ {
+ case JOY_AXIS_X:
+ return &ji.dwXpos;
+ case JOY_AXIS_Y:
+ return &ji.dwYpos;
+ case JOY_AXIS_Z:
+ return &ji.dwZpos;
+ case JOY_AXIS_R:
+ return &ji.dwRpos;
+ case JOY_AXIS_U:
+ return &ji.dwUpos;
+ case JOY_AXIS_V:
+ return &ji.dwVpos;
+ }
+ return NULL; // LordHavoc: hush compiler warning
+}
+
+
+/*
+===========
+Joy_AdvancedUpdate_f
+===========
+*/
+void Joy_AdvancedUpdate_f (void)
+{
+
+ // called once by IN_ReadJoystick and by user whenever an update is needed
+ // cvars are now available
+ int i;
+ DWORD dwTemp;
+
+ // initialize all the maps
+ for (i = 0; i < JOY_MAX_AXES; i++)
+ {
+ dwAxisMap[i] = AxisNada;
+ dwControlMap[i] = JOY_ABSOLUTE_AXIS;
+ pdwRawValue[i] = RawValuePointer(i);
+ }
+
+ if( joy_advanced.integer == 0)
+ {
+ // default joystick initialization
+ // 2 axes only with joystick control
+ dwAxisMap[JOY_AXIS_X] = AxisTurn;
+ // dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
+ dwAxisMap[JOY_AXIS_Y] = AxisForward;
+ // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
+ }
+ else
+ {
+ if (strcmp (joy_name.string, "joystick") != 0)
+ {
+ // notify user of advanced controller
+ Con_Printf ("\n%s configured\n\n", joy_name.string);
+ }
+
+ // advanced initialization here
+ // data supplied by user via joy_axisn cvars
+ dwTemp = (DWORD) joy_advaxisx.value;
+ dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
+ dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
+ dwTemp = (DWORD) joy_advaxisy.value;
+ dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
+ dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
+ dwTemp = (DWORD) joy_advaxisz.value;
+ dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
+ dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
+ dwTemp = (DWORD) joy_advaxisr.value;
+ dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
+ dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
+ dwTemp = (DWORD) joy_advaxisu.value;
+ dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
+ dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
+ dwTemp = (DWORD) joy_advaxisv.value;
+ dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
+ dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
+ }
+
+ // compute the axes to collect from DirectInput
+ joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
+ for (i = 0; i < JOY_MAX_AXES; i++)
+ {
+ if (dwAxisMap[i] != AxisNada)
+ {
+ joy_flags |= dwAxisFlags[i];
+ }
+ }
+}
+
+
+/*
+===========
+IN_Commands
+===========
+*/
+void IN_Commands (void)
+{
+ int i, key_index;
+ DWORD buttonstate, povstate;
+
+ if (!joy_avail)
+ {
+ return;
+ }
+
+
+ // loop through the joystick buttons
+ // key a joystick event or auxillary event for higher number buttons for each state change
+ buttonstate = ji.dwButtons;
+ for (i=0 ; i < (int) joy_numbuttons ; i++)
+ {
+ if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
+ {
+ key_index = (i < 4) ? K_JOY1 : K_AUX1;
+ Key_Event (key_index + i, true);
+ }
+
+ if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
+ {
+ key_index = (i < 4) ? K_JOY1 : K_AUX1;
+ Key_Event (key_index + i, false);
+ }
+ }
+ joy_oldbuttonstate = buttonstate;
+
+ if (joy_haspov)
+ {
+ // convert POV information into 4 bits of state information
+ // this avoids any potential problems related to moving from one
+ // direction to another without going through the center position
+ povstate = 0;
+ if(ji.dwPOV != JOY_POVCENTERED)
+ {
+ if (ji.dwPOV == JOY_POVFORWARD)
+ povstate |= 0x01;
+ if (ji.dwPOV == JOY_POVRIGHT)
+ povstate |= 0x02;
+ if (ji.dwPOV == JOY_POVBACKWARD)
+ povstate |= 0x04;
+ if (ji.dwPOV == JOY_POVLEFT)
+ povstate |= 0x08;
+ }
+ // determine which bits have changed and key an auxillary event for each change
+ for (i=0 ; i < 4 ; i++)
+ {
+ if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
+ {
+ Key_Event (K_AUX29 + i, true);
+ }
+
+ if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
+ {
+ Key_Event (K_AUX29 + i, false);
+ }
+ }
+ joy_oldpovstate = povstate;
+ }
+}
+
+
+/*
+===============
+IN_ReadJoystick
+===============
+*/
+qboolean IN_ReadJoystick (void)
+{
+
+ memset (&ji, 0, sizeof(ji));
+ ji.dwSize = sizeof(ji);
+ ji.dwFlags = joy_flags;
+
+ if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
+ {
+ // this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
+ // rather than having 32768 be the zero point, they have the zero point at 32668
+ // go figure -- anyway, now we get the full resolution out of the device
+ if (joy_wwhack1.integer != 0.0)
+ {
+ ji.dwUpos += 100;
+ }
+ return true;