From 484cda73d2845439a00fdd346be33011e7d3da1d Mon Sep 17 00:00:00 2001 From: driver1998 Date: Wed, 20 Mar 2019 07:47:18 +0800 Subject: [PATCH] Xinput controller support Used when DirectInput is disabled/not available (DINPUT=n). Default in ARM32. Supports up to 4 compatiable controllers, with 8 axis (left & right thumb stick, two analog triggers and d-pad) and 12 buttons (basic buttons, and digital trigger) --- src/win/win_joystick_xinput.cpp | 255 ++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 src/win/win_joystick_xinput.cpp diff --git a/src/win/win_joystick_xinput.cpp b/src/win/win_joystick_xinput.cpp new file mode 100644 index 000000000..8a7f11b7f --- /dev/null +++ b/src/win/win_joystick_xinput.cpp @@ -0,0 +1,255 @@ +/* + * 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. + * + * Xinput joystick interface. + * + * Version: @(#)win_joystick_xinput.cpp 1.0.0 2019/3/19 + * + * Authors: Sarah Walker, + * Miran Grca, + * GH Cao, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 Miran Grca. + * Copyright 2019 GH Cao. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "../86box.h" +#include "../device.h" +#include "../plat.h" +#include "../game/gameport.h" +#include "win.h" + +#define XINPUT_MAX_JOYSTICKS 4 +#define XINPUT_NAME "Xinput compatiable controller" +#define XINPUT_NAME_LX "Left Stick X" +#define XINPUT_NAME_LY "Left Stick Y" +#define XINPUT_NAME_RX "Right Stick X" +#define XINPUT_NAME_RY "Right Stick Y" +#define XINPUT_NAME_DPAD_X "D-pad X" +#define XINPUT_NAME_DPAD_Y "D-pad Y" +#define XINPUT_NAME_LB "LB" +#define XINPUT_NAME_RB "RB" +#define XINPUT_NAME_LT "LT" +#define XINPUT_NAME_RT "RT" +#define XINPUT_NAME_A "A" +#define XINPUT_NAME_B "B" +#define XINPUT_NAME_X "X" +#define XINPUT_NAME_Y "Y" +#define XINPUT_NAME_BACK "Back/View" +#define XINPUT_NAME_START "Start/Menu" +#define XINPUT_NAME_LS "Left Stick" +#define XINPUT_NAME_RS "Right Stick" + +#ifdef ENABLE_JOYSTICK_LOG +int joystick_do_log = ENABLE_JOYSTICK_LOG; + + +static void +joystick_log(const char *fmt, ...) +{ + va_list ap; + + if (joystick_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define joystick_log(fmt, ...) +#endif + +plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS]; +joystick_t joystick_state[MAX_JOYSTICKS]; +int joysticks_present = 0; + +XINPUT_STATE controllers[XINPUT_MAX_JOYSTICKS]; + +void joystick_init() +{ + int c; + + atexit(joystick_close); + + joysticks_present = 0; + + memset(controllers, 0, sizeof(XINPUT_STATE) * XINPUT_MAX_JOYSTICKS); + + for (c=0; c 127) ? 128 : 0; + plat_joystick_state[c].b[7] = (controllers[c].Gamepad.bRightTrigger > 127) ? 128 : 0; + plat_joystick_state[c].b[8] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 128 : 0; + plat_joystick_state[c].b[9] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 128 : 0; + plat_joystick_state[c].b[10] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 128 : 0; + plat_joystick_state[c].b[11] = (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 128 : 0; + + int dpad_x = 0, dpad_y = 0; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) + dpad_y+=32767; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) + dpad_y-=32767; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) + dpad_x+=32767; + if (controllers[c].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) + dpad_x-=32767; + + plat_joystick_state[c].a[2] = dpad_x; + plat_joystick_state[c].a[5] = dpad_y; + } +} + +static int joystick_get_axis(int joystick_nr, int mapping) +{ + if (mapping & POV_X) + { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return sin((2*M_PI * (double)pov) / 36000.0) * 32767; + } + else if (mapping & POV_Y) + { + int pov = plat_joystick_state[joystick_nr].p[mapping & 3]; + + if (LOWORD(pov) == 0xFFFF) + return 0; + else + return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; + } + else + return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; +} + +void joystick_process(void) +{ + int c, d; + + if (joystick_type == 7) return; + + joystick_poll(); + + for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++) + { + if (joystick_state[c].plat_joystick_nr) + { + int joystick_nr = joystick_state[c].plat_joystick_nr - 1; + + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = joystick_get_axis(joystick_nr, joystick_state[c].axis_mapping[d]); + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = plat_joystick_state[joystick_nr].b[joystick_state[c].button_mapping[d]]; + + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + { + int x, y; + double angle, magnitude; + + x = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][0]); + y = joystick_get_axis(joystick_nr, joystick_state[c].pov_mapping[d][1]); + + angle = (atan2((double)y, (double)x) * 360.0) / (2*M_PI); + magnitude = sqrt((double)x*(double)x + (double)y*(double)y); + + if (magnitude < 16384) + joystick_state[c].pov[d] = -1; + else + joystick_state[c].pov[d] = ((int)angle + 90 + 360) % 360; + } + } + else + { + for (d = 0; d < joystick_get_axis_count(joystick_type); d++) + joystick_state[c].axis[d] = 0; + for (d = 0; d < joystick_get_button_count(joystick_type); d++) + joystick_state[c].button[d] = 0; + for (d = 0; d < joystick_get_pov_count(joystick_type); d++) + joystick_state[c].pov[d] = -1; + } + } +} +