mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
bff0847761
The misinterpretations were due to either the cvar not being accessed directly by the engine, but via only the callback, or the cvars were accesssed only by progs (in which case, they should be float). The remainder are a potential enum (hud gravity) and a "too hard basket" (rcon password: need to figure out how I want to handle secret strings).
550 lines
14 KiB
C
550 lines
14 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
|
|
|
|
*/
|
|
// FIXME: THIS IS NOT FINISHED YET
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <math.h>
|
|
|
|
#include "winquake.h"
|
|
|
|
#include "QF/cmd.h"
|
|
#include "QF/cvar.h"
|
|
#include "QF/input.h"
|
|
#include "QF/joystick.h"
|
|
#include "QF/keys.h"
|
|
#include "QF/qargs.h"
|
|
#include "QF/sys.h"
|
|
|
|
#include "compat.h"
|
|
|
|
// Joystick variables and structures
|
|
float joy_sensitivity;
|
|
static cvar_t joy_sensitivity_cvar = {
|
|
.name = "joy_sensitivity",
|
|
.description =
|
|
"Joystick sensitivity",
|
|
.default_value = "1",
|
|
.flags = CVAR_ARCHIVE,
|
|
.value = { .type = &cexpr_float, .value = &joy_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_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.
|
|
|
|
char *in_joystick;
|
|
static cvar_t in_joystick_cvar = {
|
|
.name = "joystick",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_ARCHIVE,
|
|
.value = { .type = 0, .value = &in_joystick },
|
|
};
|
|
char *joy_name;
|
|
static cvar_t joy_name_cvar = {
|
|
.name = "joyname",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "joystick",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = 0, .value = &joy_name },
|
|
};
|
|
int joy_advanced;
|
|
static cvar_t joy_advanced_cvar = {
|
|
.name = "joyadvanced",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_advanced },
|
|
};
|
|
int joy_advaxisx;
|
|
static cvar_t joy_advaxisx_cvar = {
|
|
.name = "joyadvaxisx",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_advaxisx },
|
|
};
|
|
int joy_advaxisy;
|
|
static cvar_t joy_advaxisy_cvar = {
|
|
.name = "joyadvaxisy",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_advaxisy },
|
|
};
|
|
int joy_advaxisz;
|
|
static cvar_t joy_advaxisz_cvar = {
|
|
.name = "joyadvaxisz",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_advaxisz },
|
|
};
|
|
int joy_advaxisr;
|
|
static cvar_t joy_advaxisr_cvar = {
|
|
.name = "joyadvaxisr",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_advaxisr },
|
|
};
|
|
int joy_advaxisu;
|
|
static cvar_t joy_advaxisu_cvar = {
|
|
.name = "joyadvaxisu",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_advaxisu },
|
|
};
|
|
int joy_advaxisv;
|
|
static cvar_t joy_advaxisv_cvar = {
|
|
.name = "joyadvaxisv",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_advaxisv },
|
|
};
|
|
float joy_forwardthreshold;
|
|
static cvar_t joy_forwardthreshold_cvar = {
|
|
.name = "joyforwardthreshold",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0.15",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_forwardthreshold },
|
|
};
|
|
float joy_sidethreshold;
|
|
static cvar_t joy_sidethreshold_cvar = {
|
|
.name = "joysidethreshold",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0.15",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_sidethreshold },
|
|
};
|
|
float joy_pitchthreshold;
|
|
static cvar_t joy_pitchthreshold_cvar = {
|
|
.name = "joypitchthreshold",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0.15",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_pitchthreshold },
|
|
};
|
|
float joy_yawthreshold;
|
|
static cvar_t joy_yawthreshold_cvar = {
|
|
.name = "joyyawthreshold",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0.15",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_yawthreshold },
|
|
};
|
|
float joy_forwardsensitivity;
|
|
static cvar_t joy_forwardsensitivity_cvar = {
|
|
.name = "joyforwardsensitivity",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "-1.0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_forwardsensitivity },
|
|
};
|
|
float joy_sidesensitivity;
|
|
static cvar_t joy_sidesensitivity_cvar = {
|
|
.name = "joysidesensitivity",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "-1.0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_sidesensitivity },
|
|
};
|
|
float joy_pitchsensitivity;
|
|
static cvar_t joy_pitchsensitivity_cvar = {
|
|
.name = "joypitchsensitivity",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "1.0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_pitchsensitivity },
|
|
};
|
|
float joy_yawsensitivity;
|
|
static cvar_t joy_yawsensitivity_cvar = {
|
|
.name = "joyyawsensitivity",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "-1.0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_yawsensitivity },
|
|
};
|
|
int joy_wwhack1;
|
|
static cvar_t joy_wwhack1_cvar = {
|
|
.name = "joywwhack1",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0.0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_wwhack1 },
|
|
};
|
|
float joy_wwhack2;
|
|
static cvar_t joy_wwhack2_cvar = {
|
|
.name = "joywwhack2",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0.0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_float, .value = &joy_wwhack2 },
|
|
};
|
|
|
|
int joy_debug;
|
|
static cvar_t joy_debug_cvar = {
|
|
.name = "joy_debug",
|
|
.description =
|
|
"FIXME: No Description",
|
|
.default_value = "0.0",
|
|
.flags = CVAR_NONE,
|
|
.value = { .type = &cexpr_int, .value = &joy_debug },
|
|
};
|
|
|
|
qboolean joy_advancedinit, joy_haspov;
|
|
DWORD joy_oldbuttonstate, joy_oldpovstate;
|
|
int joy_id;
|
|
DWORD joy_flags;
|
|
DWORD joy_numbuttons;
|
|
#if 0
|
|
static 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;
|
|
}
|
|
|
|
static 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) {
|
|
ji.dwUpos += 100;
|
|
}
|
|
if (joy_debug) {
|
|
if (ji.dwXpos) Sys_Printf("X: %ld\n",ji.dwXpos);
|
|
if (ji.dwYpos) Sys_Printf("Y: %ld\n",ji.dwYpos);
|
|
if (ji.dwZpos) Sys_Printf("Z: %ld\n",ji.dwZpos);
|
|
if (ji.dwRpos) Sys_Printf("R: %ld\n",ji.dwRpos);
|
|
if (ji.dwUpos) Sys_Printf("U: %ld\n",ji.dwUpos);
|
|
if (ji.dwVpos) Sys_Printf("V: %ld\n",ji.dwVpos);
|
|
if (ji.dwButtons) Sys_Printf("B: %ld\n",ji.dwButtons);
|
|
}
|
|
return true;
|
|
} else { // read error
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
void
|
|
JOY_Read (void)
|
|
{
|
|
DWORD i;
|
|
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 (QFJ_BUTTON1 + i, 0, true);
|
|
}
|
|
|
|
if (!(buttonstate & (1 << i)) && (joy_oldbuttonstate & (1 << i))) {
|
|
Key_Event (QFJ_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 (QFJ_BUTTON29 + i, -1, true);
|
|
}
|
|
|
|
if (!(povstate & (1 << i)) && (joy_oldpovstate & (1 << i))) {
|
|
Key_Event (QFJ_BUTTON29 + i, -1, false);
|
|
}
|
|
}
|
|
joy_oldpovstate = povstate;
|
|
}
|
|
}
|
|
|
|
static 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) {
|
|
Sys_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) {
|
|
Sys_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) {
|
|
Sys_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;
|
|
Sys_Printf ("\njoystick detected\n\n");
|
|
return 0;
|
|
}
|
|
|
|
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)
|
|
{
|
|
}
|
|
#if 0
|
|
static 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) {
|
|
// default joystick initialization
|
|
// only 2 axes 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, "joystick") != 0) {
|
|
// notify user of advanced controller
|
|
Sys_Printf ("\n%s configured\n\n", joy_name);
|
|
}
|
|
// advanced initialization here
|
|
// data supplied by user via joy_axisn cvars
|
|
dwTemp = joy_advaxisx;
|
|
dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisy;
|
|
dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisz;
|
|
dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisr;
|
|
dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisu;
|
|
dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
|
|
dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
|
|
dwTemp = joy_advaxisv;
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
JOY_Init_Cvars(void)
|
|
{
|
|
// joystick variables
|
|
Cvar_Register (&joy_device_cvar, 0, 0);
|
|
Cvar_Register (&joy_enable_cvar, 0, 0);
|
|
Cvar_Register (&joy_sensitivity_cvar, 0, 0);
|
|
Cvar_Register (&in_joystick_cvar, 0, 0);
|
|
Cvar_Register (&joy_name_cvar, 0, 0);
|
|
Cvar_Register (&joy_advanced_cvar, 0, 0);
|
|
Cvar_Register (&joy_advaxisx_cvar, 0, 0);
|
|
Cvar_Register (&joy_advaxisy_cvar, 0, 0);
|
|
Cvar_Register (&joy_advaxisz_cvar, 0, 0);
|
|
Cvar_Register (&joy_advaxisr_cvar, 0, 0);
|
|
Cvar_Register (&joy_advaxisu_cvar, 0, 0);
|
|
Cvar_Register (&joy_advaxisv_cvar, 0, 0);
|
|
Cvar_Register (&joy_forwardthreshold_cvar, 0, 0);
|
|
Cvar_Register (&joy_sidethreshold_cvar, 0, 0);
|
|
Cvar_Register (&joy_pitchthreshold_cvar, 0, 0);
|
|
Cvar_Register (&joy_yawthreshold_cvar, 0, 0);
|
|
Cvar_Register (&joy_forwardsensitivity_cvar, 0, 0);
|
|
Cvar_Register (&joy_sidesensitivity_cvar, 0, 0);
|
|
Cvar_Register (&joy_pitchsensitivity_cvar, 0, 0);
|
|
Cvar_Register (&joy_yawsensitivity_cvar, 0, 0);
|
|
Cvar_Register (&joy_wwhack1_cvar, 0, 0);
|
|
Cvar_Register (&joy_wwhack2_cvar, 0, 0);
|
|
|
|
Cvar_Register (&joy_debug_cvar, 0, 0);
|
|
return;
|
|
}
|
|
#endif
|