forked from Dniel97/segatools
idzio/di.c: Add positional shifter support
This commit is contained in:
parent
bef6e9b4aa
commit
2214374bbd
@ -2,12 +2,17 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
#include "idzio/config.h"
|
#include "idzio/config.h"
|
||||||
|
|
||||||
void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename)
|
void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename)
|
||||||
{
|
{
|
||||||
|
wchar_t key[8];
|
||||||
|
int i;
|
||||||
|
|
||||||
assert(cfg != NULL);
|
assert(cfg != NULL);
|
||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
@ -19,6 +24,14 @@ void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename)
|
|||||||
_countof(cfg->device_name),
|
_countof(cfg->device_name),
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
|
GetPrivateProfileStringW(
|
||||||
|
L"dinput",
|
||||||
|
L"shifterName",
|
||||||
|
L"",
|
||||||
|
cfg->shifter_name,
|
||||||
|
_countof(cfg->shifter_name),
|
||||||
|
filename);
|
||||||
|
|
||||||
GetPrivateProfileStringW(
|
GetPrivateProfileStringW(
|
||||||
L"dinput",
|
L"dinput",
|
||||||
L"brakeAxis",
|
L"brakeAxis",
|
||||||
@ -39,6 +52,11 @@ void idz_di_config_load(struct idz_di_config *cfg, const wchar_t *filename)
|
|||||||
cfg->view_chg = GetPrivateProfileIntW(L"dinput", L"viewChg", 0, filename);
|
cfg->view_chg = GetPrivateProfileIntW(L"dinput", L"viewChg", 0, filename);
|
||||||
cfg->shift_dn = GetPrivateProfileIntW(L"dinput", L"shiftDn", 0, filename);
|
cfg->shift_dn = GetPrivateProfileIntW(L"dinput", L"shiftDn", 0, filename);
|
||||||
cfg->shift_up = GetPrivateProfileIntW(L"dinput", L"shiftUp", 0, filename);
|
cfg->shift_up = GetPrivateProfileIntW(L"dinput", L"shiftUp", 0, filename);
|
||||||
|
|
||||||
|
for (i = 0 ; i < 6 ; i++) {
|
||||||
|
swprintf_s(key, _countof(key), L"gear%i", i + 1);
|
||||||
|
cfg->gear[i] = GetPrivateProfileIntW(L"dinput", key, i + 1, filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void idz_io_config_load(struct idz_io_config *cfg, const wchar_t *filename)
|
void idz_io_config_load(struct idz_io_config *cfg, const wchar_t *filename)
|
||||||
|
@ -10,12 +10,14 @@ struct idz_shifter_config {
|
|||||||
|
|
||||||
struct idz_di_config {
|
struct idz_di_config {
|
||||||
wchar_t device_name[64];
|
wchar_t device_name[64];
|
||||||
|
wchar_t shifter_name[64];
|
||||||
wchar_t brake_axis[16];
|
wchar_t brake_axis[16];
|
||||||
wchar_t accel_axis[16];
|
wchar_t accel_axis[16];
|
||||||
uint8_t start;
|
uint8_t start;
|
||||||
uint8_t view_chg;
|
uint8_t view_chg;
|
||||||
uint8_t shift_dn;
|
uint8_t shift_dn;
|
||||||
uint8_t shift_up;
|
uint8_t shift_up;
|
||||||
|
uint8_t gear[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct idz_io_config {
|
struct idz_io_config {
|
||||||
|
260
idzio/di.c
260
idzio/di.c
@ -8,6 +8,7 @@
|
|||||||
#include "idzio/backend.h"
|
#include "idzio/backend.h"
|
||||||
#include "idzio/config.h"
|
#include "idzio/config.h"
|
||||||
#include "idzio/di.h"
|
#include "idzio/di.h"
|
||||||
|
#include "idzio/di-dev.h"
|
||||||
#include "idzio/idzio.h"
|
#include "idzio/idzio.h"
|
||||||
#include "idzio/shifter.h"
|
#include "idzio/shifter.h"
|
||||||
#include "idzio/wnd.h"
|
#include "idzio/wnd.h"
|
||||||
@ -20,19 +21,17 @@ struct idz_di_axis {
|
|||||||
size_t off;
|
size_t off;
|
||||||
};
|
};
|
||||||
|
|
||||||
union idz_di_state {
|
|
||||||
DIJOYSTATE st;
|
|
||||||
uint8_t bytes[sizeof(DIJOYSTATE)];
|
|
||||||
};
|
|
||||||
|
|
||||||
static HRESULT idz_di_config_apply(const struct idz_di_config *cfg);
|
static HRESULT idz_di_config_apply(const struct idz_di_config *cfg);
|
||||||
static const struct idz_di_axis *idz_di_get_axis(const wchar_t *name);
|
static const struct idz_di_axis *idz_di_get_axis(const wchar_t *name);
|
||||||
static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx);
|
static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx);
|
||||||
static void idz_di_try_fx(void);
|
static BOOL idz_di_enum_callback_shifter(
|
||||||
static HRESULT idz_di_poll(union idz_di_state *state);
|
const DIDEVICEINSTANCEW *dev,
|
||||||
|
void *ctx);
|
||||||
static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out);
|
static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out);
|
||||||
static uint8_t idz_di_decode_pov(DWORD pov);
|
static uint8_t idz_di_decode_pov(DWORD pov);
|
||||||
static void idz_di_jvs_read_shifter(uint8_t *gear);
|
static void idz_di_jvs_read_shifter(uint8_t *gear);
|
||||||
|
static void idz_di_jvs_read_shifter_pos(uint8_t *gear);
|
||||||
|
static void idz_di_jvs_read_shifter_virt(uint8_t *gear);
|
||||||
static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out);
|
static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out);
|
||||||
|
|
||||||
static const struct idz_di_axis idz_di_axes[] = {
|
static const struct idz_di_axis idz_di_axes[] = {
|
||||||
@ -56,6 +55,7 @@ static const struct idz_io_backend idz_di_backend = {
|
|||||||
static HWND idz_di_wnd;
|
static HWND idz_di_wnd;
|
||||||
static IDirectInput8W *idz_di_api;
|
static IDirectInput8W *idz_di_api;
|
||||||
static IDirectInputDevice8W *idz_di_dev;
|
static IDirectInputDevice8W *idz_di_dev;
|
||||||
|
static IDirectInputDevice8W *idz_di_shifter;
|
||||||
static IDirectInputEffect *idz_di_fx;
|
static IDirectInputEffect *idz_di_fx;
|
||||||
static size_t idz_di_off_brake;
|
static size_t idz_di_off_brake;
|
||||||
static size_t idz_di_off_accel;
|
static size_t idz_di_off_accel;
|
||||||
@ -63,6 +63,7 @@ static uint8_t idz_di_shift_dn;
|
|||||||
static uint8_t idz_di_shift_up;
|
static uint8_t idz_di_shift_up;
|
||||||
static uint8_t idz_di_view_chg;
|
static uint8_t idz_di_view_chg;
|
||||||
static uint8_t idz_di_start;
|
static uint8_t idz_di_start;
|
||||||
|
static uint8_t idz_di_gear[6];
|
||||||
|
|
||||||
HRESULT idz_di_init(
|
HRESULT idz_di_init(
|
||||||
const struct idz_di_config *cfg,
|
const struct idz_di_config *cfg,
|
||||||
@ -109,7 +110,7 @@ HRESULT idz_di_init(
|
|||||||
|
|
||||||
if (dinput8 == NULL) {
|
if (dinput8 == NULL) {
|
||||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||||
dprintf("Wheel: LoadLibrary failed: %08x\n", (int) hr);
|
dprintf("DirectInput: LoadLibrary failed: %08x\n", (int) hr);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -117,7 +118,7 @@ HRESULT idz_di_init(
|
|||||||
api_entry = (void *) GetProcAddress(dinput8, "DirectInput8Create");
|
api_entry = (void *) GetProcAddress(dinput8, "DirectInput8Create");
|
||||||
|
|
||||||
if (api_entry == NULL) {
|
if (api_entry == NULL) {
|
||||||
dprintf("Wheel: GetProcAddress failed\n");
|
dprintf("DirectInput: GetProcAddress failed\n");
|
||||||
|
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
@ -130,7 +131,7 @@ HRESULT idz_di_init(
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("Wheel: API create failed: %08x\n", (int) hr);
|
dprintf("DirectInput: API create failed: %08x\n", (int) hr);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -143,7 +144,7 @@ HRESULT idz_di_init(
|
|||||||
DIEDFL_ATTACHEDONLY);
|
DIEDFL_ATTACHEDONLY);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("Wheel: EnumDevices failed: %08x\n", (int) hr);
|
dprintf("DirectInput: EnumDevices failed: %08x\n", (int) hr);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
@ -154,35 +155,43 @@ HRESULT idz_di_init(
|
|||||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IDirectInputDevice8_SetCooperativeLevel(
|
hr = idz_di_dev_start(idz_di_dev, idz_di_wnd);
|
||||||
idz_di_dev,
|
|
||||||
idz_di_wnd,
|
|
||||||
DISCL_BACKGROUND | DISCL_EXCLUSIVE);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("Wheel: SetCooperativeLevel failed: %08x\n", (int) hr);
|
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IDirectInputDevice8_SetDataFormat(idz_di_dev, &c_dfDIJoystick);
|
idz_di_dev_start_fx(idz_di_dev, &idz_di_fx);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (cfg->shifter_name[0] != L'\0') {
|
||||||
dprintf("Wheel: SetDataFormat failed: %08x\n", (int) hr);
|
hr = IDirectInput8_EnumDevices(
|
||||||
|
idz_di_api,
|
||||||
|
DI8DEVCLASS_GAMECTRL,
|
||||||
|
idz_di_enum_callback_shifter,
|
||||||
|
(void *) cfg,
|
||||||
|
DIEDFL_ATTACHEDONLY);
|
||||||
|
|
||||||
return hr;
|
if (FAILED(hr)) {
|
||||||
|
dprintf("DirectInput: EnumDevices failed: %08x\n", (int) hr);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idz_di_dev == NULL) {
|
||||||
|
dprintf("Shifter: Controller not found\n");
|
||||||
|
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = idz_di_dev_start(idz_di_shifter, idz_di_wnd);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IDirectInputDevice8_Acquire(idz_di_dev);
|
dprintf("DirectInput: Controller initialized\n");
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dprintf("Wheel: Acquire failed: %08x\n", (int) hr);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("Wheel: DirectInput initialized\n");
|
|
||||||
idz_di_try_fx();
|
|
||||||
*backend = &idz_di_backend;
|
*backend = &idz_di_backend;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@ -192,6 +201,7 @@ static HRESULT idz_di_config_apply(const struct idz_di_config *cfg)
|
|||||||
{
|
{
|
||||||
const struct idz_di_axis *brake_axis;
|
const struct idz_di_axis *brake_axis;
|
||||||
const struct idz_di_axis *accel_axis;
|
const struct idz_di_axis *accel_axis;
|
||||||
|
int i;
|
||||||
|
|
||||||
brake_axis = idz_di_get_axis(cfg->brake_axis);
|
brake_axis = idz_di_get_axis(cfg->brake_axis);
|
||||||
accel_axis = idz_di_get_axis(cfg->accel_axis);
|
accel_axis = idz_di_get_axis(cfg->accel_axis);
|
||||||
@ -232,6 +242,16 @@ static HRESULT idz_di_config_apply(const struct idz_di_config *cfg)
|
|||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < 6 ; i++) {
|
||||||
|
if (cfg->gear[i] > 32) {
|
||||||
|
dprintf("Shifter: Invalid gear %i button: %i\n",
|
||||||
|
i + 1,
|
||||||
|
cfg->gear[i]);
|
||||||
|
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Print some debug output to make sure config works... */
|
/* Print some debug output to make sure config works... */
|
||||||
|
|
||||||
dprintf("Wheel: --- Begin configuration ---\n");
|
dprintf("Wheel: --- Begin configuration ---\n");
|
||||||
@ -245,6 +265,20 @@ static HRESULT idz_di_config_apply(const struct idz_di_config *cfg)
|
|||||||
dprintf("Wheel: Shift Up button . . : %i\n", cfg->shift_up);
|
dprintf("Wheel: Shift Up button . . : %i\n", cfg->shift_up);
|
||||||
dprintf("Wheel: --- End configuration ---\n");
|
dprintf("Wheel: --- End configuration ---\n");
|
||||||
|
|
||||||
|
if (cfg->shifter_name[0] != L'\0') {
|
||||||
|
dprintf("Shifter: --- Begin configuration ---\n");
|
||||||
|
dprintf("Shifter: Device name . . . : Contains \"%S\"\n",
|
||||||
|
cfg->shifter_name);
|
||||||
|
dprintf("Shifter: Gear buttons . . : %i %i %i %i %i %i\n",
|
||||||
|
cfg->gear[0],
|
||||||
|
cfg->gear[1],
|
||||||
|
cfg->gear[2],
|
||||||
|
cfg->gear[3],
|
||||||
|
cfg->gear[4],
|
||||||
|
cfg->gear[5]);
|
||||||
|
dprintf("Shifter: --- End configuration ---\n");
|
||||||
|
}
|
||||||
|
|
||||||
idz_di_off_brake = accel_axis->off;
|
idz_di_off_brake = accel_axis->off;
|
||||||
idz_di_off_accel = brake_axis->off;
|
idz_di_off_accel = brake_axis->off;
|
||||||
idz_di_start = cfg->start;
|
idz_di_start = cfg->start;
|
||||||
@ -252,6 +286,10 @@ static HRESULT idz_di_config_apply(const struct idz_di_config *cfg)
|
|||||||
idz_di_shift_dn = cfg->shift_dn;
|
idz_di_shift_dn = cfg->shift_dn;
|
||||||
idz_di_shift_up = cfg->shift_up;
|
idz_di_shift_up = cfg->shift_up;
|
||||||
|
|
||||||
|
for (i = 0 ; i < 6 ; i++) {
|
||||||
|
idz_di_gear[i] = cfg->gear[i];
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,6 +312,7 @@ static const struct idz_di_axis *idz_di_get_axis(const wchar_t *name)
|
|||||||
static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx)
|
static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx)
|
||||||
{
|
{
|
||||||
const struct idz_di_config *cfg;
|
const struct idz_di_config *cfg;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
cfg = ctx;
|
cfg = ctx;
|
||||||
|
|
||||||
@ -283,119 +322,45 @@ static BOOL idz_di_enum_callback(const DIDEVICEINSTANCEW *dev, void *ctx)
|
|||||||
|
|
||||||
dprintf("Wheel: Using DirectInput device \"%S\"\n", dev->tszProductName);
|
dprintf("Wheel: Using DirectInput device \"%S\"\n", dev->tszProductName);
|
||||||
|
|
||||||
IDirectInput8_CreateDevice(
|
hr = IDirectInput8_CreateDevice(
|
||||||
idz_di_api,
|
idz_di_api,
|
||||||
&dev->guidInstance,
|
&dev->guidInstance,
|
||||||
&idz_di_dev,
|
&idz_di_dev,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
dprintf("Wheel: CreateDevice failed: %08x\n", (int) hr);
|
||||||
|
}
|
||||||
|
|
||||||
return DIENUM_STOP;
|
return DIENUM_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idz_di_try_fx(void)
|
static BOOL idz_di_enum_callback_shifter(
|
||||||
|
const DIDEVICEINSTANCEW *dev,
|
||||||
|
void *ctx)
|
||||||
{
|
{
|
||||||
/* Set up force-feedback on devices that support it. This is just a stub
|
const struct idz_di_config *cfg;
|
||||||
for the time being, since we don't yet know how the serial port force
|
|
||||||
feedback protocol works.
|
|
||||||
|
|
||||||
I'm currently developing with an Xbox One Thrustmaster TMX wheel, if
|
|
||||||
we don't perform at least some perfunctory FFB initialization of this
|
|
||||||
nature (or indeed if no DirectInput application is running) then the
|
|
||||||
wheel exhibits considerable resistance, similar to that of a stationary
|
|
||||||
car. Changing cf.lMagnitude to a nonzero value does cause the wheel to
|
|
||||||
continuously turn in the given direction with the given force as one
|
|
||||||
would expect (max magnitude per DirectInput docs is +/- 10000).
|
|
||||||
|
|
||||||
Failure here is non-fatal, we log any errors and move on.
|
|
||||||
|
|
||||||
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee416353(v=vs.85)
|
|
||||||
*/
|
|
||||||
|
|
||||||
DWORD axis;
|
|
||||||
LONG direction;
|
|
||||||
DIEFFECT fx;
|
|
||||||
DICONSTANTFORCE cf;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
dprintf("Wheel: Attempting to start force feedback (may take a sec)\n");
|
cfg = ctx;
|
||||||
|
|
||||||
axis = DIJOFS_X;
|
if (wcsstr(dev->tszProductName, cfg->shifter_name) == NULL) {
|
||||||
direction = 0;
|
return DIENUM_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&cf, 0, sizeof(cf));
|
dprintf("Shifter: Using DirectInput device \"%S\"\n", dev->tszProductName);
|
||||||
cf.lMagnitude = 0;
|
|
||||||
|
|
||||||
memset(&fx, 0, sizeof(fx));
|
hr = IDirectInput8_CreateDevice(
|
||||||
fx.dwSize = sizeof(fx);
|
idz_di_api,
|
||||||
fx.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
&dev->guidInstance,
|
||||||
fx.dwDuration = INFINITE;
|
&idz_di_shifter,
|
||||||
fx.dwGain = DI_FFNOMINALMAX;
|
|
||||||
fx.dwTriggerButton = DIEB_NOTRIGGER;
|
|
||||||
fx.dwTriggerRepeatInterval = INFINITE;
|
|
||||||
fx.cAxes = 1;
|
|
||||||
fx.rgdwAxes = &axis;
|
|
||||||
fx.rglDirection = &direction;
|
|
||||||
fx.cbTypeSpecificParams = sizeof(cf);
|
|
||||||
fx.lpvTypeSpecificParams = &cf;
|
|
||||||
|
|
||||||
hr = IDirectInputDevice8_CreateEffect(
|
|
||||||
idz_di_dev,
|
|
||||||
&GUID_ConstantForce,
|
|
||||||
&fx,
|
|
||||||
&idz_di_fx,
|
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
dprintf("Wheel: DirectInput force feedback unavailable: %08x\n",
|
dprintf("Shifter: CreateDevice failed: %08x\n", (int) hr);
|
||||||
(int) hr);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IDirectInputEffect_Start(idz_di_fx, INFINITE, 0);
|
return DIENUM_STOP;
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dprintf("Wheel: DirectInput force feedback start failed: %08x\n",
|
|
||||||
(int) hr);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintf("Wheel: Force feedback initialized and set to zero\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT idz_di_poll(union idz_di_state *out)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
memset(out, 0, sizeof(*out));
|
|
||||||
|
|
||||||
if (idz_di_dev == NULL) {
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pump our dummy window's message queue just in case DirectInput or an
|
|
||||||
IHV DirectInput driver somehow relies on it */
|
|
||||||
|
|
||||||
while (PeekMessageW(&msg, idz_di_wnd, 0, 0, PM_REMOVE)) {
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = IDirectInputDevice8_GetDeviceState(
|
|
||||||
idz_di_dev,
|
|
||||||
sizeof(out->st),
|
|
||||||
&out->st);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
dprintf("Wheel: I/O error: %08x\n", (int) hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* JVS lacks a protocol for reporting hardware errors from poll command
|
|
||||||
responses, so this ends up returning zeroed input state instead. */
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out)
|
static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out)
|
||||||
@ -406,7 +371,7 @@ static void idz_di_jvs_read_buttons(uint8_t *gamebtn_out)
|
|||||||
|
|
||||||
assert(gamebtn_out != NULL);
|
assert(gamebtn_out != NULL);
|
||||||
|
|
||||||
hr = idz_di_poll(&state);
|
hr = idz_di_dev_poll(idz_di_dev, idz_di_wnd, &state);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return;
|
return;
|
||||||
@ -441,6 +406,47 @@ static uint8_t idz_di_decode_pov(DWORD pov)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void idz_di_jvs_read_shifter(uint8_t *gear)
|
static void idz_di_jvs_read_shifter(uint8_t *gear)
|
||||||
|
{
|
||||||
|
assert(gear != NULL);
|
||||||
|
|
||||||
|
if (idz_di_shifter != NULL) {
|
||||||
|
idz_di_jvs_read_shifter_pos(gear);
|
||||||
|
} else {
|
||||||
|
idz_di_jvs_read_shifter_virt(gear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void idz_di_jvs_read_shifter_pos(uint8_t *out)
|
||||||
|
{
|
||||||
|
union idz_di_state state;
|
||||||
|
uint8_t btn_no;
|
||||||
|
uint8_t gear;
|
||||||
|
uint8_t i;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert(out != NULL);
|
||||||
|
assert(idz_di_shifter != NULL);
|
||||||
|
|
||||||
|
hr = idz_di_dev_poll(idz_di_shifter, idz_di_wnd, &state);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gear = 0;
|
||||||
|
|
||||||
|
for (i = 0 ; i < 6 ; i++) {
|
||||||
|
btn_no = idz_di_gear[i];
|
||||||
|
|
||||||
|
if (btn_no && state.st.rgbButtons[btn_no - 1]) {
|
||||||
|
gear = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = gear;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void idz_di_jvs_read_shifter_virt(uint8_t *gear)
|
||||||
{
|
{
|
||||||
union idz_di_state state;
|
union idz_di_state state;
|
||||||
bool shift_dn;
|
bool shift_dn;
|
||||||
@ -449,7 +455,7 @@ static void idz_di_jvs_read_shifter(uint8_t *gear)
|
|||||||
|
|
||||||
assert(gear != NULL);
|
assert(gear != NULL);
|
||||||
|
|
||||||
hr = idz_di_poll(&state);
|
hr = idz_di_dev_poll(idz_di_dev, idz_di_wnd, &state);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return;
|
return;
|
||||||
@ -481,7 +487,7 @@ static void idz_di_jvs_read_analogs(struct idz_io_analog_state *out)
|
|||||||
|
|
||||||
assert(out != NULL);
|
assert(out != NULL);
|
||||||
|
|
||||||
hr = idz_di_poll(&state);
|
hr = idz_di_dev_poll(idz_di_dev, idz_di_wnd, &state);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user