// ****************************************************************** // * // * .,-::::: .,:: .::::::::. .,:: .: // * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; // * [[[ '[[,,[[' [[[__[[\. '[[,,[[' // * $$$ Y$$$P $$""""Y$$ Y$$$P // * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, // * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, // * // * Cxbx->Win32->XBController.cpp // * // * This file is part of the Cxbx project. // * // * Cxbx and Cxbe are free software; you can redistribute them // * and/or modify them under the terms of the GNU General Public // * License as published by the Free Software Foundation; either // * version 2 of the license, or (at your option) any later version. // * // * This program is distributed in the hope that it will be useful, // * but WITHOUT ANY WARRANTY; without even the implied warranty of // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // * GNU General Public License for more details. // * // * You should have recieved a copy of the GNU General Public License // * along with this program; see the file COPYING. // * If not, write to the Free Software Foundation, Inc., // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * // * (c) 2002-2003 Aaron Robinson // * // * All rights reserved // * // ****************************************************************** #include "XBController.h" #include // ****************************************************************** // * func: XBController::XBController // ****************************************************************** XBController::XBController() { int v=0; for(v=0;vEnumDevices ( DI8DEVCLASS_GAMECTRL, WrapEnumGameCtrlCallback, this, DIEDFL_ATTACHEDONLY ); hRet = m_pDirectInput8->CreateDevice(GUID_SysKeyboard, &m_InputDevice[m_dwInputDeviceCount].m_Device, NULL); if(!FAILED(hRet)) { m_InputDevice[m_dwInputDeviceCount].m_Flags = DEVICE_FLAG_KEYBOARD; m_InputDevice[m_dwInputDeviceCount++].m_Device->SetDataFormat(&c_dfDIKeyboard); } hRet = m_pDirectInput8->CreateDevice(GUID_SysMouse, &m_InputDevice[m_dwInputDeviceCount].m_Device, NULL); if(!FAILED(hRet)) { m_InputDevice[m_dwInputDeviceCount].m_Flags = DEVICE_FLAG_MOUSE; m_InputDevice[m_dwInputDeviceCount++].m_Device->SetDataFormat(&c_dfDIMouse2); } } // ****************************************************************** // * Set cooperative level and acquire // ****************************************************************** { for(int v=m_dwInputDeviceCount-1;v>=0;v--) { m_InputDevice[v].m_Device->SetCooperativeLevel(hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); m_InputDevice[v].m_Device->Acquire(); HRESULT hRet = m_InputDevice[v].m_Device->Poll(); if(FAILED(hRet)) { hRet = m_InputDevice[v].m_Device->Acquire(); while(hRet == DIERR_INPUTLOST) hRet = m_InputDevice[v].m_Device->Acquire(); if(hRet != DIERR_INPUTLOST) break; } } } // ****************************************************************** // * Enumerate Controller objects // ****************************************************************** { for(m_dwCurObject=0;m_dwCurObjectEnumObjects(WrapEnumObjectsCallback, this, DIDFT_ALL); } // ****************************************************************** // * Last Mouse Input for Delta Calculations // ****************************************************************** LastMouse_lX = -1; LastMouse_lY = -1; LastMouse_lZ = -1; CurConfigObject = object; cleanup: return; } // ****************************************************************** // * func: XBController::ConfigPoll // ****************************************************************** bool XBController::ConfigPoll(char *szStatus) { DIDEVICEINSTANCE DeviceInstance; DIDEVICEOBJECTINSTANCE ObjectInstance; DeviceInstance.dwSize = sizeof(DIDEVICEINSTANCE); ObjectInstance.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); // ****************************************************************** // * Monitor for significant device state changes // ****************************************************************** for(int v=m_dwInputDeviceCount-1;v>=0;v--) { // ****************************************************************** // * Poll the current device // ****************************************************************** { HRESULT hRet = m_InputDevice[v].m_Device->Poll(); if(FAILED(hRet)) { hRet = m_InputDevice[v].m_Device->Acquire(); while(hRet == DIERR_INPUTLOST) hRet = m_InputDevice[v].m_Device->Acquire(); } } DWORD dwHow = -1, dwFlags = m_InputDevice[v].m_Flags; // ****************************************************************** // * Detect Joystick Input // ****************************************************************** if(m_InputDevice[v].m_Flags & DEVICE_FLAG_JOYSTICK) { DIJOYSTATE JoyState; // ****************************************************************** // * Get Joystick State // ****************************************************************** { HRESULT hRet = m_InputDevice[v].m_Device->GetDeviceState(sizeof(DIJOYSTATE), &JoyState); if(FAILED(hRet)) continue; } dwFlags = DEVICE_FLAG_JOYSTICK; if(abs(JoyState.lX) > DETECT_SENSITIVITY_JOYSTICK) { dwHow = FIELD_OFFSET(DIJOYSTATE, lX); dwFlags |= (JoyState.lX > 0) ? (DEVICE_FLAG_AXIS | DEVICE_FLAG_POSITIVE) : (DEVICE_FLAG_AXIS | DEVICE_FLAG_NEGATIVE); } else if(abs(JoyState.lY) > DETECT_SENSITIVITY_JOYSTICK) { dwHow = FIELD_OFFSET(DIJOYSTATE, lY); dwFlags |= (JoyState.lY > 0) ? (DEVICE_FLAG_AXIS | DEVICE_FLAG_POSITIVE) : (DEVICE_FLAG_AXIS | DEVICE_FLAG_NEGATIVE); } else if(abs(JoyState.lZ) > DETECT_SENSITIVITY_JOYSTICK) { dwHow = FIELD_OFFSET(DIJOYSTATE, lZ); dwFlags |= (JoyState.lZ > 0) ? (DEVICE_FLAG_AXIS | DEVICE_FLAG_POSITIVE) : (DEVICE_FLAG_AXIS | DEVICE_FLAG_NEGATIVE); } else if(abs(JoyState.lRx) > DETECT_SENSITIVITY_JOYSTICK) { dwHow = FIELD_OFFSET(DIJOYSTATE, lRx); dwFlags |= (JoyState.lRx > 0) ? (DEVICE_FLAG_AXIS | DEVICE_FLAG_POSITIVE) : (DEVICE_FLAG_AXIS | DEVICE_FLAG_NEGATIVE); } else if(abs(JoyState.lRy) > DETECT_SENSITIVITY_JOYSTICK) { dwHow = FIELD_OFFSET(DIJOYSTATE, lRy); dwFlags |= (JoyState.lRy > 0) ? (DEVICE_FLAG_AXIS | DEVICE_FLAG_POSITIVE) : (DEVICE_FLAG_AXIS | DEVICE_FLAG_NEGATIVE); } else if(abs(JoyState.lRz) > DETECT_SENSITIVITY_JOYSTICK) { dwHow = FIELD_OFFSET(DIJOYSTATE, lRz); dwFlags |= (JoyState.lRz > 0) ? (DEVICE_FLAG_AXIS | DEVICE_FLAG_POSITIVE) : (DEVICE_FLAG_AXIS | DEVICE_FLAG_NEGATIVE); } else for(int b=0;b<2;b++) if(abs(JoyState.rglSlider[b]) > DETECT_SENSITIVITY_JOYSTICK) dwHow = FIELD_OFFSET(DIJOYSTATE, rglSlider[b]); else for(int b=0;b<4;b++) if(abs(JoyState.rgdwPOV[b]) > DETECT_SENSITIVITY_POV) dwHow = FIELD_OFFSET(DIJOYSTATE, rgdwPOV[b]); else for(int b=0;b<32;b++) if(JoyState.rgbButtons[b] > DETECT_SENSITIVITY_BUTTON) dwHow = FIELD_OFFSET(DIJOYSTATE, rgbButtons[b]); // ****************************************************************** // * Retrieve Object Info // ****************************************************************** if(dwHow != -1) { char *szDirection = (dwFlags & DEVICE_FLAG_AXIS) ? (dwFlags & DEVICE_FLAG_POSITIVE) ? "Positive " : "Negative " : ""; m_InputDevice[v].m_Device->GetDeviceInfo(&DeviceInstance); m_InputDevice[v].m_Device->GetObjectInfo(&ObjectInstance, dwHow, DIPH_BYOFFSET); Map(CurConfigObject, DeviceInstance.tszInstanceName, dwHow, dwFlags); printf("Cxbx: Detected %s %s on %s\n", szDirection, ObjectInstance.tszName, DeviceInstance.tszInstanceName, ObjectInstance.dwType); sprintf(szStatus, "Success: %s Mapped to '%s%s' on '%s'!", m_DeviceNameLookup[CurConfigObject], szDirection, ObjectInstance.tszName, DeviceInstance.tszInstanceName); return true; } } } return false; } // ****************************************************************** // * func: XBController::ConfigEnd // ****************************************************************** void XBController::ConfigEnd() { // ****************************************************************** // * Cleanup DirectInput // ****************************************************************** { for(int v=m_dwInputDeviceCount-1;v>=0;v--) { m_InputDevice[v].m_Device->Unacquire(); m_InputDevice[v].m_Device->Release(); m_InputDevice[v].m_Device = 0; } m_dwInputDeviceCount = 0; if(m_pDirectInput8 != 0) { m_pDirectInput8->Release(); m_pDirectInput8 = 0; } } return; } // ****************************************************************** // * func: XBController::Map // ****************************************************************** void XBController::Map(XBCtrlObject object, const char *szDeviceName, int dwInfo, int dwFlags) { // Initialize InputMapping instance m_ObjectConfig[object].dwDevice = Insert(szDeviceName); m_ObjectConfig[object].dwInfo = dwInfo; m_ObjectConfig[object].dwFlags = dwFlags; // Purse unused device slots for(int v=0;vCreateDevice(lpddi->guidInstance, &m_InputDevice[m_dwInputDeviceCount].m_Device, NULL); if(!FAILED(hRet)) { m_InputDevice[m_dwInputDeviceCount].m_Flags = DEVICE_FLAG_JOYSTICK; m_InputDevice[m_dwInputDeviceCount++].m_Device->SetDataFormat(&c_dfDIJoystick); } return DIENUM_CONTINUE; } // ****************************************************************** // * func: XBController::EnumObjectsCallback // ****************************************************************** BOOL XBController::EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi) { if(lpddoi->dwType & DIDFT_AXIS) { DIPROPRANGE diprg; diprg.diph.dwSize = sizeof(DIPROPRANGE); diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); diprg.diph.dwHow = DIPH_BYID; diprg.diph.dwObj = lpddoi->dwType; diprg.lMin = 0 - 32768; diprg.lMax = 0 + 32767; HRESULT hRet = m_InputDevice[m_dwCurObject].m_Device->SetProperty(DIPROP_RANGE, &diprg.diph); if(FAILED(hRet)) return DIENUM_STOP; } return DIENUM_CONTINUE; } // ****************************************************************** // * func: WrapEnumGameCtrlCallback // ****************************************************************** BOOL CALLBACK WrapEnumGameCtrlCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { XBController *context = (XBController*)pvRef; return context->EnumGameCtrlCallback(lpddi); } // ****************************************************************** // * func: WrapEnumObjectsCallback // ****************************************************************** BOOL CALLBACK WrapEnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) { XBController *context = (XBController*)pvRef; return context->EnumObjectsCallback(lpddoi); } // ****************************************************************** // * Input Device Name Lookup Table // ****************************************************************** const char *XBController::m_DeviceNameLookup[XBCTRL_OBJECT_COUNT] = { // ****************************************************************** // * Analog Axis // ****************************************************************** "LThumbPosX", "LThumbNegX", "LThumbPosY", "LThumbNegY", "RThumbPosX", "RThumbNegX", "RThumbPosY", "RThumbNegY", // ****************************************************************** // * Analog Buttons // ****************************************************************** "X", "Y", "A", "B", "White", "Black", "LTrigger", "RTrigger", // ****************************************************************** // * Digital Buttons // ****************************************************************** "DPadUp", "DPadDown", "DPadLeft", "DPadRight", "Back", "Start", "LThumb", "RThumb", };