Jump to content
Korean Random

Передача вибраций на геймпад(из кода офф. вибронакидки) в World of Tanks. Проблема с переводом xInput в Direct Input.


finn163

Recommended Posts

Доброго времени суток, друзья. Нужна ваща помощь.

 

Товарищи Kharlashkin, inj3ct0r и sirmax сделали мод позволяющий использовать вибрации с официальной вибронакидки, передавая их на Геймпад.

С этим вы можете ознакомится здесь

'Ссылка на офф форум раз'

и здесь

'Ссылка на офф форум два'

 

Проблем при использовании геймпадов с поддержкой XInput (стандарт данных для геймпадов XBOX 360) не наблюдается, но вот геймпад с использованием DirectInput никак не реагируют на вибрацию. Мне собственно нужно сделать так, что бы мы могли завести вибрацию на геймпадах без поддержки XInput (тобишь на обычных с поддержкой DirectInput)

 

Для подключения накидки используется следующий алгоритм.

'Алгоритм подключения накидки'

1. Необходимо установить Python версий 2.7.х (у меня стоит 2.7.6).
2. Необходимо установить Flask, я делал по этой инструкции. Качаем файл distribute_setup.py в папку "C:\temp" (например), запускаем консоль "Win+R" - cmd и выполняем команду "C:\Python27\python.exe C:\temp\distribute_setup.py" наблюдаем процесс загрузки нужных файлов в папку "C:\Python27\Scripts", далее в консоли запускаем команды по очереди и наблюдаем их выполнение:
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Flask
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Jinja2
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Werkzeug
C:\Python27\python.exe C:\Python27\Scripts\easy_install-2.7-script.py Virtualenv
3. Распаковать мод в нужную папку.

'Ссылка на мод'

 

 

После этого Танки говорят что видят вибронакидку, и передают команды о вибрациях на геймпад. Проблема в том что поскольку у DirectInput другой алгоритм, он эти сигналы совершенно не воспринимает. И даже в Эмуляторах x360 и x360 vibromod, геймпад не вибрирует, по той же причине.

 

В папке с модом который лежит у нас в директории модов world of tanks есть файлик на питоне, который по словам kharlashkin-а отправляют сигналы на геймпад о вибрации.

Декомпилировав имеем код

'Код'

# Embedded file name: .\gpXInput.py
import ctypes

class XINPUT_VIBRATION(ctypes.Structure):
_fields_ = [('wLeftMotorSpeed', ctypes.c_ushort), ('wRightMotorSpeed', ctypes.c_ushort)]


class gpXInputClass:

def __init__(self):
xInputDLLFileName = 'xinput1_3'
xinput = ctypes.WinDLL(xInputDLLFileName)
self.__XInputSetState = xinput.XInputSetState
self.__XInputSetState.argtypes = [ctypes.c_uint, ctypes.POINTER(XINPUT_VIBRATION)]
self.__XInputSetState.restype = ctypes.c_uint
self.__l = 0
self.__r = 0

def adjust_vibration(self, left_motor_delta, right_motor_delta, set = False, controller = 0):
if set:
self.__l = left_motor
self.__r = right_motor
else:
self.__l += left_motor_delta
self.__r += right_motor_delta
tempL = self.__l
tempR = self.__r
if self.__l > 255:
tempL = 255
elif self.__l < 0:
tempL = 0
if self.__r > 255:
tempR = 255
elif self.__r < 0:
tempR = 0
vibration = XINPUT_VIBRATION(int(tempL * 65535 / 255), int(tempR * 65535 / 255))
self.__XInputSetState(controller, ctypes.byref(vibration))

def stop_vibration(self, controller = 0):
vibration = XINPUT_VIBRATION(0, 0)
self.__XInputSetState(controller, ctypes.byref(vibration))


gpXInputObject = gpXInputClass()

 

Сам в програмировании на таком уровне не очень секу, так что очень нужна помощь. Как я понимаю достаточно переписать этот код так, что бы он отправлял сигналы воспринимаемые DirectInput-ом, тобишь все сигналы переделать.

Про DirectInput нашел на майкрософтовском сайте, но сам толком ничего не разобрал.

Вот ссыль

'Ссылка DirectInput Force Feedback'

 

Уж очень нужна помощь.

Просто нужно переделать из одного стандарта (XInput) в другой (DirectInput). Программисты помогите!

Edited by finn163
  • Upvote 1
Link to comment
Short link
Share on other sites

Я изучал данную тему, мое мнение не нужно переводить Xinput вибрации в Directinput, проще будет изменить модуль вывода вибраций из мода сразу для Directinput.

  • Upvote 1
Link to comment
Short link
Share on other sites

Итак, делюсь своими наработками и новыми вводными данными.

1. Гугление привело к тому что нужно наверное использовать SDL - наверное самый простой способ для меня, так как переделать код из C++ для python не смогу.

2. Нашел тестовый скрипт для проверки вибраций.

'testhaptic.py'

"""Simple example for haptic/force-feedback"""
import os
import sys
import ctypes
import sdl2


def run():
    sdl2.SDL_Init(sdl2.SDL_INIT_TIMER | sdl2.SDL_INIT_JOYSTICK | sdl2.SDL_INIT_HAPTIC)

    print "Trying to find haptics"
    if (sdl2.SDL_NumHaptics() == 0):
        print "No haptic devices found"
        sdl2.SDL_Quit()
        exit(0)

    for index in range(0,sdl2.SDL_NumHaptics()):
        print "Found", index, ":", sdl2.SDL_HapticName(index)

    if (len(sys.argv) == 2):
        index = int(sys.argv[1])
    else:
        index = 0

    haptic = sdl2.SDL_HapticOpen(index);
    if haptic == None:
        print "Unable to open device"
        sdl2.SDL_Quit()
        exit(0)
    else:
        print "Using device", index

    nefx = 0
    efx = [0] * 12
    id = [0] * 12
    supported = sdl2.SDL_HapticQuery(haptic)
    
    if (supported & sdl2.SDL_HAPTIC_SINE):
        print "   effect", nefx, "Sine Wave"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_SINE, periodic= \
            sdl2.SDL_HapticPeriodic(type=sdl2.SDL_HAPTIC_SINE, direction=sdl2.SDL_HapticDirection(type=sdl2.SDL_HAPTIC_POLAR, dir=(9000,0,0)), \
            period=1000, magnitude=0x4000, length=5000, attack_length=1000, fade_length=1000))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_TRIANGLE):
        print "   effect", nefx, "Triangle"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_TRIANGLE, periodic= \
            sdl2.SDL_HapticPeriodic(type=sdl2.SDL_HAPTIC_SINE, direction=sdl2.SDL_HapticDirection(type=sdl2.SDL_HAPTIC_CARTESIAN, dir=(1,0,0)), \
            period=1000, magnitude=0x4000, length=5000, attack_length=1000, fade_length=1000))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_SAWTOOTHUP):
        print "   effect", nefx, "Sawtooth Up"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_SAWTOOTHUP, periodic= \
            sdl2.SDL_HapticPeriodic(type=sdl2.SDL_HAPTIC_SAWTOOTHUP, direction=sdl2.SDL_HapticDirection(type=sdl2.SDL_HAPTIC_POLAR, dir=(9000,0,0)), \
            period=500, magnitude=0x5000, length=5000, attack_length=1000, fade_length=1000))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_SAWTOOTHDOWN):
        print "   effect", nefx, "Sawtooth Down"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_SAWTOOTHDOWN, periodic= \
            sdl2.SDL_HapticPeriodic(type=sdl2.SDL_HAPTIC_SAWTOOTHDOWN, direction=sdl2.SDL_HapticDirection(type=sdl2.SDL_HAPTIC_CARTESIAN, dir=(1,0,0)), \
            period=500, magnitude=0x5000, length=5000, attack_length=1000, fade_length=1000))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_RAMP):
        print "   effect", nefx, "Ramp"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_RAMP, ramp= \
            sdl2.SDL_HapticRamp(type=sdl2.SDL_HAPTIC_RAMP, direction=sdl2.SDL_HapticDirection(type=sdl2.SDL_HAPTIC_POLAR, dir=(9000,0,0)), \
            start=0x5000, end=0x0000, length=5000, attack_length=1000, fade_length=1000))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_CONSTANT):
        print "   effect", nefx, "Constant Force"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_CONSTANT, constant= \
            sdl2.SDL_HapticConstant(type=sdl2.SDL_HAPTIC_CONSTANT, direction=sdl2.SDL_HapticDirection(type=sdl2.SDL_HAPTIC_CARTESIAN, dir=(1,0,0)), \
            length=5000, level=0x4000, attack_length=1000, fade_length=1000))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_SPRING):
        print "   effect", nefx, "Spring"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_SPRING, condition= \
            sdl2.SDL_HapticCondition(type=sdl2.SDL_HAPTIC_SPRING, length=5000, right_sat=(0x7FFF,0x7FFF,0x7FFF), left_sat=(0x7FFF,0x7FFF,0x7FFF), \
            right_coeff=(0x2000,0x2000,0x2000), left_coeff=(0x2000,0x2000,0x2000), center=(0x1000,0x1000,0x1000)))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_DAMPER):
        print "   effect", nefx, "Damper"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_DAMPER, condition= \
            sdl2.SDL_HapticCondition(type=sdl2.SDL_HAPTIC_DAMPER, length=5000, right_sat=(0x7FFF,0x7FFF,0x7FFF), left_sat=(0x7FFF,0x7FFF,0x7FFF), \
            right_coeff=(0x2000,0x2000,0x2000), left_coeff=(0x2000,0x2000,0x2000), center=(0x1000,0x1000,0x1000)))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_INERTIA):
        print "   effect", nefx, "Interia"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_INERTIA, condition= \
            sdl2.SDL_HapticCondition(type=sdl2.SDL_HAPTIC_INERTIA, length=5000, right_sat=(0x7FFF,0x7FFF,0x7FFF), left_sat=(0x7FFF,0x7FFF,0x7FFF), \
            right_coeff=(0x2000,0x2000,0x2000), left_coeff=(0x2000,0x2000,0x2000), center=(0x1000,0x1000,0x1000)))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_FRICTION):
        print "   effect", nefx, "Friction"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_FRICTION, condition= \
            sdl2.SDL_HapticCondition(type=sdl2.SDL_HAPTIC_FRICTION, length=5000, right_sat=(0x7FFF,0x7FFF,0x7FFF), left_sat=(0x7FFF,0x7FFF,0x7FFF), \
            right_coeff=(0x2000,0x2000,0x2000), left_coeff=(0x2000,0x2000,0x2000), center=(0x1000,0x1000,0x1000)))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

    if (supported & sdl2.SDL_HAPTIC_LEFTRIGHT):
        # leftright argument not defined for HapticEffect
        print "   effect", nefx, "Left/Right"
        print "      Bug 'leftright' not defined"
        efx[nefx] = sdl2.SDL_HapticEffect(type=sdl2.SDL_HAPTIC_LEFTRIGHT, leftright= \
            sdl2.SDL_HapticLeftRight(type=sdl2.SDL_HAPTIC_LEFTRIGHT, length=5000, large_magnitude=0x3000, small_magnitude=0xFFFF))
        id[nefx] = sdl2.SDL_HapticNewEffect(haptic, efx[nefx]);
        nefx += 1

        print "Now playing effects for 5 seconds each with 1 second delay between"
    for i in range(0, nefx):
        print "   Playing effect", i
        sdl2.SDL_HapticRunEffect(haptic, id[i], 1);
        sdl2.SDL_Delay(6000);        # Effects only have length 5000

    sdl2.SDL_Quit()
    return 0

if __name__ == "__main__":
    sys.exit(run()) 

3. Сам PySDL2 взял отсюда - https://bitbucket.org/marcusva/py-sdl2

4. Установил по этой инструкции http://pysdl2.readthedocs.org/en/latest/install.html#installation.

5. Вываливается ошибка:

post-19155-0-39559000-1420359358_thumb.png

Не могу понять куда подсовывать SDL.dll.

 

Может подскажет кто?

 

Добавил путь к SDL.dll  в переменную среду. Теперь ошибка следующая:

Traceback (most recent call last):
  File "C:\temp\testhaptic.py", line 5, in <module>
    import sdl2
  File "D:\Python27\lib\site-packages\sdl2\__init__.py", line 2, in <module>
    from .dll import get_dll_file, _bind
  File "D:\Python27\lib\site-packages\sdl2\dll.py", line 113, in <module>
    raise ImportError(exc)
ImportError: found ['D:\\SDL2\\SDL2.dll'], but it's not usable for the library SDL2

"УРА! Заработало!" ©кот Матроскин:

post-19155-0-62522000-1420363818_thumb.png

Теперь подробнее автору топика про установку и проверку.

1. Установить Python (у меня установлено 2.7.8), хотя мне кажется уже установлено.

2. Качаем отсюда py-sdl2 версию PySDL2-0.9.3.zip.

3. Распаковываем тупо на диск "С:\"

4. Из консоли Windows ("Win+R" - cmd) переходим в распакованную папку - "cd c:\pysdl2-0.9.3".

5. Выполняем установку - "c:\python27\python.exe setup.py install"

6. Качаем c libsdl.org архив для 32-х битной Windows - SDL2-2.0.3-win32-x86.zip.

7. Распаковываем файл SDL.dll в папку "C:\SDL2".

8. Добавляем папку "C:\SDL2" в переменные среды (Компьютер - Свойства - Дополнительные параметры системы - Переменные среды - Создать)

post-19155-0-96030500-1420366971_thumb.png

9. Качаем тестовый скрипт и кладем его куда угодно (у меня "C:\temp").

10. Открываем его в IDLE.

11. Клавишей F5 запускаем проверку.

 

Если завибрирует - хорошо, если нет - то ХЗ.

 

Edited by kharlashkin
Link to comment
Short link
Share on other sites

Итак, оказывается Xpadder конфликтует с x360 эмулятором и тот отказывается вибрировать. Без Хпадера х360 работает на ура. Как и х360 Vibromod.

 

Несмотря на то что удалось запустить вибрацию в режиме XInput в программе х360, в танках работать вибрация отказывается. При любых заменах XInputa в дириктории питона и даже винде, всё одно - не работает в танках.

 

Тобишь просто так на эмуляторе идет вибрации, а при попытке выхватить её из Питона не работает. Тем неменее на обычных геймпадах с XInput-ом всё ок, выхватывает из питона как надо.
 

Диагноз - х360 не перехватывает сигнал и не преобразует его в DirectInput, а на геймпад идут обычные сигналы в XInput-е, а он их естественно не воспринимает.

 

Так что по прежнему нужна помощь программистов:)

Edited by finn163
Link to comment
Short link
Share on other sites

Конкретно у автора темы тестовая вибрация SDL не завелась - хотя эффекты и пытались проиграться:

post-19155-0-67083300-1420379672_thumb.jpg

Скорее всего, мне кажется что это бока программистов из SpeedLink, а может и разработчиков SDL (на оф.форуме есть жалобы на работу вибраций Directinput).

 

Вспомнился мой пост о мытарствах подключения геампада под python, вспомнился проект PsychoPy и нашелся нужный код, который вроде без промежуточных DLL умеет обращаться с геймпадами.

http://pydoc.net/Python/PsychoPy/1.81.03/psychopy.hardware.joystick.pyglet_input.dinput/

http://pydoc.net/Python/PsychoPy/1.81.03/psychopy.hardware.joystick.pyglet_input.directinput/

 

Если я правильно понимаю, нужно выбросить все лишнее и можно использовать это для вызова напрямую вибраций?

Link to comment
Short link
Share on other sites

На форуме поддержки x360ce, накопал интересную информацию касательно эмуляции геймпада Xbox 360. Документ использования перехватов прилагаю.

 

Как оказалось, что в стандартный графический интерфейс (как это обычно и бывает) не внесены все возможности использования, полностью все возможности доступны в файле настройки, а именно x360ce.ini.

[InputHook]
HookLL=0
HookCOM=0
HookSA=0
HookWT=0
HookDI=0
HookPIDVID=0
HookName=0

Так как мы вызываем вибрации непосредственно из xinput1_3.dll  - мне кажется что именно HookLL тот параметр, в который нужно поставить 1.

 

P.S. Ну вообще рекомендую более глубоко покопаться в документации. Может найдутся ещё скрытые возможности. Если ничего не поможет - попробуйте попросить помощи у них на форуме.

P.P.S. Вот кстати и список игр, для которых нужны отличные от стандартных настройки, для некоторых нужны несколько параметров hook-ов.


Проверил какой именно exe-шник обращается к xinput1_3.dll при работе мода, по этой инструкции:

post-19155-0-92335000-1420451376_thumb.png

Нужно автору темы пробовать играться с параметрами:

HookLL=(0/1)
HookCOM=(0/1)
HookSA=(0/1)
HookWT=(0/1)
HOOKDI=(0/1)
HOOKPIDVID=(0/1)
HookName=(0/1)

Сгенерированную DLL положить в папку с системным python "C:\Python27".


Вспомнил про тестовый скрипт. Чтобы не запускать танки постоянно, просто запустить в редакторе ff.py.

 

Тестовый скрипт запускает левый мотор на максимум и правый в пол силы в течении 5 секунд.

x360ce_intro_to_input_hooking2.pdf

ff.7z

Edited by kharlashkin
Link to comment
Short link
Share on other sites

Ни у кого нет геймпадов или никто не хочет помочь - проверить?

 

Интересно что скрипт проверочный скачали 3 раза - документ с хуками ни разу...

 

P.S. Вчера вечером проверил на своих геймпадах - SDL вывалил ошибку, типа не назначены коэфициенты для левого/правого моторов (глубоко не копал), проверочный скрипт работает как положено.

Link to comment
Short link
Share on other sites

Проверил - python действительно обращается к xinput1_3.dll x360ce, при размещении файлов в папке "C:\Python27\". Но так как DirectInput геймпада нет у меня - дальше проверки дело не идет.

post-19155-0-41758900-1420618614_thumb.png

Link to comment
Short link
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...