Merge pull request #4168 from lemondrops/joystick

Fixes and enhancements to joystick support
This commit is contained in:
Miran Grča
2024-02-18 16:39:51 +01:00
committed by GitHub
17 changed files with 210 additions and 292 deletions

View File

@@ -31,10 +31,6 @@
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/isapnp.h> #include <86box/isapnp.h>
#include <86box/gameport.h> #include <86box/gameport.h>
#include <86box/joystick_ch_flightstick_pro.h>
#include <86box/joystick_standard.h>
#include <86box/joystick_sw_pad.h>
#include <86box/joystick_tm_fcs.h>
#include <86box/plat_unused.h> #include <86box/plat_unused.h>
typedef struct g_axis_t { typedef struct g_axis_t {

View File

@@ -43,7 +43,6 @@
#include <86box/device.h> #include <86box/device.h>
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/gameport.h> #include <86box/gameport.h>
#include <86box/joystick_standard.h>
#include <86box/plat_unused.h> #include <86box/plat_unused.h>
static void * static void *

View File

@@ -43,7 +43,6 @@
#include <86box/device.h> #include <86box/device.h>
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/gameport.h> #include <86box/gameport.h>
#include <86box/joystick_standard.h>
#include <86box/plat_unused.h> #include <86box/plat_unused.h>
static void * static void *

View File

@@ -64,7 +64,6 @@
#include <86box/device.h> #include <86box/device.h>
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/gameport.h> #include <86box/gameport.h>
#include <86box/joystick_sw_pad.h>
#include <86box/plat_unused.h> #include <86box/plat_unused.h>
typedef struct sw_data { typedef struct sw_data {

View File

@@ -43,7 +43,6 @@
#include <86box/device.h> #include <86box/device.h>
#include <86box/timer.h> #include <86box/timer.h>
#include <86box/gameport.h> #include <86box/gameport.h>
#include <86box/joystick_standard.h>
#include <86box/plat_unused.h> #include <86box/plat_unused.h>
static void * static void *

View File

@@ -24,6 +24,10 @@
#define MAX_PLAT_JOYSTICKS 8 #define MAX_PLAT_JOYSTICKS 8
#define MAX_JOYSTICKS 4 #define MAX_JOYSTICKS 4
#define MAX_JOY_AXES 16
#define MAX_JOY_BUTTONS 32
#define MAX_JOY_POVS 4
#define JS_TYPE_NONE 0 #define JS_TYPE_NONE 0
#define JS_TYPE_2AXIS_4BUTTON 1 #define JS_TYPE_2AXIS_4BUTTON 1
#define JS_TYPE_2AXIS_6BUTTON 2 #define JS_TYPE_2AXIS_6BUTTON 2
@@ -36,7 +40,6 @@
#define POV_X 0x80000000 #define POV_X 0x80000000
#define POV_Y 0x40000000 #define POV_Y 0x40000000
#define SLIDER 0x20000000
#define AXIS_NOT_PRESENT -99999 #define AXIS_NOT_PRESENT -99999
@@ -47,46 +50,39 @@
typedef struct plat_joystick_t { typedef struct plat_joystick_t {
char name[260]; char name[260];
int a[8]; int a[MAX_JOY_AXES];
int b[32]; int b[MAX_JOY_BUTTONS];
int p[4]; int p[MAX_JOY_POVS];
int s[2];
struct { struct {
char name[260]; char name[260];
int id; int id;
} axis[8]; } axis[MAX_JOY_AXES];
struct { struct {
char name[260]; char name[260];
int id; int id;
} button[32]; } button[MAX_JOY_BUTTONS];
struct { struct {
char name[260]; char name[260];
int id; int id;
} pov[4]; } pov[MAX_JOY_POVS];
struct {
char name[260];
int id;
} slider[2];
int nr_axes; int nr_axes;
int nr_buttons; int nr_buttons;
int nr_povs; int nr_povs;
int nr_sliders;
} plat_joystick_t; } plat_joystick_t;
typedef struct joystick_t { typedef struct joystick_t {
int axis[8]; int axis[MAX_JOY_AXES];
int button[32]; int button[MAX_JOY_BUTTONS];
int pov[4]; int pov[MAX_JOY_POVS];
int plat_joystick_nr; int plat_joystick_nr;
int axis_mapping[8]; int axis_mapping[MAX_JOY_AXES];
int button_mapping[32]; int button_mapping[MAX_JOY_BUTTONS];
int pov_mapping[4][2]; int pov_mapping[MAX_JOY_POVS][2];
} joystick_t; } joystick_t;
typedef struct joystick_if_t { typedef struct joystick_if_t {
@@ -104,9 +100,9 @@ typedef struct joystick_if_t {
int button_count; int button_count;
int pov_count; int pov_count;
int max_joysticks; int max_joysticks;
const char *axis_names[8]; const char *axis_names[MAX_JOY_AXES];
const char *button_names[32]; const char *button_names[MAX_JOY_BUTTONS];
const char *pov_names[4]; const char *pov_names[MAX_JOY_POVS];
} joystick_if_t; } joystick_if_t;
#ifdef __cplusplus #ifdef __cplusplus
@@ -158,6 +154,19 @@ extern void gameport_update_joystick_type(void);
extern void gameport_remap(void *priv, uint16_t address); extern void gameport_remap(void *priv, uint16_t address);
extern void *gameport_add(const device_t *gameport_type); extern void *gameport_add(const device_t *gameport_type);
extern const joystick_if_t joystick_2axis_2button;
extern const joystick_if_t joystick_2axis_4button;
extern const joystick_if_t joystick_3axis_2button;
extern const joystick_if_t joystick_3axis_4button;
extern const joystick_if_t joystick_4axis_4button;
extern const joystick_if_t joystick_2axis_6button;
extern const joystick_if_t joystick_2axis_8button;
extern const joystick_if_t joystick_ch_flightstick_pro;
extern const joystick_if_t joystick_sw_pad;
extern const joystick_if_t joystick_tm_fcs;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -1,43 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the Flight Stick Pro driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* 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 the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H
#define EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H
extern const joystick_if_t joystick_ch_flightstick_pro;
#endif /*EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H*/

View File

@@ -1,49 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the joystick driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* 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 the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_STANDARD_H
#define EMU_JOYSTICK_STANDARD_H
extern const joystick_if_t joystick_2axis_2button;
extern const joystick_if_t joystick_2axis_4button;
extern const joystick_if_t joystick_3axis_2button;
extern const joystick_if_t joystick_3axis_4button;
extern const joystick_if_t joystick_4axis_4button;
extern const joystick_if_t joystick_2axis_6button;
extern const joystick_if_t joystick_2axis_8button;
#endif /*EMU_JOYSTICK_STANDARD_H*/

View File

@@ -1,43 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the Sidewinder Pro driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* 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 the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_SW_PAD_H
#define EMU_JOYSTICK_SW_PAD_H
extern const joystick_if_t joystick_sw_pad;
#endif /*EMU_JOYSTICK_SW_PAD_H*/

View File

@@ -1,43 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for the Flight Control System driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* 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 the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_TM_FCS_H
#define EMU_JOYSTICK_TM_FCS_H
extern const joystick_if_t joystick_tm_fcs;
#endif /*EMU_JOYSTICK_TM_FCS_H*/

View File

@@ -118,19 +118,12 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index)
Models::AddEntry(model, QString("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); Models::AddEntry(model, QString("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0);
} }
for (int d = 0; d < plat_joystick_state[joystick].nr_sliders; d++) {
Models::AddEntry(model, plat_joystick_state[joystick].slider[d].name, 0);
}
int nr_axes = plat_joystick_state[joystick].nr_axes; int nr_axes = plat_joystick_state[joystick].nr_axes;
int nr_povs = plat_joystick_state[joystick].nr_povs;
int mapping = joystick_state[joystick_nr].axis_mapping[c]; int mapping = joystick_state[joystick_nr].axis_mapping[c];
if (mapping & POV_X) if (mapping & POV_X)
cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2); cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2);
else if (mapping & POV_Y) else if (mapping & POV_Y)
cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2 + 1); cbox->setCurrentIndex(nr_axes + (mapping & 3) * 2 + 1);
else if (mapping & SLIDER)
cbox->setCurrentIndex(nr_axes + nr_povs * 2 + (mapping & 3));
else else
cbox->setCurrentIndex(mapping); cbox->setCurrentIndex(mapping);

View File

@@ -137,22 +137,16 @@ get_axis(JoystickConfiguration &jc, int axis, int joystick_nr)
{ {
int axis_sel = jc.selectedAxis(axis); int axis_sel = jc.selectedAxis(axis);
int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes;
int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs;
if (axis_sel < nr_axes) { if (axis_sel < nr_axes) {
return axis_sel; return axis_sel;
} }
axis_sel -= nr_axes; axis_sel -= nr_axes;
if (axis_sel < nr_povs * 2) { if (axis_sel & 1)
if (axis_sel & 1) return POV_Y | (axis_sel >> 1);
return POV_Y | (axis_sel >> 1); else
else return POV_X | (axis_sel >> 1);
return POV_X | (axis_sel >> 1);
}
axis_sel -= nr_povs;
return SLIDER | (axis_sel >> 1);
} }
static int static int

View File

@@ -36,19 +36,19 @@ joystick_init()
int d; int d;
strncpy(plat_joystick_state[c].name, SDL_JoystickNameForIndex(c), 64); strncpy(plat_joystick_state[c].name, SDL_JoystickNameForIndex(c), 64);
plat_joystick_state[c].nr_axes = SDL_JoystickNumAxes(sdl_joy[c]); plat_joystick_state[c].nr_axes = std::min(SDL_JoystickNumAxes(sdl_joy[c]), MAX_JOY_AXES);
plat_joystick_state[c].nr_buttons = SDL_JoystickNumButtons(sdl_joy[c]); plat_joystick_state[c].nr_buttons = std::min(SDL_JoystickNumButtons(sdl_joy[c]), MAX_JOY_BUTTONS);
plat_joystick_state[c].nr_povs = SDL_JoystickNumHats(sdl_joy[c]); plat_joystick_state[c].nr_povs = std::min(SDL_JoystickNumHats(sdl_joy[c]), MAX_JOY_POVS);
for (d = 0; d < std::min(plat_joystick_state[c].nr_axes, 8); d++) { for (d = 0; d < plat_joystick_state[c].nr_axes; d++) {
snprintf(plat_joystick_state[c].axis[d].name, sizeof(plat_joystick_state[c].axis[d].name), "Axis %i", d); snprintf(plat_joystick_state[c].axis[d].name, sizeof(plat_joystick_state[c].axis[d].name), "Axis %i", d);
plat_joystick_state[c].axis[d].id = d; plat_joystick_state[c].axis[d].id = d;
} }
for (d = 0; d < std::min(plat_joystick_state[c].nr_buttons, 8); d++) { for (d = 0; d < plat_joystick_state[c].nr_buttons; d++) {
snprintf(plat_joystick_state[c].button[d].name, sizeof(plat_joystick_state[c].button[d].name), "Button %i", d); snprintf(plat_joystick_state[c].button[d].name, sizeof(plat_joystick_state[c].button[d].name), "Button %i", d);
plat_joystick_state[c].button[d].id = d; plat_joystick_state[c].button[d].id = d;
} }
for (d = 0; d < std::min(plat_joystick_state[c].nr_povs, 4); d++) { for (d = 0; d < plat_joystick_state[c].nr_povs; d++) {
snprintf(plat_joystick_state[c].pov[d].name, sizeof(plat_joystick_state[c].pov[d].name), "POV %i", d); snprintf(plat_joystick_state[c].pov[d].name, sizeof(plat_joystick_state[c].pov[d].name), "POV %i", d);
plat_joystick_state[c].pov[d].id = d; plat_joystick_state[c].pov[d].id = d;
} }
@@ -116,17 +116,13 @@ joystick_process()
for (c = 0; c < joysticks_present; c++) { for (c = 0; c < joysticks_present; c++) {
int b; int b;
plat_joystick_state[c].a[0] = SDL_JoystickGetAxis(sdl_joy[c], 0); for (b = 0; b < plat_joystick_state[c].nr_axes; b++)
plat_joystick_state[c].a[1] = SDL_JoystickGetAxis(sdl_joy[c], 1); plat_joystick_state[c].a[b] = SDL_JoystickGetAxis(sdl_joy[c], b);
plat_joystick_state[c].a[2] = SDL_JoystickGetAxis(sdl_joy[c], 2);
plat_joystick_state[c].a[3] = SDL_JoystickGetAxis(sdl_joy[c], 3);
plat_joystick_state[c].a[4] = SDL_JoystickGetAxis(sdl_joy[c], 4);
plat_joystick_state[c].a[5] = SDL_JoystickGetAxis(sdl_joy[c], 5);
for (b = 0; b < 16; b++) for (b = 0; b < plat_joystick_state[c].nr_buttons; b++)
plat_joystick_state[c].b[b] = SDL_JoystickGetButton(sdl_joy[c], b); plat_joystick_state[c].b[b] = SDL_JoystickGetButton(sdl_joy[c], b);
for (b = 0; b < 4; b++) for (b = 0; b < plat_joystick_state[c].nr_povs; b++)
plat_joystick_state[c].p[b] = SDL_JoystickGetHat(sdl_joy[c], b); plat_joystick_state[c].p[b] = SDL_JoystickGetHat(sdl_joy[c], b);
// pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); // pclog("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present);
} }

View File

@@ -35,6 +35,29 @@
#include <86box/gameport.h> #include <86box/gameport.h>
#include <86box/win.h> #include <86box/win.h>
/* These are defined in hidusage.h in the Windows SDK, but not in mingw-w64. */
#ifndef HID_USAGE_SIMULATION_AILERON
# define HID_USAGE_SIMULATION_AILERON ((USAGE) 0xb0)
#endif
#ifndef HID_USAGE_SIMULATION_ELEVATOR
# define HID_USAGE_SIMULATION_ELEVATOR ((USAGE) 0xb8)
#endif
#ifndef HID_USAGE_SIMULATION_ACCELLERATOR
# define HID_USAGE_SIMULATION_ACCELLERATOR ((USAGE) 0xc4)
#endif
#ifndef HID_USAGE_SIMULATION_BRAKE
# define HID_USAGE_SIMULATION_BRAKE ((USAGE) 0xc5)
#endif
#ifndef HID_USAGE_SIMULATION_CLUTCH
# define HID_USAGE_SIMULATION_CLUTCH ((USAGE) 0xc6)
#endif
#ifndef HID_USAGE_SIMULATION_SHIFTER
# define HID_USAGE_SIMULATION_SHIFTER ((USAGE) 0xc7)
#endif
#ifndef HID_USAGE_SIMULATION_STEERING
# define HID_USAGE_SIMULATION_STEERING ((USAGE) 0xc8)
#endif
#ifdef ENABLE_JOYSTICK_LOG #ifdef ENABLE_JOYSTICK_LOG
int joystick_do_log = ENABLE_JOYSTICK_LOG; int joystick_do_log = ENABLE_JOYSTICK_LOG;
@@ -65,14 +88,14 @@ typedef struct {
USHORT bitsize; USHORT bitsize;
LONG max; LONG max;
LONG min; LONG min;
} axis[8]; } axis[MAX_JOY_AXES];
struct raw_pov_t { struct raw_pov_t {
USAGE usage; USAGE usage;
USHORT link; USHORT link;
LONG max; LONG max;
LONG min; LONG min;
} pov[4]; } pov[MAX_JOY_POVS];
} raw_joystick_t; } raw_joystick_t;
plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
@@ -85,7 +108,7 @@ raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS];
void void
joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage)
{ {
if (joy->nr_buttons >= 32) if (joy->nr_buttons >= MAX_JOY_BUTTONS)
return; return;
if (usage < 1 || usage > 128) if (usage < 1 || usage > 128)
return; return;
@@ -98,7 +121,7 @@ joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage)
void void
joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop)
{ {
if (joy->nr_axes >= 8) if (joy->nr_axes >= MAX_JOY_AXES)
return; return;
switch (prop->Range.UsageMin) { switch (prop->Range.UsageMin) {
@@ -120,6 +143,42 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS
case HID_USAGE_GENERIC_RZ: case HID_USAGE_GENERIC_RZ:
sprintf(joy->axis[joy->nr_axes].name, "RZ"); sprintf(joy->axis[joy->nr_axes].name, "RZ");
break; break;
case HID_USAGE_GENERIC_SLIDER:
sprintf(joy->axis[joy->nr_axes].name, "Slider");
break;
case HID_USAGE_GENERIC_DIAL:
sprintf(joy->axis[joy->nr_axes].name, "Dial");
break;
case HID_USAGE_GENERIC_WHEEL:
sprintf(joy->axis[joy->nr_axes].name, "Wheel");
break;
case HID_USAGE_SIMULATION_AILERON:
sprintf(joy->axis[joy->nr_axes].name, "Aileron");
break;
case HID_USAGE_SIMULATION_ELEVATOR:
sprintf(joy->axis[joy->nr_axes].name, "Elevator");
break;
case HID_USAGE_SIMULATION_RUDDER:
sprintf(joy->axis[joy->nr_axes].name, "Rudder");
break;
case HID_USAGE_SIMULATION_THROTTLE:
sprintf(joy->axis[joy->nr_axes].name, "Throttle");
break;
case HID_USAGE_SIMULATION_ACCELLERATOR:
sprintf(joy->axis[joy->nr_axes].name, "Accelerator");
break;
case HID_USAGE_SIMULATION_BRAKE:
sprintf(joy->axis[joy->nr_axes].name, "Brake");
break;
case HID_USAGE_SIMULATION_CLUTCH:
sprintf(joy->axis[joy->nr_axes].name, "Clutch");
break;
case HID_USAGE_SIMULATION_SHIFTER:
sprintf(joy->axis[joy->nr_axes].name, "Shifter");
break;
case HID_USAGE_SIMULATION_STEERING:
sprintf(joy->axis[joy->nr_axes].name, "Steering");
break;
default: default:
return; return;
} }
@@ -147,7 +206,7 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS
void void
joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop)
{ {
if (joy->nr_povs >= 4) if (joy->nr_povs >= MAX_JOY_POVS)
return; return;
sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1); sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1);
@@ -367,10 +426,10 @@ win_joystick_handle(PRAWINPUT raw)
/* Read axes */ /* Read axes */
for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) { for (int a = 0; a < plat_joystick_state[j].nr_axes; a++) {
struct raw_axis_t *axis = &raw_joystick_state[j].axis[a]; const struct raw_axis_t *axis = &raw_joystick_state[j].axis[a];
ULONG uvalue = 0; ULONG uvalue = 0;
LONG value = 0; LONG value = 0;
LONG center = (axis->max - axis->min + 1) / 2; LONG center = (axis->max - axis->min + 1) / 2;
r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, axis->link, axis->usage, &uvalue, r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, axis->link, axis->usage, &uvalue,
raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid);
@@ -395,14 +454,16 @@ win_joystick_handle(PRAWINPUT raw)
} }
plat_joystick_state[j].a[a] = value; plat_joystick_state[j].a[a] = value;
// joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); #if 0
joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]);
#endif
} }
/* read povs */ /* read povs */
for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) { for (int p = 0; p < plat_joystick_state[j].nr_povs; p++) {
struct raw_pov_t *pov = &raw_joystick_state[j].pov[p]; const struct raw_pov_t *pov = &raw_joystick_state[j].pov[p];
ULONG uvalue = 0; ULONG uvalue = 0;
LONG value = -1; LONG value = -1;
r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, pov->link, pov->usage, &uvalue, r = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, pov->link, pov->usage, &uvalue,
raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid); raw_joystick_state[j].data, (PCHAR) raw->data.hid.bRawData, raw->data.hid.dwSizeHid);
@@ -415,9 +476,13 @@ win_joystick_handle(PRAWINPUT raw)
plat_joystick_state[j].p[p] = value; plat_joystick_state[j].p[p] = value;
// joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]); #if 0
joystick_log("%s %-3d ", plat_joystick_state[j].pov[p].name, plat_joystick_state[j].p[p]);
#endif
} }
// joystick_log("\n"); #if 0
joystick_log("\n");
#endif
} }
static int static int

View File

@@ -36,6 +36,7 @@
plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
joystick_t joystick_state[MAX_JOYSTICKS]; joystick_t joystick_state[MAX_JOYSTICKS];
int joysticks_present = 0; int joysticks_present = 0;
int has_slider = 0;
static LPDIRECTINPUT8 lpdi; static LPDIRECTINPUT8 lpdi;
static LPDIRECTINPUTDEVICE8 lpdi_joystick[2] = { NULL, NULL }; static LPDIRECTINPUTDEVICE8 lpdi_joystick[2] = { NULL, NULL };
@@ -83,7 +84,7 @@ DIEnumDeviceObjectsCallback(
plat_joystick_t *state = (plat_joystick_t *) pvRef; plat_joystick_t *state = (plat_joystick_t *) pvRef;
if (lpddoi->guidType == GUID_XAxis || lpddoi->guidType == GUID_YAxis || lpddoi->guidType == GUID_ZAxis || lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis) { if (lpddoi->guidType == GUID_XAxis || lpddoi->guidType == GUID_YAxis || lpddoi->guidType == GUID_ZAxis || lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis) {
if (state->nr_axes < 8) { if (state->nr_axes < MAX_JOY_AXES) {
memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1);
joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType);
if (lpddoi->guidType == GUID_XAxis) if (lpddoi->guidType == GUID_XAxis)
@@ -98,27 +99,24 @@ DIEnumDeviceObjectsCallback(
state->axis[state->nr_axes].id = 4; state->axis[state->nr_axes].id = 4;
else if (lpddoi->guidType == GUID_RzAxis) else if (lpddoi->guidType == GUID_RzAxis)
state->axis[state->nr_axes].id = 5; state->axis[state->nr_axes].id = 5;
else if (lpddoi->guidType == GUID_Slider) {
state->axis[state->nr_axes].id = 6 + has_slider;
has_slider++;
}
state->nr_axes++; state->nr_axes++;
} }
} else if (lpddoi->guidType == GUID_Button) { } else if (lpddoi->guidType == GUID_Button) {
if (state->nr_buttons < 32) { if (state->nr_buttons < MAX_JOY_BUTTONS) {
memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1);
joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType);
state->nr_buttons++; state->nr_buttons++;
} }
} else if (lpddoi->guidType == GUID_POV) { } else if (lpddoi->guidType == GUID_POV) {
if (state->nr_povs < 4) { if (state->nr_povs < MAX_JOY_POVS) {
memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1);
joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType);
state->nr_povs++; state->nr_povs++;
} }
} else if (lpddoi->guidType == GUID_Slider) {
if (state->nr_sliders < 2) {
memcpy(state->slider[state->nr_sliders].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1);
state->slider[state->nr_sliders].id = state->nr_sliders | SLIDER;
joystick_log("Slider %i : %s %x %x\n", state->nr_sliders, state->slider[state->nr_sliders].name, lpddoi->dwOfs, lpddoi->dwType);
state->nr_sliders++;
}
} }
return DIENUM_CONTINUE; return DIENUM_CONTINUE;
@@ -170,6 +168,7 @@ joystick_init()
joystick_log(" Buttons = %i\n", devcaps.dwButtons); joystick_log(" Buttons = %i\n", devcaps.dwButtons);
joystick_log(" POVs = %i\n", devcaps.dwPOVs); joystick_log(" POVs = %i\n", devcaps.dwPOVs);
has_slider = 0;
lpdi_joystick[c]->EnumObjects(DIEnumDeviceObjectsCallback, &plat_joystick_state[c], DIDFT_ALL); lpdi_joystick[c]->EnumObjects(DIEnumDeviceObjectsCallback, &plat_joystick_state[c], DIDFT_ALL);
if (FAILED(lpdi_joystick[c]->SetCooperativeLevel(hwndMain, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) if (FAILED(lpdi_joystick[c]->SetCooperativeLevel(hwndMain, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
@@ -234,8 +233,6 @@ joystick_get_axis(int joystick_nr, int mapping)
return 0; return 0;
else else
return -cos((2 * M_PI * (double) pov) / 36000.0) * 32767; return -cos((2 * M_PI * (double) pov) / 36000.0) * 32767;
} else if (mapping & SLIDER) {
return plat_joystick_state[joystick_nr].s[mapping & 3];
} else } else
return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id];
} }
@@ -269,13 +266,13 @@ joystick_process(void)
plat_joystick_state[c].a[3] = joystate.lRx; plat_joystick_state[c].a[3] = joystate.lRx;
plat_joystick_state[c].a[4] = joystate.lRy; plat_joystick_state[c].a[4] = joystate.lRy;
plat_joystick_state[c].a[5] = joystate.lRz; plat_joystick_state[c].a[5] = joystate.lRz;
plat_joystick_state[c].s[0] = joystate.rglSlider[0]; plat_joystick_state[c].a[6] = joystate.rglSlider[0];
plat_joystick_state[c].s[1] = joystate.rglSlider[1]; plat_joystick_state[c].a[7] = joystate.rglSlider[1];
for (b = 0; b < 16; b++) for (b = 0; b < MAX_JOY_BUTTONS; b++)
plat_joystick_state[c].b[b] = joystate.rgbButtons[b] & 0x80; plat_joystick_state[c].b[b] = joystate.rgbButtons[b] & 0x80;
for (b = 0; b < 4; b++) for (b = 0; b < MAX_JOY_POVS; b++)
plat_joystick_state[c].p[b] = joystate.rgdwPOV[b]; plat_joystick_state[c].p[b] = joystate.rgdwPOV[b];
// joystick_log("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present); // joystick_log("joystick %i - x=%i y=%i b[0]=%i b[1]=%i %i\n", c, joystick_state[c].x, joystick_state[c].y, joystick_state[c].b[0], joystick_state[c].b[1], joysticks_present);
} }

View File

@@ -35,6 +35,29 @@
#include <86box/gameport.h> #include <86box/gameport.h>
#include <86box/win.h> #include <86box/win.h>
/* These are defined in hidusage.h in the Windows SDK, but not in mingw-w64. */
#ifndef HID_USAGE_SIMULATION_AILERON
# define HID_USAGE_SIMULATION_AILERON ((USAGE) 0xb0)
#endif
#ifndef HID_USAGE_SIMULATION_ELEVATOR
# define HID_USAGE_SIMULATION_ELEVATOR ((USAGE) 0xb8)
#endif
#ifndef HID_USAGE_SIMULATION_ACCELLERATOR
# define HID_USAGE_SIMULATION_ACCELLERATOR ((USAGE) 0xc4)
#endif
#ifndef HID_USAGE_SIMULATION_BRAKE
# define HID_USAGE_SIMULATION_BRAKE ((USAGE) 0xc5)
#endif
#ifndef HID_USAGE_SIMULATION_CLUTCH
# define HID_USAGE_SIMULATION_CLUTCH ((USAGE) 0xc6)
#endif
#ifndef HID_USAGE_SIMULATION_SHIFTER
# define HID_USAGE_SIMULATION_SHIFTER ((USAGE) 0xc7)
#endif
#ifndef HID_USAGE_SIMULATION_STEERING
# define HID_USAGE_SIMULATION_STEERING ((USAGE) 0xc8)
#endif
#ifdef ENABLE_JOYSTICK_LOG #ifdef ENABLE_JOYSTICK_LOG
int joystick_do_log = ENABLE_JOYSTICK_LOG; int joystick_do_log = ENABLE_JOYSTICK_LOG;
@@ -65,14 +88,14 @@ typedef struct {
USHORT bitsize; USHORT bitsize;
LONG max; LONG max;
LONG min; LONG min;
} axis[8]; } axis[MAX_JOY_AXES];
struct raw_pov_t { struct raw_pov_t {
USAGE usage; USAGE usage;
USHORT link; USHORT link;
LONG max; LONG max;
LONG min; LONG min;
} pov[4]; } pov[MAX_JOY_POVS];
} raw_joystick_t; } raw_joystick_t;
plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
@@ -85,7 +108,7 @@ raw_joystick_t raw_joystick_state[MAX_PLAT_JOYSTICKS];
void void
joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage) joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage)
{ {
if (joy->nr_buttons >= 32) if (joy->nr_buttons >= MAX_JOY_BUTTONS)
return; return;
if (usage < 1 || usage > 128) if (usage < 1 || usage > 128)
return; return;
@@ -98,7 +121,7 @@ joystick_add_button(raw_joystick_t *rawjoy, plat_joystick_t *joy, USAGE usage)
void void
joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop)
{ {
if (joy->nr_axes >= 8) if (joy->nr_axes >= MAX_JOY_AXES)
return; return;
switch (prop->Range.UsageMin) { switch (prop->Range.UsageMin) {
@@ -120,6 +143,42 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS
case HID_USAGE_GENERIC_RZ: case HID_USAGE_GENERIC_RZ:
sprintf(joy->axis[joy->nr_axes].name, "RZ"); sprintf(joy->axis[joy->nr_axes].name, "RZ");
break; break;
case HID_USAGE_GENERIC_SLIDER:
sprintf(joy->axis[joy->nr_axes].name, "Slider");
break;
case HID_USAGE_GENERIC_DIAL:
sprintf(joy->axis[joy->nr_axes].name, "Dial");
break;
case HID_USAGE_GENERIC_WHEEL:
sprintf(joy->axis[joy->nr_axes].name, "Wheel");
break;
case HID_USAGE_SIMULATION_AILERON:
sprintf(joy->axis[joy->nr_axes].name, "Aileron");
break;
case HID_USAGE_SIMULATION_ELEVATOR:
sprintf(joy->axis[joy->nr_axes].name, "Elevator");
break;
case HID_USAGE_SIMULATION_RUDDER:
sprintf(joy->axis[joy->nr_axes].name, "Rudder");
break;
case HID_USAGE_SIMULATION_THROTTLE:
sprintf(joy->axis[joy->nr_axes].name, "Throttle");
break;
case HID_USAGE_SIMULATION_ACCELLERATOR:
sprintf(joy->axis[joy->nr_axes].name, "Accelerator");
break;
case HID_USAGE_SIMULATION_BRAKE:
sprintf(joy->axis[joy->nr_axes].name, "Brake");
break;
case HID_USAGE_SIMULATION_CLUTCH:
sprintf(joy->axis[joy->nr_axes].name, "Clutch");
break;
case HID_USAGE_SIMULATION_SHIFTER:
sprintf(joy->axis[joy->nr_axes].name, "Shifter");
break;
case HID_USAGE_SIMULATION_STEERING:
sprintf(joy->axis[joy->nr_axes].name, "Steering");
break;
default: default:
return; return;
} }
@@ -147,7 +206,7 @@ joystick_add_axis(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS
void void
joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop) joystick_add_pov(raw_joystick_t *rawjoy, plat_joystick_t *joy, PHIDP_VALUE_CAPS prop)
{ {
if (joy->nr_povs >= 4) if (joy->nr_povs >= MAX_JOY_POVS)
return; return;
sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1); sprintf(joy->pov[joy->nr_povs].name, "POV %d", joy->nr_povs + 1);
@@ -395,7 +454,9 @@ win_joystick_handle(PRAWINPUT raw)
} }
plat_joystick_state[j].a[a] = value; plat_joystick_state[j].a[a] = value;
// joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]); #if 0
joystick_log("%s %-06d ", plat_joystick_state[j].axis[a].name, plat_joystick_state[j].a[a]);
#endif
} }
/* read povs */ /* read povs */

View File

@@ -54,9 +54,6 @@ rebuild_axis_button_selections(HWND hdlg)
sprintf(s, "%s (Y axis)", plat_joystick_state[joystick - 1].pov[d].name); sprintf(s, "%s (Y axis)", plat_joystick_state[joystick - 1].pov[d].name);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) s); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) s);
} }
for (d = 0; d < plat_joystick_state[joystick - 1].nr_sliders; d++) {
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) (LPCSTR) plat_joystick_state[joystick - 1].slider[d].name);
}
SendMessage(h, CB_SETCURSEL, sel, 0); SendMessage(h, CB_SETCURSEL, sel, 0);
EnableWindow(h, TRUE); EnableWindow(h, TRUE);
} else } else
@@ -111,21 +108,15 @@ get_axis(HWND hdlg, int id)
HWND h = GetDlgItem(hdlg, id); HWND h = GetDlgItem(hdlg, id);
int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0);
int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes; int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_axes;
int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs;
if (axis_sel < nr_axes) if (axis_sel < nr_axes)
return axis_sel; return axis_sel;
axis_sel -= nr_axes; axis_sel -= nr_axes;
if (axis_sel < nr_povs * 2) { if (axis_sel & 1)
if (axis_sel & 1) return POV_Y | (axis_sel >> 1);
return POV_Y | (axis_sel >> 1); else
else return POV_X | (axis_sel >> 1);
return POV_X | (axis_sel >> 1);
}
axis_sel -= nr_povs;
return SLIDER | (axis_sel >> 1);
} }
static int static int
@@ -188,8 +179,6 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lPa
SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2, 0); SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2, 0);
else if (mapping & POV_Y) else if (mapping & POV_Y)
SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2 + 1, 0); SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3) * 2 + 1, 0);
else if (mapping & SLIDER)
SendMessage(h, CB_SETCURSEL, nr_axes + nr_povs * 2 + (mapping & 3), 0);
else else
SendMessage(h, CB_SETCURSEL, mapping, 0); SendMessage(h, CB_SETCURSEL, mapping, 0);
id += 2; id += 2;