mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 21:21:14 +00:00
networking support. Second, I moves keys.c from qw and nq to libs/video/targets when I did the next thing. Existing user configs which do binds, sledge hammer. Sledge hammer, existing user configs which do binds. *WHACK* *WHACK* *WHACK* See, much nicer now. Someone should document it, and fix all targets which don't use SDL for input. (I honestly don't expect svgalib and the like to ever be fixed.)
431 lines
12 KiB
C
431 lines
12 KiB
C
/*
|
|
joy_win.c
|
|
|
|
Joystick device driver for Win32
|
|
|
|
Copyright (C) 2000 Jeff Teunissen <deek@dusknet.dhs.org>
|
|
Copyright (C) 2000 Jukka Sorjonen <jukka.sorjone@asikkala.fi>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to:
|
|
|
|
Free Software Foundation, Inc.
|
|
59 Temple Place - Suite 330
|
|
Boston, MA 02111-1307, USA
|
|
|
|
$Id$
|
|
*/
|
|
|
|
// FIXME: THIS IS NOT FINISHED YET
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
#include <math.h>
|
|
#ifdef __MINGW32__
|
|
# define INITGUID
|
|
#endif
|
|
|
|
#define byte __byte
|
|
#include <dinput.h>
|
|
#undef byte
|
|
|
|
#include "QF/cmd.h"
|
|
#include "compat.h"
|
|
#include "QF/console.h"
|
|
#include "QF/cvar.h"
|
|
#include "QF/input.h"
|
|
#include "QF/joystick.h"
|
|
#include "QF/keys.h"
|
|
#include "QF/qargs.h"
|
|
|
|
// Joystick variables and structures
|
|
cvar_t *joy_device; // Joystick device name
|
|
cvar_t *joy_enable; // Joystick enabling flag
|
|
cvar_t *joy_sensitivity; // Joystick sensitivity
|
|
|
|
// joystick defines and variables
|
|
// where should defines be moved?
|
|
|
|
#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick
|
|
#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner,
|
|
// trackball
|
|
#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V
|
|
#define JOY_AXIS_X 0
|
|
#define JOY_AXIS_Y 1
|
|
#define JOY_AXIS_Z 2
|
|
#define JOY_AXIS_R 3
|
|
#define JOY_AXIS_U 4
|
|
#define JOY_AXIS_V 5
|
|
|
|
enum _ControlList {
|
|
AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn
|
|
};
|
|
|
|
DWORD dwAxisFlags[JOY_MAX_AXES] = {
|
|
JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV
|
|
};
|
|
|
|
DWORD dwAxisMap[JOY_MAX_AXES];
|
|
DWORD dwControlMap[JOY_MAX_AXES];
|
|
PDWORD pdwRawValue[JOY_MAX_AXES];
|
|
|
|
JOYINFOEX ji;
|
|
|
|
// none of these cvars are saved over a session
|
|
// this means that advanced controller configuration needs to be executed
|
|
// each time. this avoids any problems with getting back to a default usage
|
|
// or when changing from one controller to another. this way at least something
|
|
// works.
|
|
|
|
cvar_t *in_joystick;
|
|
cvar_t *joy_name;
|
|
cvar_t *joy_advanced;
|
|
cvar_t *joy_advaxisx;
|
|
cvar_t *joy_advaxisy;
|
|
cvar_t *joy_advaxisz;
|
|
cvar_t *joy_advaxisr;
|
|
cvar_t *joy_advaxisu;
|
|
cvar_t *joy_advaxisv;
|
|
cvar_t *joy_forwardthreshold;
|
|
cvar_t *joy_sidethreshold;
|
|
cvar_t *joy_pitchthreshold;
|
|
cvar_t *joy_yawthreshold;
|
|
cvar_t *joy_forwardsensitivity;
|
|
cvar_t *joy_sidesensitivity;
|
|
cvar_t *joy_pitchsensitivity;
|
|
cvar_t *joy_yawsensitivity;
|
|
cvar_t *joy_wwhack1;
|
|
cvar_t *joy_wwhack2;
|
|
|
|
cvar_t *joy_debug;
|
|
|
|
qboolean joy_advancedinit, joy_haspov;
|
|
DWORD joy_oldbuttonstate, joy_oldpovstate;
|
|
int joy_id;
|
|
DWORD joy_flags;
|
|
DWORD joy_numbuttons;
|
|
|
|
//
|
|
//
|
|
//
|
|
void JOY_AdvancedUpdate_f (void);
|
|
int JOY_StartupJoystick (void);
|
|
|
|
PDWORD RawValuePointer (int axis);
|
|
|
|
qboolean
|
|
_JOY_Read (void)
|
|
{
|
|
memset (&ji, 0, sizeof (ji));
|
|
ji.dwSize = sizeof (ji);
|
|
ji.dwFlags = joy_flags;
|
|
|
|
if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR) {
|
|
// HACK HACK HACK -- there's a bug in the Logitech Wingman Warrior's
|
|
// DInput driver that causes it to make 32668 the center point
|
|
// instead
|
|
// of 32768
|
|
if (joy_wwhack1->int_val) {
|
|
ji.dwUpos += 100;
|
|
}
|
|
if (joy_debug->int_val) {
|
|
if (ji.dwXpos) Con_Printf("X: %ld\n",ji.dwXpos);
|
|
if (ji.dwYpos) Con_Printf("Y: %ld\n",ji.dwYpos);
|
|
if (ji.dwZpos) Con_Printf("Z: %ld\n",ji.dwZpos);
|
|
if (ji.dwRpos) Con_Printf("R: %ld\n",ji.dwRpos);
|
|
if (ji.dwUpos) Con_Printf("U: %ld\n",ji.dwUpos);
|
|
if (ji.dwVpos) Con_Printf("V: %ld\n",ji.dwVpos);
|
|
if (ji.dwButtons) Con_Printf("B: %ld\n",ji.dwButtons);
|
|
}
|
|
return true;
|
|
} else { // read error
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void
|
|
JOY_Read (void)
|
|
{
|
|
int i, key_index;
|
|
DWORD buttonstate, povstate;
|
|
|
|
if (!joy_found) {
|
|
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 < joy_numbuttons; i++) {
|
|
if ((buttonstate & (1 << i)) && !(joy_oldbuttonstate & (1 << i))) {
|
|
Key_Event (J_BUTTON1 + i, 0, true);
|
|
}
|
|
|
|
if (!(buttonstate & (1 << i)) && (joy_oldbuttonstate & (1 << i))) {
|
|
Key_Event (J_BUTTON1 + i, 0, 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 (J_BUTTON29 + i, -1, true);
|
|
}
|
|
|
|
if (!(povstate & (1 << i)) && (joy_oldpovstate & (1 << i))) {
|
|
Key_Event (J_BUTTON29 + i, -1, false);
|
|
}
|
|
}
|
|
joy_oldpovstate = povstate;
|
|
}
|
|
}
|
|
|
|
int
|
|
JOY_Open (void)
|
|
{
|
|
return JOY_StartupJoystick();
|
|
// Cmd_AddCommand ("joyadvancedupdate", JOY_AdvancedUpdate_f, "FIXME: This appears to update the joystick poll? No Description");
|
|
}
|
|
|
|
void
|
|
JOY_Close (void)
|
|
{
|
|
}
|
|
|
|
/*
|
|
Joy_AdvancedUpdate_f
|
|
*/
|
|
void
|
|
JOY_AdvancedUpdate_f (void)
|
|
{
|
|
// called once by JOY_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->int_val) {
|
|
// 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 = joy_advaxisx->int_val;
|
|
dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisy->int_val;
|
|
dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisz->int_val;
|
|
dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisr->int_val;
|
|
dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisu->int_val;
|
|
dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisv->int_val;
|
|
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_StartupJoystick
|
|
*/
|
|
int
|
|
JOY_StartupJoystick (void)
|
|
{
|
|
int /* i, */ numdevs;
|
|
JOYCAPS jc;
|
|
MMRESULT mmr = !JOYERR_NOERROR;
|
|
|
|
// assume no joystick
|
|
joy_found = false;
|
|
|
|
// abort startup if user requests no joystick
|
|
if (COM_CheckParm ("-nojoy"))
|
|
return -1;
|
|
|
|
// verify joystick driver is present
|
|
if ((numdevs = joyGetNumDevs ()) == 0) {
|
|
Con_Printf ("\njoystick not found -- driver not present\n\n");
|
|
return -1;
|
|
}
|
|
// 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 -1;
|
|
}
|
|
// 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 -1;
|
|
}
|
|
// 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_advancedinit = false;
|
|
joy_found = true;
|
|
// FIXME: do this right
|
|
joy_active = true;
|
|
Con_Printf ("\njoystick detected\n\n");
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
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;
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
JOY_Init_Cvars(void)
|
|
{
|
|
joy_device =
|
|
Cvar_Get ("joy_device", "none", CVAR_NONE | CVAR_ROM, 0,
|
|
"Joystick device");
|
|
joy_enable =
|
|
Cvar_Get ("joy_enable", "1", CVAR_NONE | CVAR_ARCHIVE, 0,
|
|
"Joystick enable flag");
|
|
joy_sensitivity =
|
|
Cvar_Get ("joy_sensitivity", "1", CVAR_NONE | CVAR_ARCHIVE, 0,
|
|
"Joystick sensitivity");
|
|
|
|
// joystick variables
|
|
|
|
in_joystick =
|
|
Cvar_Get ("joystick", "0", CVAR_ARCHIVE, 0, "FIXME: No Description");
|
|
joy_name =
|
|
Cvar_Get ("joyname", "joystick", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_advanced =
|
|
Cvar_Get ("joyadvanced", "0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_advaxisx =
|
|
Cvar_Get ("joyadvaxisx", "0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_advaxisy =
|
|
Cvar_Get ("joyadvaxisy", "0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_advaxisz =
|
|
Cvar_Get ("joyadvaxisz", "0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_advaxisr =
|
|
Cvar_Get ("joyadvaxisr", "0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_advaxisu =
|
|
Cvar_Get ("joyadvaxisu", "0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_advaxisv =
|
|
Cvar_Get ("joyadvaxisv", "0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_forwardthreshold =
|
|
Cvar_Get ("joyforwardthreshold", "0.15", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_sidethreshold =
|
|
Cvar_Get ("joysidethreshold", "0.15", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_pitchthreshold =
|
|
Cvar_Get ("joypitchthreshold", "0.15", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_yawthreshold = Cvar_Get ("joyyawthreshold", "0.15", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_forwardsensitivity =
|
|
Cvar_Get ("joyforwardsensitivity", "-1.0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_sidesensitivity =
|
|
Cvar_Get ("joysidesensitivity", "-1.0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_pitchsensitivity =
|
|
Cvar_Get ("joypitchsensitivity", "1.0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_yawsensitivity =
|
|
Cvar_Get ("joyyawsensitivity", "-1.0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_wwhack1 = Cvar_Get ("joywwhack1", "0.0", CVAR_NONE, 0, "FIXME: No Description");
|
|
joy_wwhack2 = Cvar_Get ("joywwhack2", "0.0", CVAR_NONE, 0, "FIXME: No Description");
|
|
|
|
joy_debug = Cvar_Get ("joy_debug", "0.0", CVAR_NONE, 0, "FIXME: No Description");
|
|
|
|
return;
|
|
}
|
|
#endif
|