void joystick_windows::setup_joystick_object(const DIDEVICEOBJECTINSTANCE *ob, int p_joy_id) { if (ob->dwType & DIDFT_AXIS) { HRESULT res; DIPROPRANGE prop_range; DIPROPDWORD dilong; DWORD ofs; if (ob->guidType == GUID_XAxis) ofs = DIJOFS_X; else if (ob->guidType == GUID_YAxis) ofs = DIJOFS_Y; else if (ob->guidType == GUID_ZAxis) ofs = DIJOFS_Z; else if (ob->guidType == GUID_RxAxis) ofs = DIJOFS_RX; else if (ob->guidType == GUID_RyAxis) ofs = DIJOFS_RY; else if (ob->guidType == GUID_RzAxis) ofs = DIJOFS_RZ; else if (ob->guidType == GUID_Slider) ofs = DIJOFS_SLIDER(0); else return; prop_range.diph.dwSize = sizeof(DIPROPRANGE); prop_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); prop_range.diph.dwObj = ob->dwType; prop_range.diph.dwHow = DIPH_BYID; prop_range.lMin = -MAX_JOY_AXIS; prop_range.lMax = +MAX_JOY_AXIS; dinput_gamepad &joy = d_joysticks[p_joy_id]; res = IDirectInputDevice8_SetProperty(joy.di_joy, DIPROP_RANGE, &prop_range.diph); if (FAILED(res)) return; dilong.diph.dwSize = sizeof(dilong); dilong.diph.dwHeaderSize = sizeof(dilong.diph); dilong.diph.dwObj = ob->dwType; dilong.diph.dwHow = DIPH_BYID; dilong.dwData = 0; res = IDirectInputDevice8_SetProperty(joy.di_joy, DIPROP_DEADZONE, &dilong.diph); if (FAILED(res)) return; joy.joy_axis.push_back(ofs); } }
int CL_InputDeviceProvider_DirectInput::get_axis_count() const { throw_if_disposed(); int count=0; // Struct DIJOYSTATE contains maximums count += check_axis(DIJOFS_SLIDER(0)); count += check_axis(DIJOFS_SLIDER(1)); // Should the hat be classified as an axis? count += check_axis(DIJOFS_POV(0)); count += check_axis(DIJOFS_POV(1)); count += check_axis(DIJOFS_POV(2)); count += check_axis(DIJOFS_POV(3)); count += check_axis(DIJOFS_RX); count += check_axis(DIJOFS_RY); count += check_axis(DIJOFS_RZ); count += check_axis(DIJOFS_X); count += check_axis(DIJOFS_Y); count += check_axis(DIJOFS_Z); return count; }
#include <stdarg.h> #include "windef.h" #include "dinput.h" #define numObjects(x) (sizeof(x) / sizeof(x[0])) static const DIOBJECTDATAFORMAT dfDIJoystick[] = { { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0}, { &GUID_POV,DIJOFS_POV(0),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, { &GUID_POV,DIJOFS_POV(1),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, { &GUID_POV,DIJOFS_POV(2),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, { &GUID_POV,DIJOFS_POV(3),DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0}, { NULL,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
/* update_joystick: [joystick thread] * Reads in data for a single DirectInput joystick device, updates * the internal ALLEGRO_JOYSTICK_STATE structure, and generates any Allegro * events required. */ static void update_joystick(ALLEGRO_JOYSTICK_DIRECTX *joy) { DIDEVICEOBJECTDATA buffer[DEVICE_BUFFER_SIZE]; DWORD num_items = DEVICE_BUFFER_SIZE; HRESULT hr; ALLEGRO_EVENT_SOURCE *es = al_get_joystick_event_source(); /* some devices require polling */ IDirectInputDevice8_Poll(joy->device); /* get device data into buffer */ hr = IDirectInputDevice8_GetDeviceData(joy->device, sizeof(DIDEVICEOBJECTDATA), buffer, &num_items, 0); if (hr != DI_OK && hr != DI_BUFFEROVERFLOW) { if ((hr == DIERR_NOTACQUIRED) || (hr == DIERR_INPUTLOST)) { ALLEGRO_WARN("joystick device not acquired or lost\n"); } else { ALLEGRO_ERROR("unexpected error while polling the joystick\n"); } return; } /* don't bother locking the event source if there's no work to do */ /* this happens a lot for polled devices */ if (num_items == 0) return; _al_event_source_lock(es); { unsigned int i; for (i = 0; i < num_items; i++) { const DIDEVICEOBJECTDATA *item = &buffer[i]; const int dwOfs = item->dwOfs; const DWORD dwData = item->dwData; switch (dwOfs) { case DIJOFS_X: handle_axis_event(joy, &joy->x_mapping, dwData); break; case DIJOFS_Y: handle_axis_event(joy, &joy->y_mapping, dwData); break; case DIJOFS_Z: handle_axis_event(joy, &joy->z_mapping, dwData); break; case DIJOFS_RX: handle_axis_event(joy, &joy->rx_mapping, dwData); break; case DIJOFS_RY: handle_axis_event(joy, &joy->ry_mapping, dwData); break; case DIJOFS_RZ: handle_axis_event(joy, &joy->rz_mapping, dwData); break; case DIJOFS_SLIDER(0): handle_axis_event(joy, &joy->slider_mapping[0], dwData); break; case DIJOFS_SLIDER(1): handle_axis_event(joy, &joy->slider_mapping[1], dwData); break; case DIJOFS_POV(0): handle_pov_event(joy, joy->pov_mapping_stick[0], dwData); break; case DIJOFS_POV(1): handle_pov_event(joy, joy->pov_mapping_stick[1], dwData); break; case DIJOFS_POV(2): handle_pov_event(joy, joy->pov_mapping_stick[2], dwData); break; case DIJOFS_POV(3): handle_pov_event(joy, joy->pov_mapping_stick[3], dwData); break; default: /* buttons */ if ((dwOfs >= DIJOFS_BUTTON0) && (dwOfs < DIJOFS_BUTTON(joy->parent.info.num_buttons))) { int num = (dwOfs - DIJOFS_BUTTON0) / (DIJOFS_BUTTON1 - DIJOFS_BUTTON0); handle_button_event(joy, num, (dwData & 0x80)); } break; } } } _al_event_source_unlock(es); }
// this function sets the input range to -100 <-> +100 (we already do that in sdl) // it also sets the dead zone which we do not support in sdl yet.. probably easy to do though... void SetUpJoystickAxis(int joystick) { DIPROPRANGE diprg; bool DeadzoneNotSet = false; int i; // set axis range to (-100 ... +100) // This lets us test against 0 to see which way the stick is pointed. diprg.diph.dwSize = sizeof(diprg); diprg.diph.dwHeaderSize = sizeof(diprg.diph); diprg.diph.dwHow = DIPH_BYOFFSET; diprg.lMin = -100; diprg.lMax = +100; DebugPrintf( "SetUpJoystickAxis: setting up %d axes for joystick #%d='%s'\n", JoystickInfo[ joystick ].NumAxis, joystick, JoystickInfo[ joystick ].Name ); if (JoystickInfo[joystick].Axis[AXIS_XAxis].exists) { DebugPrintf( "SetUpJoystickAxis: setting up X axis range=(%d,%d) for joystick #%d='%s'\n", diprg.lMin, diprg.lMax, joystick, JoystickInfo[ joystick ].Name ); diprg.diph.dwObj = DIJOFS_X; if( !lpdiJoystick[joystick] ) { JoystickInfo[joystick].Axis[AXIS_XAxis].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for X axis because lpdiJoystick[joystick] is NULL\n" ); } else if ( lpdiJoystick[joystick]->lpVtbl->SetProperty(lpdiJoystick[joystick], DIPROP_RANGE, &diprg.diph) != DI_OK) { JoystickInfo[joystick].Axis[AXIS_XAxis].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for X axis\n" ); } else { // set dead zone // Units are ten thousandths, so multiply %age by 100. DebugPrintf( "SetUpJoystickAxis: setting up X axis deadzone=%d for joystick #%d='%s'\n", JoystickInfo[ joystick ].Axis[AXIS_XAxis].deadzone, joystick, JoystickInfo[ joystick ].Name ); if (SetDIDwordProperty(lpdiJoystick[joystick], DIPROP_DEADZONE, DIJOFS_X, DIPH_BYOFFSET, (DWORD)(JoystickInfo[joystick].Axis[AXIS_XAxis].deadzone * 100)) != DI_OK) { // cannot set deadzone - but just ignore for now... DeadzoneNotSet = true; DebugPrintf( "SetUpJoystickAxis: failed to set deadzone for X axis\n" ); } } } if (JoystickInfo[joystick].Axis[AXIS_YAxis].exists) { DebugPrintf( "SetUpJoystickAxis: setting up Y axis range=(%d,%d) for joystick #%d='%s'\n", diprg.lMin, diprg.lMax, joystick, JoystickInfo[ joystick ].Name ); diprg.diph.dwObj = DIJOFS_Y; if(lpdiJoystick[joystick]->lpVtbl->SetProperty(lpdiJoystick[joystick], DIPROP_RANGE, &diprg.diph) != DI_OK) { JoystickInfo[joystick].Axis[AXIS_YAxis].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for Y axis\n" ); }else { DebugPrintf( "SetUpJoystickAxis: setting up Y axis deadzone=%d for joystick #%d='%s'\n", JoystickInfo[ joystick ].Axis[AXIS_YAxis].deadzone, joystick, JoystickInfo[ joystick ].Name ); if (SetDIDwordProperty(lpdiJoystick[joystick], DIPROP_DEADZONE, DIJOFS_Y, DIPH_BYOFFSET, (DWORD)(JoystickInfo[joystick].Axis[AXIS_YAxis].deadzone * 100)) != DI_OK) { // cannot set deadzone - but just ignore for now... DeadzoneNotSet = true; DebugPrintf( "SetUpJoystickAxis: failed to set deadzone for Y axis\n" ); } } } if (JoystickInfo[joystick].Axis[AXIS_ZAxis].exists) { DebugPrintf( "SetUpJoystickAxis: setting up Z axis range=(%d,%d) for joystick #%d='%s'\n", diprg.lMin, diprg.lMax, joystick, JoystickInfo[ joystick ].Name ); diprg.diph.dwObj = DIJOFS_Z; if(lpdiJoystick[joystick]->lpVtbl->SetProperty(lpdiJoystick[joystick], DIPROP_RANGE, &diprg.diph) != DI_OK) { JoystickInfo[joystick].Axis[AXIS_ZAxis].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for Z axis\n" ); }else { DebugPrintf( "SetUpJoystickAxis: setting up Z axis deadzone=%d for joystick #%d='%s'\n", JoystickInfo[ joystick ].Axis[AXIS_ZAxis].deadzone, joystick, JoystickInfo[ joystick ].Name ); if (SetDIDwordProperty(lpdiJoystick[joystick], DIPROP_DEADZONE, DIJOFS_Z, DIPH_BYOFFSET, (DWORD)(JoystickInfo[joystick].Axis[AXIS_ZAxis].deadzone * 100)) != DI_OK) { // cannot set deadzone - but just ignore for now... DeadzoneNotSet = true; DebugPrintf( "SetUpJoystickAxis: failed to set deadzone for Z axis\n" ); } } } if (JoystickInfo[joystick].Axis[AXIS_RxAxis].exists) { DebugPrintf( "SetUpJoystickAxis: setting up Rx axis range=(%d,%d) for joystick #%d='%s'\n", diprg.lMin, diprg.lMax, joystick, JoystickInfo[ joystick ].Name ); diprg.diph.dwObj = DIJOFS_RX; if(lpdiJoystick[joystick]->lpVtbl->SetProperty(lpdiJoystick[joystick], DIPROP_RANGE, &diprg.diph) != DI_OK) { JoystickInfo[joystick].Axis[AXIS_RxAxis].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for Rx axis\n" ); }else { DebugPrintf( "SetUpJoystickAxis: setting up Rx axis deadzone=%d for joystick #%d='%s'\n", JoystickInfo[ joystick ].Axis[AXIS_RxAxis].deadzone, joystick, JoystickInfo[ joystick ].Name ); if (SetDIDwordProperty(lpdiJoystick[joystick], DIPROP_DEADZONE, DIJOFS_RX, DIPH_BYOFFSET, (DWORD)(JoystickInfo[joystick].Axis[AXIS_RxAxis].deadzone * 100)) != DI_OK) { // cannot set deadzone - but just ignore for now... DeadzoneNotSet = true; DebugPrintf( "SetUpJoystickAxis: failed to set deadzone for Rx axis\n" ); } } } if (JoystickInfo[joystick].Axis[AXIS_RyAxis].exists) { DebugPrintf( "SetUpJoystickAxis: setting up Ry axis range=(%d,%d) for joystick #%d='%s'\n", diprg.lMin, diprg.lMax, joystick, JoystickInfo[ joystick ].Name ); diprg.diph.dwObj = DIJOFS_RY; if(lpdiJoystick[joystick]->lpVtbl->SetProperty(lpdiJoystick[joystick], DIPROP_RANGE, &diprg.diph) != DI_OK) { JoystickInfo[joystick].Axis[AXIS_RyAxis].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for Ry axis\n" ); }else { DebugPrintf( "SetUpJoystickAxis: setting up Ry axis deadzone=%d for joystick #%d='%s'\n", JoystickInfo[ joystick ].Axis[AXIS_RyAxis].deadzone, joystick, JoystickInfo[ joystick ].Name ); if (SetDIDwordProperty(lpdiJoystick[joystick], DIPROP_DEADZONE, DIJOFS_RY, DIPH_BYOFFSET, (DWORD)(JoystickInfo[joystick].Axis[AXIS_RyAxis].deadzone * 100)) != DI_OK) { // cannot set deadzone - but just ignore for now... DeadzoneNotSet = true; DebugPrintf( "SetUpJoystickAxis: failed to set deadzone for Ry axis\n" ); } } } if (JoystickInfo[joystick].Axis[AXIS_RzAxis].exists) { DebugPrintf( "SetUpJoystickAxis: setting up Rz axis range=(%d,%d) for joystick #%d='%s'\n", diprg.lMin, diprg.lMax, joystick, JoystickInfo[ joystick ].Name ); diprg.diph.dwObj = DIJOFS_RZ; if(lpdiJoystick[joystick]->lpVtbl->SetProperty(lpdiJoystick[joystick], DIPROP_RANGE, &diprg.diph) != DI_OK) { JoystickInfo[joystick].Axis[AXIS_RzAxis].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for Rz axis\n" ); }else { DebugPrintf( "SetUpJoystickAxis: setting up Rz axis deadzone=%d for joystick #%d='%s'\n", JoystickInfo[ joystick ].Axis[AXIS_RzAxis].deadzone, joystick, JoystickInfo[ joystick ].Name ); if (SetDIDwordProperty(lpdiJoystick[joystick], DIPROP_DEADZONE, DIJOFS_RZ, DIPH_BYOFFSET, (DWORD)(JoystickInfo[joystick].Axis[AXIS_RzAxis].deadzone * 100)) != DI_OK) { // cannot set deadzone - but just ignore for now... DeadzoneNotSet = true; DebugPrintf( "SetUpJoystickAxis: failed to set deadzone for Rz axis\n" ); } } } for (i = 0; i < 2; i++) { if (JoystickInfo[joystick].Axis[AXIS_SliderAxis0 + i].exists) { DebugPrintf( "SetUpJoystickAxis: setting up Slider%d range=(%d,%d) for joystick #%d='%s'\n", i, diprg.lMin, diprg.lMax, joystick, JoystickInfo[ joystick ].Name ); diprg.diph.dwObj = DIJOFS_SLIDER(i); if(lpdiJoystick[joystick]->lpVtbl->SetProperty(lpdiJoystick[joystick], DIPROP_RANGE, &diprg.diph) != DI_OK) { JoystickInfo[joystick].Axis[AXIS_SliderAxis0 + i].exists = false; // cannot set range, therefore do not allow axis DebugPrintf( "SetUpJoystickAxis: failed to set range for Slider%d axis\n", i ); }else { DebugPrintf( "SetUpJoystickAxis: setting up Slider%d deadzone=%d for joystick #%d='%s'\n", i, JoystickInfo[ joystick ].Axis[AXIS_SliderAxis0 + i].deadzone, joystick, JoystickInfo[ joystick ].Name ); if (SetDIDwordProperty(lpdiJoystick[joystick], DIPROP_DEADZONE, DIJOFS_SLIDER(i), DIPH_BYOFFSET, (DWORD)(JoystickInfo[joystick].Axis[AXIS_SliderAxis0 + i].deadzone * 100)) != DI_OK) { // cannot set deadzone - but just ignore for now... DeadzoneNotSet = true; DebugPrintf( "SetUpJoystickAxis: failed to set deadzone for Slider%d axis\n", i ); } } } } // could do something about unset deadzones here... if (DeadzoneNotSet) DeadzoneNotSet = false; }
/* Function to update the state of a joystick - called as a device poll. * This function shouldn't update the joystick structure directly, * but instead should call SDL_PrivateJoystick*() to deliver events * and update joystick device state. */ static void UpdateDINPUTJoystickState_Polled(SDL_Joystick * joystick) { DIJOYSTATE2 state; HRESULT result; int i; result = IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice, sizeof(DIJOYSTATE2), &state); if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { IDirectInputDevice8_Acquire(joystick->hwdata->InputDevice); result = IDirectInputDevice8_GetDeviceState(joystick->hwdata->InputDevice, sizeof(DIJOYSTATE2), &state); } if (result != DI_OK) { joystick->hwdata->send_remove_event = SDL_TRUE; joystick->hwdata->removed = SDL_TRUE; return; } /* Set each known axis, button and POV. */ for (i = 0; i < joystick->hwdata->NumInputs; ++i) { const input_t *in = &joystick->hwdata->Inputs[i]; switch (in->type) { case AXIS: switch (in->ofs) { case DIJOFS_X: SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lX); break; case DIJOFS_Y: SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lY); break; case DIJOFS_Z: SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lZ); break; case DIJOFS_RX: SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRx); break; case DIJOFS_RY: SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRy); break; case DIJOFS_RZ: SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.lRz); break; case DIJOFS_SLIDER(0): SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[0]); break; case DIJOFS_SLIDER(1): SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)state.rglSlider[1]); break; } break; case BUTTON: SDL_PrivateJoystickButton(joystick, in->num, (Uint8)(state.rgbButtons[in->ofs - DIJOFS_BUTTON0] ? SDL_PRESSED : SDL_RELEASED)); break; case HAT: { Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]); SDL_PrivateJoystickHat(joystick, in->num, pos); break; } } } }
static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) { SDL_Joystick *joystick = (SDL_Joystick *)pvRef; HRESULT result; input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; if (dev->dwType & DIDFT_BUTTON) { in->type = BUTTON; in->num = joystick->nbuttons; in->ofs = DIJOFS_BUTTON(in->num); joystick->nbuttons++; } else if (dev->dwType & DIDFT_POV) { in->type = HAT; in->num = joystick->nhats; in->ofs = DIJOFS_POV(in->num); joystick->nhats++; } else if (dev->dwType & DIDFT_AXIS) { DIPROPRANGE diprg; DIPROPDWORD dilong; in->type = AXIS; in->num = joystick->naxes; if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType))) in->ofs = DIJOFS_X; else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType))) in->ofs = DIJOFS_Y; else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType))) in->ofs = DIJOFS_Z; else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType))) in->ofs = DIJOFS_RX; else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType))) in->ofs = DIJOFS_RY; else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType))) in->ofs = DIJOFS_RZ; else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) { in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders); ++joystick->hwdata->NumSliders; } else { return DIENUM_CONTINUE; /* not an axis we can grok */ } diprg.diph.dwSize = sizeof(diprg); diprg.diph.dwHeaderSize = sizeof(diprg.diph); diprg.diph.dwObj = dev->dwType; diprg.diph.dwHow = DIPH_BYID; diprg.lMin = SDL_JOYSTICK_AXIS_MIN; diprg.lMax = SDL_JOYSTICK_AXIS_MAX; result = IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice, DIPROP_RANGE, &diprg.diph); if (FAILED(result)) { return DIENUM_CONTINUE; /* don't use this axis */ } /* Set dead zone to 0. */ dilong.diph.dwSize = sizeof(dilong); dilong.diph.dwHeaderSize = sizeof(dilong.diph); dilong.diph.dwObj = dev->dwType; dilong.diph.dwHow = DIPH_BYID; dilong.dwData = 0; result = IDirectInputDevice8_SetProperty(joystick->hwdata->InputDevice, DIPROP_DEADZONE, &dilong.diph); if (FAILED(result)) { return DIENUM_CONTINUE; /* don't use this axis */ } joystick->naxes++; } else { /* not supported at this time */ return DIENUM_CONTINUE; } joystick->hwdata->NumInputs++; if (joystick->hwdata->NumInputs == MAX_INPUTS) { return DIENUM_STOP; /* too many */ } return DIENUM_CONTINUE; }
static void checkJoypads() { DIDEVICEOBJECTINSTANCE di; ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE)); di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); int i =0; DIJOYSTATE joystick; for (i = 1; i < numDevices; i++) { HRESULT hret = pDevices[i].device->Acquire(); if (pDevices[i].isPolled) ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll(); hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick); int j; if (pDevices[i].first) { memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); pDevices[i].first = FALSE; continue; } for (j = 0; j < pDevices[i].nButtons; j++) { if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j]) & joystick.rgbButtons[j]) & 0x80) { HWND focus = GetFocus(); SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128); } } for (j = 0; j < pDevices[i].nAxes && j < 8; j++) { LONG value = pDevices[i].axis[j].center; LONG old = 0; switch (pDevices[i].axis[j].offset) { case DIJOFS_X: value = joystick.lX; old = pDevices[i].state.lX; break; case DIJOFS_Y: value = joystick.lY; old = pDevices[i].state.lY; break; case DIJOFS_Z: value = joystick.lZ; old = pDevices[i].state.lZ; break; case DIJOFS_RX: value = joystick.lRx; old = pDevices[i].state.lRx; break; case DIJOFS_RY: value = joystick.lRy; old = pDevices[i].state.lRy; break; case DIJOFS_RZ: value = joystick.lRz; old = pDevices[i].state.lRz; break; case DIJOFS_SLIDER(0): value = joystick.rglSlider[0]; old = pDevices[i].state.rglSlider[0]; break; case DIJOFS_SLIDER(1): value = joystick.rglSlider[1]; old = pDevices[i].state.rglSlider[1]; break; } if (value != old) { if (value < pDevices[i].axis[j].negative) SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)); else if (value > pDevices[i].axis[j].positive) SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1); } } for (j = 0;j < 4 && j < pDevices[i].nPovs; j++) { if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) { int state = getPovState(joystick.rgdwPOV[j]); if (state & POV_UP) SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20); else if (state & POV_DOWN) SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21); else if (state & POV_RIGHT) SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22); else if (state & POV_LEFT) SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23); } } memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); } }
void DIInitJoysticks() { HRESULT hr; hr=CoCreateInstance(CLSID_DirectInput,NULL,CLSCTX_ALL,IID_IDirectInput,(void**)&DIObj); if (FAILED(hr)) return; hr=DIObj->Initialize(GetModuleHandle(NULL),DIRECTINPUT_VERSION); if (FAILED(hr)){ DIFreeJoysticks();return; } hr=DIObj->EnumDevices(DIDEVTYPE_JOYSTICK,DIEnumJoysticksCallback,NULL,DIEDFL_ALLDEVICES); if (FAILED(hr) || NumJoysticks==0){ DIFreeJoysticks();return; } // Set up data format const GUID* AxisList[]={&GUID_XAxis,&GUID_YAxis,&GUID_ZAxis,&GUID_RxAxis,&GUID_RyAxis, &GUID_RzAxis,&GUID_Slider,&GUID_Slider,NULL}; int Offset=FIELD_OFFSET(DIJOYSTATE,lX); int i=0; while (AxisList[i]){ DIJoyDataFormatObjects[i].pguid=AxisList[i]; DIJoyDataFormatObjects[i].dwOfs=Offset; DIJoyDataFormatObjects[i].dwType=DIDFT_AXIS | DIFT_ALLOWNOTEXIST | DIDFT_ANYINSTANCE; DIJoyDataFormatObjects[i].dwFlags=DIDOI_ASPECTPOSITION; Offset+=sizeof(LONG); i++; } for (int n=0;n<4;n++){ DIJoyDataFormatObjects[i].pguid=&GUID_POV; DIJoyDataFormatObjects[i].dwOfs=FIELD_OFFSET(DIJOYSTATE,rgdwPOV[n]); DIJoyDataFormatObjects[i].dwType=DIDFT_POV | DIFT_ALLOWNOTEXIST | DIDFT_ANYINSTANCE; DIJoyDataFormatObjects[i].dwFlags=0; i++; } for (int n=0;n<32;n++){ DIJoyDataFormatObjects[i].pguid=NULL; DIJoyDataFormatObjects[i].dwOfs=FIELD_OFFSET(DIJOYSTATE,rgbButtons[n]); DIJoyDataFormatObjects[i].dwType=DIDFT_BUTTON | DIFT_ALLOWNOTEXIST | DIDFT_ANYINSTANCE; DIJoyDataFormatObjects[i].dwFlags=0; i++; if (i>DIJOY_MAX_DATAOBJECT) break; } DIJoyDataFormat.dwNumObjs=i; for (int j=0;j<MAX_PC_JOYS;j++){ if (DIJoy[j]){ JoyExists[j]=true; DIJoy[j]->SetDataFormat(&DIJoyDataFormat); DIJoy[j]->SetCooperativeLevel(StemWin,DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); // Set device wide options DIPROPDWORD dip={{sizeof(DIPROPDWORD),sizeof(DIPROPHEADER),0,DIPH_DEVICE},0}; dip.dwData=DIPROPAXISMODE_ABS; DIJoy[j]->SetProperty(DIPROP_AXISMODE,&dip.diph); dip.dwData=0; DIJoy[j]->SetProperty(DIPROP_DEADZONE,&dip.diph); dip.dwData=10000; DIJoy[j]->SetProperty(DIPROP_SATURATION,&dip.diph); for (int a=0;a<7;a++) JoyInfo[j].AxisExists[a]=0; DIGetAxisInfo(j,DIJOFS_X,AXIS_X); DIGetAxisInfo(j,DIJOFS_Y,AXIS_Y); DIGetAxisInfo(j,DIJOFS_Z,AXIS_Z); DIGetAxisInfo(j,DIJOFS_SLIDER(0),AXIS_U); DIGetAxisInfo(j,DIJOFS_SLIDER(1),AXIS_V); int rofs[3]={DIJOFS_RZ,DIJOFS_RX,DIJOFS_RY}; DI_RnMap[j][0]=-1, DI_RnMap[j][1]=-1, DI_RnMap[j][2]=-1; for (int i=0;i<3;i++){ int axnum=-1; for (int a=0;a<AXIS_POV;a++){ if (JoyInfo[j].AxisExists[a]==0){ axnum=a; break; } } if (axnum<0) break; DIGetAxisInfo(j,rofs[i],axnum); if (JoyInfo[j].AxisExists[axnum]) DI_RnMap[j][i]=axnum; } DIPOVNum=-1; for (int i=0;i<4;i++){ DIDEVICEOBJECTINSTANCE didoi; didoi.dwSize=sizeof(DIDEVICEOBJECTINSTANCE); if (DIJoy[j]->GetObjectInfo(&didoi,DIJOFS_POV(i),DIPH_BYOFFSET)==DI_OK){ DIPOVNum=i; JoyInfo[j].AxisExists[AXIS_POV]=true; break; } } // This is just in case getting positions fails silently somehow. DIJoyPos[j].lX=JoyInfo[j].AxisMid[AXIS_X]; DIJoyPos[j].lY=JoyInfo[j].AxisMid[AXIS_Y]; DIJoyPos[j].lZ=JoyInfo[j].AxisMid[AXIS_Z]; DIJoyPos[j].rglSlider[0]=JoyInfo[j].AxisMid[AXIS_U]; DIJoyPos[j].rglSlider[1]=JoyInfo[j].AxisMid[AXIS_V]; for (int p=0;p<4;p++) DIJoyPos[j].rgdwPOV[p]=0xffffffff; if (DI_RnMap[j][0]>=0) DIJoyPos[j].lRz=JoyInfo[j].AxisMid[DI_RnMap[j][0]]; if (DI_RnMap[j][1]>=0) DIJoyPos[j].lRx=JoyInfo[j].AxisMid[DI_RnMap[j][1]]; if (DI_RnMap[j][2]>=0) DIJoyPos[j].lRy=JoyInfo[j].AxisMid[DI_RnMap[j][2]]; JoyInfo[j].NumButtons=31; ZeroMemory(DIJoyPos[j].rgbButtons,sizeof(DIJoyPos[j].rgbButtons)); DIDisconnected[j]=50; DIJoy[j]->Acquire(); } } }
void InputHandler_DInput::UpdateBuffered(DIDevice &device, const RageTimer &tm) { DWORD numevents; DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; numevents = INPUT_QSIZE; HRESULT hr = IDirectInputDevice2_GetDeviceData( device.Device, sizeof(DIDEVICEOBJECTDATA), evtbuf, &numevents, 0); if ( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED ) return; /* Handle the events */ if ( hr != DI_OK ) { LOG->Trace( hr_ssprintf(hr, "UpdateBuffered: IDirectInputDevice2_GetDeviceData") ); return; } /* XXX: We should check GetConsoleWindow(), to allow input while the console window * is focused. */ if( GetForegroundWindow() != GraphicsWindow::GetHwnd() ) return; for(int i = 0; i < (int) numevents; ++i) { for(unsigned j = 0; j < device.Inputs.size(); ++j) { const input_t &in = device.Inputs[j]; const InputDevice dev = device.dev; if(evtbuf[i].dwOfs != in.ofs) continue; switch(in.type) { case in.KEY: ButtonPressed(DeviceInput(dev, in.num, -1, tm), !!(evtbuf[i].dwData & 0x80)); break; case in.BUTTON: ButtonPressed(DeviceInput(dev, JOY_1 + in.num, -1, tm), !!evtbuf[i].dwData); break; case in.AXIS: { int up = 0, down = 0; switch(in.ofs) { case DIJOFS_X: up = JOY_LEFT; down = JOY_RIGHT; break; case DIJOFS_Y: up = JOY_UP; down = JOY_DOWN; break; case DIJOFS_Z: up = JOY_Z_UP; down = JOY_Z_DOWN; break; case DIJOFS_RX: up = JOY_ROT_UP; down = JOY_ROT_DOWN; break; case DIJOFS_RY: up = JOY_ROT_LEFT; down = JOY_ROT_RIGHT; break; case DIJOFS_RZ: up = JOY_ROT_Z_UP; down = JOY_ROT_Z_DOWN; break; case DIJOFS_SLIDER(0): up = JOY_AUX_1; down = JOY_AUX_2; break; case DIJOFS_SLIDER(1): up = JOY_AUX_3; down = JOY_AUX_4; break; default: LOG->MapLog("unknown input", "Controller '%s' is returning an unknown joystick offset, %i", device.JoystickInst.tszProductName, in.ofs ); continue; } float l = SCALE( int(evtbuf[i].dwData), 0.0f, 100.0f, 0.0f, 1.0f ); ButtonPressed(DeviceInput(dev, up, max(-l,0), tm), int(evtbuf[i].dwData) < -50); ButtonPressed(DeviceInput(dev, down, max(+l,0), tm), int(evtbuf[i].dwData) > 50); break; } case in.HAT: { const int pos = TranslatePOV(evtbuf[i].dwData); ButtonPressed(DeviceInput(dev, JOY_HAT_UP, -1, tm), !!(pos & HAT_UP_MASK)); ButtonPressed(DeviceInput(dev, JOY_HAT_DOWN, -1, tm), !!(pos & HAT_DOWN_MASK)); ButtonPressed(DeviceInput(dev, JOY_HAT_LEFT, -1, tm), !!(pos & HAT_LEFT_MASK)); ButtonPressed(DeviceInput(dev, JOY_HAT_RIGHT, -1, tm), !!(pos & HAT_RIGHT_MASK)); } } } } }
/* This doesn't take a timestamp; instead, we let InputHandler::ButtonPressed figure * it out. Be sure to call InputHandler::Update() between each poll. */ void InputHandler_DInput::UpdatePolled(DIDevice &device, const RageTimer &tm) { if( device.type == device.KEYBOARD ) { unsigned char keys[256]; HRESULT hr = GetDeviceState(device.Device, 256, keys); if ( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED ) return; if ( hr != DI_OK ) { LOG->MapLog( "UpdatePolled", hr_ssprintf(hr, "Failures on polled keyboard update") ); return; } for( int k = 0; k < 256; ++k ) { const int key = device.Inputs[k].num; ButtonPressed(DeviceInput(device.dev, key), !!(keys[k] & 0x80)); } return; } DIJOYSTATE state; HRESULT hr = GetDeviceState(device.Device, sizeof(state), &state); if ( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED ) return; /* Set each known axis, button and POV. */ for(unsigned i = 0; i < device.Inputs.size(); ++i) { const input_t &in = device.Inputs[i]; const InputDevice dev = device.dev; switch(in.type) { case in.BUTTON: { DeviceInput di(dev, JOY_1 + in.num, -1, tm); ButtonPressed(di, !!state.rgbButtons[in.ofs - DIJOFS_BUTTON0]); break; } case in.AXIS: { JoystickButton neg = NUM_JOYSTICK_BUTTONS, pos = NUM_JOYSTICK_BUTTONS; int val = 0; switch(in.ofs) { case DIJOFS_X: neg = JOY_LEFT; pos = JOY_RIGHT; val = state.lX; break; case DIJOFS_Y: neg = JOY_UP; pos = JOY_DOWN; val = state.lY; break; case DIJOFS_Z: neg = JOY_Z_UP; pos = JOY_Z_DOWN; val = state.lZ; break; case DIJOFS_RX: neg = JOY_ROT_LEFT; pos = JOY_ROT_RIGHT; val = state.lRx; break; case DIJOFS_RY: neg = JOY_ROT_UP; pos = JOY_ROT_DOWN; val = state.lRy; break; case DIJOFS_RZ: neg = JOY_ROT_Z_UP; pos = JOY_ROT_Z_DOWN; val = state.lRz; break; case DIJOFS_SLIDER(0): neg = JOY_AUX_1; pos = JOY_AUX_2; val = state.rglSlider[0]; break; case DIJOFS_SLIDER(1): neg = JOY_AUX_3; pos = JOY_AUX_4; val = state.rglSlider[1]; break; default: LOG->MapLog("unknown input", "Controller '%s' is returning an unknown joystick offset, %i", device.JoystickInst.tszProductName, in.ofs ); continue; } if( neg != NUM_JOYSTICK_BUTTONS ) { float l = SCALE( int(val), 0.0f, 100.0f, 0.0f, 1.0f ); ButtonPressed(DeviceInput(dev, neg, max(-l,0), tm), val < -50); ButtonPressed(DeviceInput(dev, pos, max(+l,0), tm), val > 50); } break; } case in.HAT: if( in.num == 0 ) { const int pos = TranslatePOV(state.rgdwPOV[in.ofs - DIJOFS_POV(0)]); ButtonPressed(DeviceInput(dev, JOY_HAT_UP, -1, tm), !!(pos & HAT_UP_MASK)); ButtonPressed(DeviceInput(dev, JOY_HAT_DOWN, -1, tm), !!(pos & HAT_DOWN_MASK)); ButtonPressed(DeviceInput(dev, JOY_HAT_LEFT, -1, tm), !!(pos & HAT_LEFT_MASK)); ButtonPressed(DeviceInput(dev, JOY_HAT_RIGHT, -1, tm), !!(pos & HAT_RIGHT_MASK)); } break; } } }
fResult f2dInputJoystickImpl::UpdateState() { DIDEVICEOBJECTDATA tRawData[BufferSize]; DWORD tSize = BufferSize; HRESULT tHR = m_pDev->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), tRawData, &tSize, 0); if(FAILED(tHR)) { tHR = m_pDev->Acquire(); if(FAILED(tHR)) return FCYERR_INTERNALERR; else { tSize = BufferSize; tHR = m_pDev->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), tRawData, &tSize, 0); if(FAILED(tHR)) return FCYERR_INTERNALERR; } } for(fuInt i = 0; i<tSize; ++i) { float tValue = 0.f; switch(tRawData[i].dwOfs) { case DIJOFS_X: tValue = ((int)tRawData[i].dwData - m_lXHalf) / (float)(m_lXHalfLen); m_lX = tValue; if(m_pListener) m_pListener->OnJoystickXAxisPosChange(tValue); break; case DIJOFS_Y: tValue = ((int)tRawData[i].dwData - m_lYHalf) / (float)(m_lYHalfLen); m_lY = tValue; if(m_pListener) m_pListener->OnJoystickYAxisPosChange(tValue); break; case DIJOFS_Z: tValue = ((int)tRawData[i].dwData - m_lZHalf) / (float)(m_lZHalfLen); m_lZ = tValue; if(m_pListener) m_pListener->OnJoystickZAxisPosChange(tValue); break; case DIJOFS_RX: tValue = ((int)tRawData[i].dwData - m_lRxHalf) / (float)(m_lRxHalfLen); m_lRx = tValue; if(m_pListener) m_pListener->OnJoystickXAxisRotationChange(tValue); break; case DIJOFS_RY: tValue = ((int)tRawData[i].dwData - m_lRyHalf) / (float)(m_lRyHalfLen); m_lRy = tValue; if(m_pListener) m_pListener->OnJoystickYAxisRotationChange(tValue); break; case DIJOFS_RZ: tValue = ((int)tRawData[i].dwData - m_lRzHalf) / (float)(m_lRzHalfLen); m_lRz = tValue; if(m_pListener) m_pListener->OnJoystickZAxisRotationChange(tValue); break; case DIJOFS_SLIDER(0): m_Slider[0] = tRawData[i].dwData; break; case DIJOFS_SLIDER(1): m_Slider[1] = tRawData[i].dwData; break; case DIJOFS_POV(0): m_POV[0] = tRawData[i].dwData; break; case DIJOFS_POV(1): m_POV[1] = tRawData[i].dwData; break; case DIJOFS_POV(2): m_POV[2] = tRawData[i].dwData; break; case DIJOFS_POV(3): m_POV[3] = tRawData[i].dwData; break; default: if(tRawData[i].dwOfs>=DIJOFS_BUTTON0 && tRawData[i].dwOfs<=DIJOFS_BUTTON31) { bool tDown = (LOWORD(tRawData[i].dwData)&0x80) != 0; m_ButtonDown[tRawData[i].dwOfs - DIJOFS_BUTTON0] = tDown; if(m_pListener) if(tDown) m_pListener->OnJoystickBtnDown(tRawData[i].dwOfs - DIJOFS_BUTTON0); else m_pListener->OnJoystickBtnUp(tRawData[i].dwOfs - DIJOFS_BUTTON0); } } } return FCYERR_OK; }
boolean I_InitJoystick(void) { DIDEVICEINSTANCE ddi; int i, joyProp[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1) }; const char *axisName[] = { "X", "Y", "Z", "RX", "RY", "RZ", "Slider 1", "Slider 2" }; HWND hWnd; HRESULT hr; if(ArgCheck("-nojoy")) return false; hWnd = Sys_GetWindowHandle(mainWindowIdx); if(!hWnd) { Con_Error("I_InitJoystick: Main window not available, cannot init joystick."); return false; } // ddi will contain info for the joystick device. memset(&firstJoystick, 0, sizeof(firstJoystick)); memset(&ddi, 0, sizeof(ddi)); counter = 0; // Find the joystick we want by doing an enumeration. IDirectInput_EnumDevices(dInput, DI8DEVCLASS_GAMECTRL, I_JoyEnum, &ddi, DIEDFL_ALLDEVICES); // Was the joystick we want found? if(!ddi.dwSize) { // Use the default joystick. if(!firstJoystick.dwSize) return false; // Not found. Con_Message("I_InitJoystick: joydevice = %i, out of range.\n", joydevice); // Use the first joystick that was found. memcpy(&ddi, &firstJoystick, sizeof(ddi)); } // Show some info. Con_Message("I_InitJoystick: %s\n", ddi.tszProductName); // Create the joystick device. hr = IDirectInput8_CreateDevice(dInput, &ddi.guidInstance, &didJoy, 0); if(FAILED(hr)) { Con_Message("I_InitJoystick: Failed to create device (0x%x).\n", hr); return false; } // Set data format. if(FAILED(hr = IDirectInputDevice_SetDataFormat(didJoy, &c_dfDIJoystick))) { Con_Message("I_InitJoystick: Failed to set data format (0x%x).\n", hr); goto kill_joy; } // Set behaviour. if(FAILED (hr = IDirectInputDevice_SetCooperativeLevel(didJoy, hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND))) { Con_Message("I_InitJoystick: Failed to set co-op level (0x%x: %s).\n", hr, I_ErrorMsg(hr)); goto kill_joy; } // Set properties. for(i = 0; i < sizeof(joyProp) / sizeof(joyProp[0]); i++) { if(FAILED (hr = I_SetRangeProperty(didJoy, DIPROP_RANGE, DIPH_BYOFFSET, joyProp[i], IJOY_AXISMIN, IJOY_AXISMAX))) { if(verbose) Con_Message("I_InitJoystick: Failed to set %s " "range (0x%x: %s).\n", axisName[i], hr, I_ErrorMsg(hr)); } } // Set no dead zone. if(FAILED(hr = I_SetProperty(didJoy, DIPROP_DEADZONE, DIPH_DEVICE, 0, 0))) { Con_Message("I_InitJoystick: Failed to set dead zone (0x%x: %s).\n", hr, I_ErrorMsg(hr)); } // Set absolute mode. if(FAILED (hr = I_SetProperty(didJoy, DIPROP_AXISMODE, DIPH_DEVICE, 0, DIPROPAXISMODE_ABS))) { Con_Message ("I_InitJoystick: Failed to set absolute axis mode (0x%x: %s).\n", hr, I_ErrorMsg(hr)); } // Acquire it. IDirectInputDevice_Acquire(didJoy); // Initialization was successful. return true; kill_joy: I_SAFE_RELEASE(didJoy); return false; }