GamePad — Xinput и Dinput
И вопрос, парочка:
1. Есть еще какие-то отличия Xinput от Dinput?
2. И не посоветуйте еще какие-нибудь gamepad’ы c возможностью этого самого переключения?
Необязательно от logitech , но можно и его, кроме f310 и 510 — эти вроде аналогичные f710-ому
Смотрел на такой, можно сказать из-за фирмы даже, в надежде на качество
http://www.dns-shop.ru/product/391e6d6957883330/gejmpad-steelseries-stratus-x.
но как-то вот это отпугнуло
Интерфейс Bluetooth
Элементы питания 2xAA
не сколько BT, хотя, сколько он, так еще и батарейки нужны, которые надо менять и от провода если они закончатся не поиграешь
Начало работы с XInput в приложениях для Windows
XInput позволяет приложениям Windows обрабатывать взаимодействие контроллера (включая эффекты свораивания контроллера и входные и выходные данные).
В этом разделе представлен краткий обзор возможностей XInput и его настройка в приложении. Это включает следующее:
- Общие сведения о XInput
- Макет контроллера
- Несколько контроллеров
- Получение состояния контроллера
- Мертвая зона
- Настройка эффектов вибрации
- Получение идентификаторов аудиоустройств
- Получение идентификаторов GUID DirectSound (только устаревший пакет SDK DirectX)
Общие сведения о XInput
Приложения могут использовать API XInput для взаимодействия с игровыми контроллерами при подключении к компьютеру с Windows (за раз можно подключить до четырех уникальных контроллеров).
С помощью этого API можно запросить любой совместимый подключенный контроллер, и можно задать эффекты вибрации. Контроллеры, подключенные к гарнитуре, также могут запрашиваться для звуковых и выходных устройств, которые можно использовать с гарнитурой для обработки голоса.
Макет контроллера
Совместимые контроллеры имеют два аналоговых указателя, каждый из которых имеет цифровую кнопку, два аналоговых триггера, цифровую панель направления с четырьмя направлениями и восемь цифровых кнопок. Состояния каждого из этих входных данных возвращаются в структуре XINPUT_GAMEPAD при вызове функции XInputGetState.
Контроллер также имеет два двигателя вибрации, чтобы обеспечить эффекты обратной связи пользователю. Скорость этих двигателей указывается в XINPUT_VIBRATION структуре, передаваемой функции XInputSetState, чтобы задать эффекты вибрации.
При необходимости гарнитура может быть подключена к контроллеру. Гарнитура имеет микрофон для голосового ввода и наушники для вывода звука. Вы можете вызвать функцию XInputGetAudioDeviceIds или устаревшую функцию XInputGetDoundAudioDeviceGuids, чтобы получить идентификаторы устройства, соответствующие устройствам для микрофона и наушника. Затем вы можете использовать API Core Audio для получения голосовых входных данных и отправки выходных данных звука.
Использование XInput
Использование XInput так же просто, как вызов функций XInput по мере необходимости. С помощью функций XInput можно получить состояние контроллера, получить идентификаторы звука гарнитуры и задать эффекты рухнуть контроллера.
Несколько контроллеров
API XInput поддерживает до четырех контроллеров, подключенных в любое время. Для всех функций XInput требуется параметр dwUserIndex , передаваемый для идентификации заданного или запрашиваемого контроллера. Этот идентификатор будет находиться в диапазоне от 0 до 3 и автоматически задается XInput. Номер соответствует порту, в который подключен контроллер, и не изменяется.
Каждый контроллер отображает идентификатор, который он использует путем освещения квадранта на «кольце света» в центре контроллера. Значение dwUserIndex, равное 0, соответствует левому верхнему квадранте; нумерация выполняется по кольцу по часовой стрелке.
Приложения должны поддерживать несколько контроллеров.
Получение состояния контроллера
На протяжении всего времени приложения состояние получения от контроллера, вероятно, будет выполняться чаще всего. От кадра к кадру в игровом приложении необходимо получить состояние и обновить сведения о игре, чтобы отразить изменения контроллера.
Чтобы получить состояние, используйте функцию XInputGetState :
DWORD dwResult; for (DWORD i=0; i < XUSER_MAX_COUNT; i++ ) < XINPUT_STATE state; ZeroMemory( &state, sizeof(XINPUT_STATE) ); // Simply get the state of the controller from XInput. dwResult = XInputGetState( i, &state ); if( dwResult == ERROR_SUCCESS ) < // Controller is connected >else < // Controller is not connected >>Обратите внимание, что возвращаемое значение XInputGetState можно использовать для определения подключения контроллера. Приложения должны определять структуру для хранения сведений о внутреннем контроллере; Эти сведения следует сравнить с результатами XInputGetState , чтобы определить, какие изменения, такие как нажатия кнопки или аналоговые разностные контроллеры, были сделаны в этом кадре. В приведенном выше примере g_Controllers представляет такую структуру.
После получения состояния в структуре XINPUT_STATE вы можете проверка его для изменений и получить конкретные сведения о состоянии контроллера.
Элемент dwPacketNumber структуры XINPUT_STATE можно использовать для проверка, если состояние контроллера изменилось с момента последнего вызова XInputGetState. Если dwPacketNumber не изменяется между двумя последовательными вызовами XInputGetState, то в состоянии не было изменений. Если оно отличается, приложение должно проверка член геймпаднойструктуры XINPUT_STATE, чтобы получить более подробные сведения о состоянии.
По соображениям производительности не вызывайте XInputGetState для «пустого» слота пользователя каждый кадр. Рекомендуется разместить проверка для новых контроллеров каждые несколько секунд.
Мертвая зона
Чтобы пользователи имели согласованный игровой процесс, ваша игра должна правильно реализовать мертвую зону. Мёртвая зона — это «перемещение» значений, сообщаемых контроллером, даже если аналоговые отпечатки не тронуты и центрированы. Существует также мертвая зона для 2 аналоговых триггеров.
Игры, использующие XInput, которые не фильтруют мертвую зону вообще будет испытывать плохой игровой процесс. Обратите внимание, что некоторые контроллеры более чувствительны, чем другие, поэтому мертвая зона может отличаться от единицы к единице. Рекомендуется протестировать игры с несколькими контроллерами Xbox в разных системах.
Приложения должны использовать «мертвые зоны» для аналоговых входных данных (триггеров, палок), чтобы указать, когда движение было сделано достаточно на палке или триггере, чтобы считаться допустимым.
Приложение должно проверка для мертвых зон и реагировать на них, как в следующем примере:
XINPUT_STATE state = g_Controllers[i].state; float LX = state.Gamepad.sThumbLX; float LY = state.Gamepad.sThumbLY; //determine how far the controller is pushed float magnitude = sqrt(LX*LX + LY*LY); //determine the direction the controller is pushed float normalizedLX = LX / magnitude; float normalizedLY = LY / magnitude; float normalizedMagnitude = 0; //check if the controller is outside a circular dead zone if (magnitude > INPUT_DEADZONE) < //clip the magnitude at its expected maximum value if (magnitude >32767) magnitude = 32767; //adjust magnitude relative to the end of the dead zone magnitude -= INPUT_DEADZONE; //optionally normalize the magnitude with respect to its expected range //giving a magnitude value of 0.0 to 1.0 normalizedMagnitude = magnitude / (32767 - INPUT_DEADZONE); > else //if the controller is in the deadzone zero out the magnitude < magnitude = 0.0; normalizedMagnitude = 0.0; >//repeat for right thumb stickВ этом примере вычисляется вектор направления контроллера и насколько далеко вдоль вектора контроллер был отправлен. Это позволяет применять циклическую мертвую зону, просто проверка, если величина контроллера больше, чем значение мертвой зоны. Кроме того, код нормализует величину контроллера, которая затем может быть умножена на конкретный фактор игры, чтобы преобразовать положение контроллера в единицы, относящиеся к игре.
Обратите внимание, что вы можете определить собственные мертвые зоны для палок и триггеров (в любом месте от 0 до 65534) или использовать предоставленные взаимодоставки, определенные как XINPUT_GAMEPAD_LEFT_THUМБ_DEADZONE, XINPUT_GAMEPAD_RIGHT_THUМБ_DEADZONE и XINPUT_GAMEPAD_TRIGGER_THRESHOLD в XInput.h:
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849 #define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689 #define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30После принудительного применения мертвая зона может оказаться полезной для масштабирования результирующего диапазона [0.0.1.0], плавающей запятой (как показано в примере выше), и при необходимости применить нелинейное преобразование.
Например, при управлении играми, может быть полезно кубировать результат, чтобы обеспечить лучшее чувство вождения автомобилей с помощью игровой панели, так как кубинг результат дает вам больше точности в более низких диапазонах, что желательно, так как игроки обычно применяют мягкую силу, чтобы получить тонкое движение или применить жесткие силы весь путь в одном направлении, чтобы получить rd ответ.
Настройка эффектов вибрации
Помимо получения состояния контроллера, вы также можете отправлять данные вибрации контроллеру, чтобы изменить обратную связь, предоставленную пользователю контроллера. Контроллер содержит два хворотных двигателя, которые можно самостоятельно контролировать путем передачи значений функции XInputSetState .
Скорость каждого двигателя можно указать с помощью значения WORD в структуре XINPUT_VIBRATION, передаваемой функции XInputSetState следующим образом:
XINPUT_VIBRATION vibration; ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) ); vibration.wLeftMotorSpeed = 32000; // use any value between 0-65535 here vibration.wRightMotorSpeed = 16000; // use any value between 0-65535 here XInputSetState( i, &vibration );Обратите внимание, что правый двигатель является высокочастотным двигателем, левый двигатель является низкочастотным двигателем. Они не всегда должны быть заданы одинаково, так как они обеспечивают различные эффекты.
Получение идентификаторов аудиоустройств
Гарнитура для контроллера имеет следующие функции:
- Запись звука с помощью микрофона
- Воспроизведение звука обратно с помощью наушника
Используйте этот код для получения идентификаторов устройства для гарнитуры:
WCHAR renderId[ 256 ] = ; WCHAR captureId[ 256 ] = ; UINT rcount = 256; UINT ccount = 256; XInputGetAudioDeviceIds( i, renderId, &rcount, captureId, &ccount );После получения идентификаторов устройства можно создать соответствующие интерфейсы. Например, если вы используете XAudio 2.8, используйте этот код для создания эталонного голоса для этого устройства:
IXAudio2* pXAudio2 = NULL; HRESULT hr; if ( FAILED(hr = XAudio2Create( &pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR ) ) ) return hr; IXAudio2MasteringVoice* pMasterVoice = NULL; if ( FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, renderId, NULL, AudioCategory_Communications ) ) ) return hr;Сведения об использовании идентификатора устройства captureId см. в разделе «Запись потока».
Получение идентификаторов GUID DirectSound (только устаревший пакет SDK DirectX)
Гарнитура, которая может быть подключена к контроллеру, имеет две функции: она может записывать звук с помощью микрофона, и он может воспроизводить звук с помощью наушники. В API XInput эти функции выполняются с помощью DirectSound с помощью интерфейсов IDirectSound8 и IDirectSoundCapture8.
Чтобы связать микрофон гарнитуры и наушники с соответствующими интерфейсами DirectSound, необходимо получить DirectSoundGUID для захвата и отрисовки устройств, вызвав XInputGetDSoundAudioDeviceGuids.
Использование устаревшего DirectSound не рекомендуется и недоступно в приложениях Магазина Windows. Сведения в этом разделе относятся только к версии XInput (XInput 1.3). В Windows 8 версии XInput (XInput 1.4) используются исключительно идентификаторы устройств API сеансов windows (WASAPI), полученные с помощью XInputGetAudioDeviceIds .
XInputGetDSoundAudioDeviceGuids( i, &dsRenderGuid, &dsCaptureGuid );После получения идентификаторов GUID можно создать соответствующие интерфейсы, вызвав DirectSoundCreate8 и DirectSoundCaptureCreate8, как показано ниже:
// Create IDirectSound8 using the controller's render device if( FAILED( hr = DirectSoundCreate8( &dsRenderGuid, &pDS, NULL ) ) ) return hr; // Set coop level to DSSCL_PRIORITY if( FAILED( hr = pDS->SetCooperativeLevel( hWnd, DSSCL_NORMAL ) ) ) return hr; // Create IDirectSoundCapture using the controller's capture device if( FAILED( hr = DirectSoundCaptureCreate8( &dsCaptureGuid, &pDSCapture, NULL ) ) ) return hr;Сравнение функций XInput и DirectInput
В этом документе сравниваются реализации ввода контроллера XInput и DirectInput , а также как поддерживать устройства XInput и устаревшие устройства DirectInput.
Приложения Магазина Windows не поддерживают DirectInput.
Обзор
XInput позволяет приложениям получать входные данные от контроллеров XUSB. API доступны через пакет SDK DirectX, а драйвер доступен через Обновл. Windows.
Существует несколько преимуществ использования XInput по сравнению с DirectInput:
- XInput проще использовать и требует меньше установки, чем DirectInput
- Программирование Xbox и Windows будет использовать одни и те же наборы основных API, что позволяет программированию переводить кроссплатформенное гораздо проще
- Будет установлена большая база контроллеров
- Устройство XInput будет иметь функции вибрации только при использовании API XInput
Использование контроллеров XUSB с DirectInput
Контроллеры XUSB правильно перечисляются в DirectInput и могут использоваться с DirectInputAPIs. Однако некоторые функции, предоставляемые XInput, отсутствуют в реализации DirectInput:
- Кнопки триггера слева и справа будут выступать как одна кнопка, а не независимо
- Эффекты вибрации не будут доступны
- Запрос устройств гарнитуры не будет доступен
Сочетание левых и правых триггеров в DirectInput выполняется по проектированию. Игры всегда предполагают, что оси устройств DirectInput центрируются, если взаимодействие пользователя с устройством отсутствует. Однако более новые контроллеры были разработаны для регистрации минимального значения, а не центра, когда триггеры не хранятся. Поэтому старые игры предполагают взаимодействие с пользователем.
Решением было объединить триггеры, установив один триггер в положительном направлении и другой в отрицательном направлении, поэтому взаимодействие с пользователем не указывает на DirectInput элемента управления в центре.
Чтобы проверить значения триггера отдельно, необходимо использовать XInput.
XInput и DirectInput параллельно
Поддерживая только XInput, ваша игра не будет работать с устаревшими устройствами DirectInput . XInput не распознает эти устройства.
Если вы хотите, чтобы игра поддерживала устаревшие устройства DirectInput , вы можете использовать DirectInput и XInput параллельно. При перечислении устройств DirectInput все устройства DirectInput будут правильно перечисляться. Все устройства XInput будут отображаться как устройства XInput и DirectInput, но они не должны обрабатываться через DirectInput. Необходимо определить, какие из устройств DirectInput являются устаревшими и которые являются устройствами XInput, а также удалять их из перечисления устройств DirectInput.
Для этого вставьте этот код в обратный вызов перечисления DirectInput:
#include #include #ifndef SAFE_RELEASE #define SAFE_RELEASE(p) < if (p) < (p)->Release(); (p) = nullptr; > > #endif //----------------------------------------------------------------------------- // Enum each PNP device using WMI and check each device ID to see if it contains // "IG_" (ex. "VID_0000&PID_0000&IG_00"). If it does, then it's an XInput device // Unfortunately this information cannot be found by just using DirectInput //----------------------------------------------------------------------------- BOOL IsXInputDevice( const GUID* pGuidProductFromDirectInput ) < IWbemLocator* pIWbemLocator = nullptr; IEnumWbemClassObject* pEnumDevices = nullptr; IWbemClassObject* pDevices[20] = <>; IWbemServices* pIWbemServices = nullptr; BSTR bstrNamespace = nullptr; BSTR bstrDeviceID = nullptr; BSTR bstrClassName = nullptr; bool bIsXinputDevice = false; // CoInit if needed HRESULT hr = CoInitialize(nullptr); bool bCleanupCOM = SUCCEEDED(hr); // So we can call VariantClear() later, even if we never had a successful IWbemClassObject::Get(). VARIANT var = <>; VariantInit(&var); // Create WMI hr = CoCreateInstance(__uuidof(WbemLocator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator); if (FAILED(hr) || pIWbemLocator == nullptr) goto LCleanup; bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == nullptr) goto LCleanup; bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == nullptr) goto LCleanup; bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == nullptr) goto LCleanup; // Connect to WMI hr = pIWbemLocator->ConnectServer(bstrNamespace, nullptr, nullptr, 0L, 0L, nullptr, nullptr, &pIWbemServices); if (FAILED(hr) || pIWbemServices == nullptr) goto LCleanup; // Switch security level to IMPERSONATE. hr = CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE); if ( FAILED(hr) ) goto LCleanup; hr = pIWbemServices->CreateInstanceEnum(bstrClassName, 0, nullptr, &pEnumDevices); if (FAILED(hr) || pEnumDevices == nullptr) goto LCleanup; // Loop over all devices for (;;) < ULONG uReturned = 0; hr = pEnumDevices->Next(10000, _countof(pDevices), pDevices, &uReturned); if (FAILED(hr)) goto LCleanup; if (uReturned == 0) break; for (size_t iDevice = 0; iDevice < uReturned; ++iDevice) < // For each device, get its device ID hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, nullptr, nullptr); if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != nullptr) < // Check if the device ID contains "IG_". If it does, then it's an XInput device // This information cannot be found from DirectInput if (wcsstr(var.bstrVal, L"IG_")) < // If it does, then get the VID/PID from var.bstrVal DWORD dwPid = 0, dwVid = 0; WCHAR* strVid = wcsstr(var.bstrVal, L"VID_"); if (strVid && swscanf_s(strVid, L"VID_%4X", &dwVid) != 1) dwVid = 0; WCHAR* strPid = wcsstr(var.bstrVal, L"PID_"); if (strPid && swscanf_s(strPid, L"PID_%4X", &dwPid) != 1) dwPid = 0; // Compare the VID/PID to the DInput device DWORD dwVidPid = MAKELONG(dwVid, dwPid); if (dwVidPid == pGuidProductFromDirectInput->Data1) < bIsXinputDevice = true; goto LCleanup; >> > VariantClear(&var); SAFE_RELEASE(pDevices[iDevice]); > > LCleanup: VariantClear(&var); if(bstrNamespace) SysFreeString(bstrNamespace); if(bstrDeviceID) SysFreeString(bstrDeviceID); if(bstrClassName) SysFreeString(bstrClassName); for (size_t iDevice = 0; iDevice < _countof(pDevices); ++iDevice) SAFE_RELEASE(pDevices[iDevice]); SAFE_RELEASE(pEnumDevices); SAFE_RELEASE(pIWbemLocator); SAFE_RELEASE(pIWbemServices); if(bCleanupCOM) CoUninitialize(); return bIsXinputDevice; >//----------------------------------------------------------------------------- // Name: EnumJoysticksCallback() // Desc: Called once for each enumerated joystick. If we find one, create a // device interface on it so we can play with it. //----------------------------------------------------------------------------- BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) < if( IsXInputDevice( &pdidInstance->guidProduct ) ) return DIENUM_CONTINUE; // Device is verified not XInput, so add it to the list of DInput devices return DIENUM_CONTINUE; >Немного улучшенная версия этого кода находится в устаревшем примере DirectInput Джойстик .
Эмуляция XBox-контроллера для геймпадов без аппаратной поддержки XInput.
В текущих реалия ПК-гейминга, современные игры поддерживают только XInput-совместимые геймпады, и только некоторые игры поддерживают DirectInput-устройства, и то, в основном применительно только к одному контроллеру — DUALSHOCK 4. Также стандарт DirectInput используется в различных гоночных и авиа-симуляторах, для работы игровых рулей и штурвалов.
Что такое XInput? XInput — это API, который позволяет приложениям получать данные от контроллера Xbox (или любого другого контроллера с аппаратной поддержкой XInput). Подробнее можно почитать тут.
реклама
А что же делать юзеру, если у него в арсенале оказался геймпад без аппаратной поддержки XInput, DirectInput-совместимый? Выкидывать геймпад? Продавать и покупать XInput-совместимый? Нет, это совершенно необязательно, потому что существуют различные варианты эмуляции XInput для DirectInput Only геймпада. Вот эти варианты мы сегодня и рассмотрим.
Сразу оговорюсь, эмуляторов DS4Windows и InputMapper, предназначенных для DUALSHOCK 4, в этой статье не будет. Для DUALSHOCK 4 существует отдельная статья в блоге, DUALSHOCK 4 в реалиях ПК, где эта тема раскрыта достаточно широко.
реклама
Вариант номер один — эмулятор x360ce.
Изначально эмулятор появился под названием «XBOX360 Controller Emulator v3.0 by Racer_S». Был он, мягко говоря, сыроват, пока его дальнейшим развитием не занялся пользователь с ником virus, обитающий тогда на сайте www.tocaedit.com. В дальнейшем всё это дело переросло в проект x360ce и существует по сей день.
Что представляет из себя x360ce эмулятор? Это кастомные библиотеки:
реклама
плюс файл с настройками:
x360ce.ini конфигурируете вы самостоятельно, конкретно под свой геймпад, с помощью утилиты из комплекта. После чего x360ce.ini и dll-файлы (как правило достаточно одного dll-файла — xinput1_3.dll) подбрасываются в папку с целевой игрой:

реклама




Настроек много и они не универсальные. Эмуляция может работать, а может и не работать, зависит от игры и подобранных настроек. Для 64-битных приложений, нужно использовать 64-битную версию библиотек. Если для вашего DirectInput-геймпада в системе не установлен драйвер с поддержкой вибрации, вибрации не будет и через эмулятор. x360ce не работает с UWP-приложениями.
x360ce-эмулятор был отличным решением несколько лет назад, но сейчас есть варианты поинтереснее. Впрочем, иногда он спасает.
Скачать x360ce можно тут.
Вариант номер два — XOutput эмулятор.
В XOutput принцип работы уже более продвинутый. При установке этого эмулятора, в систему ставится virtual bus driver (SCP драйвер-враппер, который также используют утилиты DS4Windows и InputMapper, для эмуляции XInput на геймпадах DUALSHOCK 4):

Но в отличие от заточенных под один геймпад DS4Windows и InputMapper, этот эмулятор всеяден и готов работать с любыми DirectInput геймпадами:


После настройки и активации эмуляции в системе (помимо нашего DirectInput геймпада) должен появиться XBox 360 геймпад:

Чтобы скрыть DirectInput сущность нашего геймпада от системы и игр, следует воспользоваться режимом «Exclusivity»:

должно стать так:

. по идее должно стать. Эмулятор достаточно капризный, в том, что касается эксклюзивного режима. Особенно на последних версиях Windows 10. Т.е. может и не работать.
Вибрации через эмулятор, даже если она поддерживается вашим геймпадом, и в систему установлен родной forcefeedback драйвер для DirectInput устройства, не будет:

У этого эмулятора есть неоспоримые преимущества перед x360ce: он работает в UWP-приложениях, он не требует никаких сторонних DLL-библиотек в папке с игрой, он легко включается и выключается, его можно добавить в автозагрузку, он работает с 32-битными и 64-битными приложениями.
Скачать эмулятор можно тут.
Также существует новая ветка разработки XOutput. Тут для полноценной работы потребуется другой пакет драйверов (вместо SCP) — ViGEm Bus:



Суть та же, но тут работа над софтом и драйвером идёт активнее.
Вот вам необходимые ссылки по новой версии XOutput:
- ViGEm Bus Driver Installation
- ViGEm Bus Driver Installation – caveman edition
- Virtual Gamepad Emulation Framework Documentation
И наконец вариант номер три — эмуляция XInput через Steam.
Steam поддерживает большое количество геймпадов «из коробки», т.е. не требуется дополнительных телодвижений для того, чтобы Steam распознал ваш геймпад, а точнее правильно определил раскладку кнопок и прочее.
Но нет ничего страшного, если ваш DirectInput-геймпад незнаком стиму.
Для того, чтобы для вашего DirectInput-друга, в играх из библиотеки Steam (или добавленных туда вручную), заработала эмуляция XInput (и прочие плюшки), нужно проделать следующие шаги.
Подключить геймпад к ПК, запустить Steam и перейти в режим Big Picture:

Перейти в пункт меню с настройками контроллера:

поставить галочку на «пользовательские настройки обычного геймпада»:

выбрать внизу, в обнаруженных контроллерах, ваш геймпад и настроить его в соответствии с подсказками на экране:

нажать «сохранить» и дать имя вашему геймпаду:

Всё. Теперь ваш геймпад поддерживается в Steam, и для него доступны все настройки для любой игры из библиотеки:


В играх (из библиотеки Steam) ваш геймпад будет определяться, как XBox 360 контроллер. Чтобы произвести дополнительные настройки по конкретной игре, нужно вызвать в процессе игры оверлейный экран Steam (кнопкой GUIDE) или комбинацией клавиш и произвести все необходимые манипуляции.