quakeforge/libs/video/targets/joy_win.c
Bill Currie bff0847761 [cvar] Clean up most misinterpreted cvar types
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).
2022-04-24 20:04:06 +09:00

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