dinput: Fix POV calculation.
Combine and simplify the POV calculations. Linux provides X,Y for the POV. While DirectInput returns dial-degrees*1000 (12 o-click is 0 degrees).
This commit is contained in:
parent
1fdc0230f0
commit
19183e71d4
|
@ -82,6 +82,9 @@ extern int id_to_object(LPCDIDATAFORMAT df, int id);
|
||||||
extern int id_to_offset(const DataFormat *df, int id);
|
extern int id_to_offset(const DataFormat *df, int id);
|
||||||
extern int find_property(const DataFormat *df, LPCDIPROPHEADER ph);
|
extern int find_property(const DataFormat *df, LPCDIPROPHEADER ph);
|
||||||
|
|
||||||
|
/* Common joystick stuff */
|
||||||
|
extern DWORD joystick_map_pov(POINTL *p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback Data used by specific callback
|
* Callback Data used by specific callback
|
||||||
* for EnumObject on 'W' interfaces
|
* for EnumObject on 'W' interfaces
|
||||||
|
|
|
@ -83,11 +83,6 @@ typedef struct {
|
||||||
LONG lSaturation;
|
LONG lSaturation;
|
||||||
} ObjProps;
|
} ObjProps;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
LONG lX;
|
|
||||||
LONG lY;
|
|
||||||
} POV;
|
|
||||||
|
|
||||||
typedef struct JoystickImpl JoystickImpl;
|
typedef struct JoystickImpl JoystickImpl;
|
||||||
static const IDirectInputDevice8AVtbl JoystickAvt;
|
static const IDirectInputDevice8AVtbl JoystickAvt;
|
||||||
static const IDirectInputDevice8WVtbl JoystickWvt;
|
static const IDirectInputDevice8WVtbl JoystickWvt;
|
||||||
|
@ -107,7 +102,7 @@ struct JoystickImpl
|
||||||
int *axis_map;
|
int *axis_map;
|
||||||
int axes;
|
int axes;
|
||||||
int buttons;
|
int buttons;
|
||||||
POV povs[4];
|
POINTL povs[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
|
static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
|
||||||
|
@ -506,7 +501,10 @@ static HRESULT alloc_device(REFGUID rguid, const void *jvt, IDirectInputImpl *di
|
||||||
if (wine_obj < 8)
|
if (wine_obj < 8)
|
||||||
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
|
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
|
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
|
||||||
|
i++; /* POV takes 2 axes */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < newDevice->buttons; i++)
|
for (i = 0; i < newDevice->buttons; i++)
|
||||||
{
|
{
|
||||||
|
@ -700,34 +698,6 @@ static LONG map_axis(JoystickImpl * This, short val, short index)
|
||||||
return fret;
|
return fret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LONG calculate_pov(JoystickImpl *This, int index)
|
|
||||||
{
|
|
||||||
if (This->povs[index].lX < -16384) {
|
|
||||||
if (This->povs[index].lY < -16384)
|
|
||||||
This->js.rgdwPOV[index] = 31500;
|
|
||||||
else if (This->povs[index].lY > 16384)
|
|
||||||
This->js.rgdwPOV[index] = 22500;
|
|
||||||
else
|
|
||||||
This->js.rgdwPOV[index] = 27000;
|
|
||||||
} else if (This->povs[index].lX > 16384) {
|
|
||||||
if (This->povs[index].lY < -16384)
|
|
||||||
This->js.rgdwPOV[index] = 4500;
|
|
||||||
else if (This->povs[index].lY > 16384)
|
|
||||||
This->js.rgdwPOV[index] = 13500;
|
|
||||||
else
|
|
||||||
This->js.rgdwPOV[index] = 9000;
|
|
||||||
} else {
|
|
||||||
if (This->povs[index].lY < -16384)
|
|
||||||
This->js.rgdwPOV[index] = 0;
|
|
||||||
else if (This->povs[index].lY > 16384)
|
|
||||||
This->js.rgdwPOV[index] = 18000;
|
|
||||||
else
|
|
||||||
This->js.rgdwPOV[index] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return This->js.rgdwPOV[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void joy_polldev(JoystickImpl *This) {
|
static void joy_polldev(JoystickImpl *This) {
|
||||||
struct pollfd plfd;
|
struct pollfd plfd;
|
||||||
struct js_event jse;
|
struct js_event jse;
|
||||||
|
@ -761,71 +731,37 @@ static void joy_polldev(JoystickImpl *This) {
|
||||||
{
|
{
|
||||||
int number = This->axis_map[jse.number]; /* wine format object index */
|
int number = This->axis_map[jse.number]; /* wine format object index */
|
||||||
|
|
||||||
if (number < 12)
|
if (number < 0) return;
|
||||||
{
|
|
||||||
inst_id = DIDFT_MAKEINSTANCE(number) | (number < 8 ? DIDFT_ABSAXIS : DIDFT_POV);
|
inst_id = DIDFT_MAKEINSTANCE(number) | (number < 8 ? DIDFT_ABSAXIS : DIDFT_POV);
|
||||||
value = map_axis(This, jse.value, id_to_object(This->base.data_format.wine_df, inst_id));
|
value = map_axis(This, jse.value, id_to_object(This->base.data_format.wine_df, inst_id));
|
||||||
/* FIXME do deadzone and saturation here */
|
|
||||||
|
|
||||||
TRACE("changing axis %d => %d\n", jse.number, number);
|
TRACE("changing axis %d => %d\n", jse.number, number);
|
||||||
switch (number) {
|
switch (number)
|
||||||
case 0:
|
{
|
||||||
This->js.lX = value;
|
case 0: This->js.lX = value; break;
|
||||||
break;
|
case 1: This->js.lY = value; break;
|
||||||
case 1:
|
case 2: This->js.lZ = value; break;
|
||||||
This->js.lY = value;
|
case 3: This->js.lRx = value; break;
|
||||||
break;
|
case 4: This->js.lRy = value; break;
|
||||||
case 2:
|
case 5: This->js.lRz = value; break;
|
||||||
This->js.lZ = value;
|
case 6: This->js.rglSlider[0] = value; break;
|
||||||
break;
|
case 7: This->js.rglSlider[1] = value; break;
|
||||||
case 3:
|
case 8: case 9: case 10: case 11:
|
||||||
This->js.lRx = value;
|
{
|
||||||
break;
|
int idx = number - 8;
|
||||||
case 4:
|
|
||||||
This->js.lRy = value;
|
if (jse.number % 2)
|
||||||
break;
|
This->povs[idx].y = jse.value;
|
||||||
case 5:
|
else
|
||||||
This->js.lRz = value;
|
This->povs[idx].x = jse.value;
|
||||||
break;
|
|
||||||
case 6:
|
This->js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
|
||||||
This->js.rglSlider[0] = value;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
This->js.rglSlider[1] = value;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
/* FIXME don't go off array */
|
|
||||||
if (This->axis_map[jse.number + 1] == number)
|
|
||||||
This->povs[0].lX = jse.value;
|
|
||||||
else if (This->axis_map[jse.number - 1] == number)
|
|
||||||
This->povs[0].lY = jse.value;
|
|
||||||
value = calculate_pov(This, 0);
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
if (This->axis_map[jse.number + 1] == number)
|
|
||||||
This->povs[1].lX = jse.value;
|
|
||||||
else if (This->axis_map[jse.number - 1] == number)
|
|
||||||
This->povs[1].lY = jse.value;
|
|
||||||
value = calculate_pov(This, 1);
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
if (This->axis_map[jse.number + 1] == number)
|
|
||||||
This->povs[2].lX = jse.value;
|
|
||||||
else if (This->axis_map[jse.number - 1] == number)
|
|
||||||
This->povs[2].lY = jse.value;
|
|
||||||
value = calculate_pov(This, 2);
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
if (This->axis_map[jse.number + 1] == number)
|
|
||||||
This->povs[3].lX = jse.value;
|
|
||||||
else if (This->axis_map[jse.number - 1] == number)
|
|
||||||
This->povs[3].lY = jse.value;
|
|
||||||
value = calculate_pov(This, 3);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else
|
default:
|
||||||
WARN("axis %d not supported\n", number);
|
WARN("axis %d not supported\n", number);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (inst_id >= 0)
|
if (inst_id >= 0)
|
||||||
queue_event((LPDIRECTINPUTDEVICE8A)This,
|
queue_event((LPDIRECTINPUTDEVICE8A)This,
|
||||||
id_to_offset(&This->base.data_format, inst_id),
|
id_to_offset(&This->base.data_format, inst_id),
|
||||||
|
|
|
@ -65,6 +65,26 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
|
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maps POV x & y event values to a DX "clock" position:
|
||||||
|
* 0
|
||||||
|
* 31500 4500
|
||||||
|
* 27000 -1 9000
|
||||||
|
* 22500 13500
|
||||||
|
* 18000
|
||||||
|
*/
|
||||||
|
DWORD joystick_map_pov(POINTL *p)
|
||||||
|
{
|
||||||
|
if (p->x > 0)
|
||||||
|
return p->y < 0 ? 4500 : !p->y ? 9000 : 13500;
|
||||||
|
else if (p->x < 0)
|
||||||
|
return p->y < 0 ? 31500 : !p->y ? 27000 : 22500;
|
||||||
|
else
|
||||||
|
return p->y < 0 ? 0 : !p->y ? -1 : 18000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CORRECT_LINUXINPUT_H
|
#ifdef HAVE_CORRECT_LINUXINPUT_H
|
||||||
|
|
||||||
#define EVDEVPREFIX "/dev/input/event"
|
#define EVDEVPREFIX "/dev/input/event"
|
||||||
|
@ -139,6 +159,7 @@ struct JoystickImpl
|
||||||
struct ObjProps props[ABS_MAX];
|
struct ObjProps props[ABS_MAX];
|
||||||
|
|
||||||
int axes[ABS_MAX];
|
int axes[ABS_MAX];
|
||||||
|
POINTL povs[4];
|
||||||
|
|
||||||
/* LUT for KEY_ to offset in rgbButtons */
|
/* LUT for KEY_ to offset in rgbButtons */
|
||||||
BYTE buttons[KEY_MAX];
|
BYTE buttons[KEY_MAX];
|
||||||
|
@ -153,7 +174,6 @@ struct JoystickImpl
|
||||||
};
|
};
|
||||||
|
|
||||||
static void fake_current_js_state(JoystickImpl *ji);
|
static void fake_current_js_state(JoystickImpl *ji);
|
||||||
static DWORD map_pov(int event_value, int is_x);
|
|
||||||
static void find_joydevs(void);
|
static void find_joydevs(void);
|
||||||
|
|
||||||
/* This GUID is slightly different from the linux joystick one. Take note. */
|
/* This GUID is slightly different from the linux joystick one. Take note. */
|
||||||
|
@ -596,31 +616,6 @@ static void fake_current_js_state(JoystickImpl *ji)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Maps an event value to a DX "clock" position:
|
|
||||||
* 0
|
|
||||||
* 27000 -1 9000
|
|
||||||
* 18000
|
|
||||||
*/
|
|
||||||
static DWORD map_pov(int event_value, int is_x)
|
|
||||||
{
|
|
||||||
DWORD ret = -1;
|
|
||||||
if (is_x) {
|
|
||||||
if (event_value<0) {
|
|
||||||
ret = 27000;
|
|
||||||
} else if (event_value>0) {
|
|
||||||
ret = 9000;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (event_value<0) {
|
|
||||||
ret = 0;
|
|
||||||
} else if (event_value>0) {
|
|
||||||
ret = 18000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert wine format offset to user format object index */
|
/* convert wine format offset to user format object index */
|
||||||
static void joy_polldev(JoystickImpl *This)
|
static void joy_polldev(JoystickImpl *This)
|
||||||
{
|
{
|
||||||
|
@ -678,25 +673,21 @@ static void joy_polldev(JoystickImpl *This)
|
||||||
case ABS_RZ: This->js.lRz = value; break;
|
case ABS_RZ: This->js.lRz = value; break;
|
||||||
case ABS_THROTTLE: This->js.rglSlider[0] = value; break;
|
case ABS_THROTTLE: This->js.rglSlider[0] = value; break;
|
||||||
case ABS_RUDDER: This->js.rglSlider[1] = value; break;
|
case ABS_RUDDER: This->js.rglSlider[1] = value; break;
|
||||||
case ABS_HAT0X:
|
case ABS_HAT0X: case ABS_HAT0Y: case ABS_HAT1X: case ABS_HAT1Y:
|
||||||
case ABS_HAT0Y:
|
case ABS_HAT2X: case ABS_HAT2Y: case ABS_HAT3X: case ABS_HAT3Y:
|
||||||
This->js.rgdwPOV[0] = value = map_pov(ie.value, ie.code==ABS_HAT0X);
|
{
|
||||||
break;
|
int idx = (ie.code - ABS_HAT0X) / 2;
|
||||||
case ABS_HAT1X:
|
|
||||||
case ABS_HAT1Y:
|
if (ie.code % 2)
|
||||||
This->js.rgdwPOV[1] = value = map_pov(ie.value, ie.code==ABS_HAT1X);
|
This->povs[idx].y = ie.value;
|
||||||
break;
|
else
|
||||||
case ABS_HAT2X:
|
This->povs[idx].x = ie.value;
|
||||||
case ABS_HAT2Y:
|
|
||||||
This->js.rgdwPOV[2] = value = map_pov(ie.value, ie.code==ABS_HAT2X);
|
This->js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
|
||||||
break;
|
|
||||||
case ABS_HAT3X:
|
|
||||||
case ABS_HAT3Y:
|
|
||||||
This->js.rgdwPOV[3] = value = map_pov(ie.value, ie.code==ABS_HAT3X);
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value);
|
FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue