void Joystick_DX5::RequestExclusive(bool value) { if(value != have_exclusive_access) { if(value && SUCCEEDED(dev->SetCooperativeLevel(GetDesktopWindow(), DISCL_BACKGROUND | DISCL_EXCLUSIVE)) && SUCCEEDED(dev->Acquire())) have_exclusive_access = true; else { have_exclusive_access = false; dev->SetCooperativeLevel(GetDesktopWindow(), DISCL_BACKGROUND | DISCL_NONEXCLUSIVE); dev->Acquire(); } } }
void ReadJoystick (int nJoystick_, LPDIRECTINPUTDEVICE2 pDevice_) { HRESULT hr; int i; DIJOYSTATE dijs = { 0 }; if (pDevice_ && (FAILED(hr = pDevice_->Poll()) || FAILED(hr = pDevice_->GetDeviceState(sizeof(dijs), &dijs)))) { if (FAILED(hr = pDevice_->Acquire())) return; if (FAILED(hr = pDevice_->Poll()) || FAILED(hr = pDevice_->GetDeviceState(sizeof(dijs), &dijs))) TRACE("!!! Failed to read joystick %d state (%#08lx)\n", nJoystick_, hr); } DWORD dwButtons = 0; int nPosition = HJ_CENTRE; // Combine the states of all buttons so any button works as fire for (i = 0 ; i < _countof(dijs.rgbButtons) ; i++) { if (dijs.rgbButtons[i] & 0x80) dwButtons |= (1 << i); } // Set the position from the main axes if (dijs.lX < 0 || dijs.lRx < 0) nPosition |= HJ_LEFT; if (dijs.lX > 0 || dijs.lRx > 0) nPosition |= HJ_RIGHT; if (dijs.lY < 0 || dijs.lRy < 0) nPosition |= HJ_UP; if (dijs.lY > 0 || dijs.lRy > 0) nPosition |= HJ_DOWN; // Consider all hat positions too for (i = 0 ; i < _countof(dijs.rgdwPOV) ; i++) { static int an[] = { HJ_UP, HJ_UP|HJ_RIGHT, HJ_RIGHT, HJ_DOWN|HJ_RIGHT, HJ_DOWN, HJ_DOWN|HJ_LEFT, HJ_LEFT, HJ_UP|HJ_LEFT }; // For best driver compatibility, only check the low WORD for the centre position if (LOWORD(dijs.rgdwPOV[i]) == 0xffff) continue; // Round the position and determine which of the 8 directions it's pointing int nPos = ((dijs.rgdwPOV[i] + 4500/2) / 4500) & 7; nPosition |= an[nPos]; } Joystick::SetPosition(nJoystick_, nPosition); Joystick::SetButtons(nJoystick_, dwButtons); }
// TODO: RequestExclusive(false) when SetRumble() hasn't been called for several seconds. void Joystick_DX5::UpdateInternal(void) { DIJOYSTATE2 js; HRESULT hres; if(DevCaps.dwFlags & (DIDC_POLLEDDEVICE | DIDC_POLLEDDATAFORMAT)) { do { /* */ hres = dev->Poll(); /* */ } while((hres == DIERR_INPUTLOST) && ((hres = dev->Acquire()) == DI_OK)); if(hres != DI_OK) return; } do { /* */ hres = dev->GetDeviceState(sizeof(js), &js); /* */ } while((hres == DIERR_INPUTLOST) && ((hres = dev->Acquire()) == DI_OK)); if(hres != DI_OK) return; for(unsigned button = 0; button < DevCaps.dwButtons; button++) { button_state[button] = (bool)(js.rgbButtons[button] & 0x80); } for(unsigned axis = 0; axis < DIAxisInfo.size(); axis++) { int64 rv = (&js.lX)[DIAxisInfo[axis].jd_logical_offset]; rv = (((rv - DIAxisInfo[axis].minimum) * 32767 * 2) / (DIAxisInfo[axis].maximum - DIAxisInfo[axis].minimum)) - 32767; if(rv < -32767) rv = -32767; if(rv > 32767) rv = 32767; axis_state[axis] = rv; } for(unsigned hat = 0; hat < DevCaps.dwPOVs; hat++) { DWORD hat_val = js.rgdwPOV[hat]; //if((uint16)hat_val == 0xFFFF) // Reportedly some drivers report 0xFFFF instead of 0xFFFFFFFF? (comment from byuu) if(hat_val >= 36000) { axis_state[(DIAxisInfo.size() + hat * 2) + 0] = 0; axis_state[(DIAxisInfo.size() + hat * 2) + 1] = 0; } else { int32 x, y; //axis_state[(DIAxisInfo.size() + hat * 2) + 0] = 32767 * sin((double)M_PI * 2 * hat_val / 36000); // x //axis_state[(DIAxisInfo.size() + hat * 2) + 1] = 32767 * -cos((double)M_PI * 2 * hat_val / 36000); // y unsigned octant = (hat_val / 4500) & 0x7; signed octant_doff = hat_val % 4500; switch(octant) { case 0: x = octant_doff * 32767 / 4500; y = -32767; break; case 1: x = 32767; y = (-4500 + octant_doff) * 32767 / 4500; break; case 2: x = 32767; y = octant_doff * 32767 / 4500; break; case 3: x = (4500 - octant_doff) * 32767 / 4500; y = 32767; break; case 4: x = (-octant_doff) * 32767 / 4500; y = 32767; break; case 5: x = -32767; y = (4500 - octant_doff) * 32767 / 4500; break; case 6: x = -32767; y = (-octant_doff) * 32767 / 4500; break; case 7: x = (-4500 + octant_doff) * 32767 / 4500; y = -32767; break; } axis_state[(DIAxisInfo.size() + hat * 2) + 0] = x; axis_state[(DIAxisInfo.size() + hat * 2) + 1] = y; } } }