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:
Vitaliy Margolen 2007-08-05 12:22:49 -06:00 committed by Alexandre Julliard
parent 1fdc0230f0
commit 19183e71d4
3 changed files with 67 additions and 137 deletions

View File

@ -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 find_property(const DataFormat *df, LPCDIPROPHEADER ph);
/* Common joystick stuff */
extern DWORD joystick_map_pov(POINTL *p);
/**
* Callback Data used by specific callback
* for EnumObject on 'W' interfaces

View File

@ -83,11 +83,6 @@ typedef struct {
LONG lSaturation;
} ObjProps;
typedef struct {
LONG lX;
LONG lY;
} POV;
typedef struct JoystickImpl JoystickImpl;
static const IDirectInputDevice8AVtbl JoystickAvt;
static const IDirectInputDevice8WVtbl JoystickWvt;
@ -107,7 +102,7 @@ struct JoystickImpl
int *axis_map;
int axes;
int buttons;
POV povs[4];
POINTL povs[4];
};
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)
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
else
{
df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
i++; /* POV takes 2 axes */
}
}
for (i = 0; i < newDevice->buttons; i++)
{
@ -700,34 +698,6 @@ static LONG map_axis(JoystickImpl * This, short val, short index)
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) {
struct pollfd plfd;
struct js_event jse;
@ -761,70 +731,36 @@ static void joy_polldev(JoystickImpl *This) {
{
int number = This->axis_map[jse.number]; /* wine format object index */
if (number < 12)
{
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));
/* FIXME do deadzone and saturation here */
if (number < 0) return;
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));
TRACE("changing axis %d => %d\n", jse.number, number);
switch (number) {
case 0:
This->js.lX = value;
break;
case 1:
This->js.lY = value;
break;
case 2:
This->js.lZ = value;
break;
case 3:
This->js.lRx = value;
break;
case 4:
This->js.lRy = value;
break;
case 5:
This->js.lRz = value;
break;
case 6:
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);
TRACE("changing axis %d => %d\n", jse.number, number);
switch (number)
{
case 0: This->js.lX = value; break;
case 1: This->js.lY = value; break;
case 2: This->js.lZ = value; break;
case 3: This->js.lRx = value; break;
case 4: This->js.lRy = value; break;
case 5: This->js.lRz = value; break;
case 6: This->js.rglSlider[0] = value; break;
case 7: This->js.rglSlider[1] = value; break;
case 8: case 9: case 10: case 11:
{
int idx = number - 8;
if (jse.number % 2)
This->povs[idx].y = jse.value;
else
This->povs[idx].x = jse.value;
This->js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
break;
}
} else
WARN("axis %d not supported\n", number);
default:
WARN("axis %d not supported\n", number);
}
}
if (inst_id >= 0)
queue_event((LPDIRECTINPUTDEVICE8A)This,

View File

@ -65,6 +65,26 @@
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
#define EVDEVPREFIX "/dev/input/event"
@ -139,6 +159,7 @@ struct JoystickImpl
struct ObjProps props[ABS_MAX];
int axes[ABS_MAX];
POINTL povs[4];
/* LUT for KEY_ to offset in rgbButtons */
BYTE buttons[KEY_MAX];
@ -153,7 +174,6 @@ struct JoystickImpl
};
static void fake_current_js_state(JoystickImpl *ji);
static DWORD map_pov(int event_value, int is_x);
static void find_joydevs(void);
/* 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 */
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_THROTTLE: This->js.rglSlider[0] = value; break;
case ABS_RUDDER: This->js.rglSlider[1] = value; break;
case ABS_HAT0X:
case ABS_HAT0Y:
This->js.rgdwPOV[0] = value = map_pov(ie.value, ie.code==ABS_HAT0X);
break;
case ABS_HAT1X:
case ABS_HAT1Y:
This->js.rgdwPOV[1] = value = map_pov(ie.value, ie.code==ABS_HAT1X);
break;
case ABS_HAT2X:
case ABS_HAT2Y:
This->js.rgdwPOV[2] = value = map_pov(ie.value, ie.code==ABS_HAT2X);
break;
case ABS_HAT3X:
case ABS_HAT3Y:
This->js.rgdwPOV[3] = value = map_pov(ie.value, ie.code==ABS_HAT3X);
case ABS_HAT0X: case ABS_HAT0Y: case ABS_HAT1X: case ABS_HAT1Y:
case ABS_HAT2X: case ABS_HAT2Y: case ABS_HAT3X: case ABS_HAT3Y:
{
int idx = (ie.code - ABS_HAT0X) / 2;
if (ie.code % 2)
This->povs[idx].y = ie.value;
else
This->povs[idx].x = ie.value;
This->js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
break;
}
default:
FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value);
break;
}
break;
}