summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2026-10-20 16:20:00 +0800
committerErik Kundiman <erik@megapahit.org>2026-10-20 16:20:00 +0800
commit61e65e2c95779d29496e5859a6edac82fc3b1ddb (patch)
treee0d70b7af955610b2a414b914c50d15f7af21015 /indra/newview
parentbbe494697ab37919f10009af516c711a685ac98e (diff)
parent923f645a923e7f061f7ff2790d8510aa4b5ced36 (diff)
Merge tag 'Second_Life_Release#923f645a-26.5' into 26.5
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt7
-rw-r--r--indra/newview/app_settings/gamecontrollerdb.txt2209
-rw-r--r--indra/newview/app_settings/key_bindings.xml83
-rw-r--r--indra/newview/app_settings/settings.xml48
-rw-r--r--indra/newview/llagent.cpp513
-rw-r--r--indra/newview/llagent.h80
-rw-r--r--indra/newview/llagentcamera.cpp551
-rw-r--r--indra/newview/llagentcamera.h110
-rw-r--r--indra/newview/llappviewer.cpp165
-rw-r--r--indra/newview/llappviewerlinux.cpp3
-rw-r--r--indra/newview/llfloaterjoystick.cpp30
-rwxr-xr-x[-rw-r--r--]indra/newview/llfloaterpreference.cpp346
-rw-r--r--indra/newview/llfloaterpreference.h67
-rw-r--r--indra/newview/llflycam.cpp325
-rw-r--r--indra/newview/llflycam.h139
-rw-r--r--indra/newview/llkeyconflict.cpp62
-rw-r--r--indra/newview/llkeyconflict.h13
-rwxr-xr-xindra/newview/llpanelpreferencegamecontrol.cpp2200
-rw-r--r--indra/newview/llpanelpreferencegamecontrol.h277
-rw-r--r--indra/newview/llscriptruntimeperms.h5
-rw-r--r--indra/newview/lltool.cpp2
-rw-r--r--indra/newview/lltoolfocus.cpp42
-rw-r--r--indra/newview/lltoolfocus.h10
-rw-r--r--indra/newview/llviewerinput.cpp788
-rw-r--r--indra/newview/llviewerinput.h35
-rw-r--r--indra/newview/llviewerjoystick.cpp316
-rw-r--r--indra/newview/llviewerjoystick.h43
-rw-r--r--indra/newview/llviewermenu.cpp97
-rw-r--r--indra/newview/llviewermenu.h3
-rw-r--r--indra/newview/llviewermessage.cpp15
-rw-r--r--indra/newview/llviewerregion.cpp7
-rw-r--r--indra/newview/llviewerregion.h3
-rw-r--r--indra/newview/llviewerstats.cpp13
-rw-r--r--indra/newview/llviewerwindow.cpp74
-rw-r--r--indra/newview/llviewerwindow.h1
-rw-r--r--indra/newview/llvoavatar.cpp2
-rw-r--r--indra/newview/llvoavatarself.cpp6
-rw-r--r--indra/newview/llvoicewebrtc.cpp6
-rw-r--r--indra/newview/pipeline.cpp2
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Dpad.pngbin0 -> 765 bytes
-rw-r--r--indra/newview/skins/default/xui/en/control_table_contents_flycam.xml125
-rw-r--r--indra/newview/skins/default/xui/en/control_table_contents_game_control.xml336
-rw-r--r--indra/newview/skins/default/xui/en/control_table_contents_movement.xml15
-rw-r--r--indra/newview/skins/default/xui/en/floater_font_test.xml38
-rw-r--r--indra/newview/skins/default/xui/en/floater_joystick.xml69
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml25
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml9
-rw-r--r--indra/newview/skins/default/xui/en/game_control_table_camera_rows.xml106
-rw-r--r--indra/newview/skins/default/xui/en/game_control_table_rows.xml116
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml70
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_controls.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_game_control.xml1205
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_move.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml41
-rw-r--r--indra/newview/tests/llgamecontrol_stub.cpp99
-rw-r--r--indra/newview/tests/llversioninfo_test.cpp5
-rwxr-xr-xindra/newview/viewer_manifest.py6
57 files changed, 10275 insertions, 696 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b800e65909..8d65e4b026 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -338,6 +338,7 @@ set(viewer_SOURCE_FILES
llfollowcam.cpp
llfriendcard.cpp
llflyoutcombobtn.cpp
+ llflycam.cpp
llgesturelistener.cpp
llgesturemgr.cpp
llgiveinventory.cpp
@@ -512,6 +513,7 @@ set(viewer_SOURCE_FILES
llpanelplaceprofile.cpp
llpanelplaces.cpp
llpanelplacestab.cpp
+ llpanelpreferencegamecontrol.cpp
llpanelpresetscamerapulldown.cpp
llpanelpresetspulldown.cpp
llpanelprimmediacontrols.cpp
@@ -1038,6 +1040,7 @@ set(viewer_HEADER_FILES
llfollowcam.h
llfriendcard.h
llflyoutcombobtn.h
+ llflycam.h
llgesturelistener.h
llgesturemgr.h
llgiveinventory.h
@@ -1201,6 +1204,7 @@ set(viewer_HEADER_FILES
llpanelplaceprofile.h
llpanelplaces.h
llpanelplacestab.h
+ llpanelpreferencegamecontrol.h
llpanelpresetscamerapulldown.h
llpanelpresetspulldown.h
llpanelprimmediacontrols.h
@@ -1792,6 +1796,7 @@ set(viewer_APPSETTINGS_FILES
app_settings/toolbars.xml
app_settings/trees.xml
app_settings/viewerart.xml
+ app_settings/gamecontrollerdb.txt
app_settings/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
#packages-info.txt
@@ -2793,7 +2798,7 @@ if (LL_TESTS)
set_property(SOURCE
${viewer_TEST_SOURCE_FILES}
PROPERTY
- LL_TEST_ADDITIONAL_LIBRARIES
+ LL_TEST_ADDITIONAL_LIBRARIES
${test_libs}
)
diff --git a/indra/newview/app_settings/gamecontrollerdb.txt b/indra/newview/app_settings/gamecontrollerdb.txt
new file mode 100644
index 0000000000..e7a236ea53
--- /dev/null
+++ b/indra/newview/app_settings/gamecontrollerdb.txt
@@ -0,0 +1,2209 @@
+# Game Controller DB for SDL in 2.0.16 format
+# Source: https://github.com/mdqinc/SDL_GameControllerDB
+
+# Windows
+03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
+03000000fa190000918d000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
+03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
+03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000060d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000070d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
+03000000c82d00001930000000000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows,
+03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000951000000000000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows,
+03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows,
+03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00002090000000000000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000451000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows,
+03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows,
+03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
+03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
+03000000c82d00006928000000000000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows,
+03000000c82d00002590000000000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows,
+03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000131000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000231000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000331000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000431000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00002867000000000000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b10,x:b3,y:b4,platform:Windows,
+03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+030000003512000020ab000000000000,8BitDo SN30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a2,rightshoulder:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001260000000000000,8BitDo Ultimate 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001c30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001d30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001130000000000000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
+03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
+030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows,
+030000006f0e00008801000000000000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows,
+0300000008100000e501000000000000,Anbernic Game Pad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000020500000913000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000373500000710000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000373500004610000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000190e00000110000000000000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Windows,
+03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows,
+03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows,
+03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
+03000000380800001889000000000000,AtGames Legends Gamer Pro,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b14,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000008a3500000102000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
+030000008a3500000201000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
+030000008a3500000302000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
+030000008a3500000402000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
+03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,
+030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows,
+030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000bc2000000055000000000000,Betop BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000790000000700000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
+03000000808300000300000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
+03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000006f0e00006401000000000000,BF One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000300f00000202000000000000,Bigben,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
+030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
+030000005a1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
+030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
+030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
+030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
+030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000d814000007cd000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000d8140000cefa000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,
+030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000a306000022f6000000000000,Cyborg V.3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows,
+030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows,
+030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+03000000bd12000002e0000000000000,Dual Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
+03000000ff1100003133000000000000,DualForce,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b1,platform:Windows,
+030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000bc2000000091000000000000,EasySMX Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000006e0500000a20000000000000,Elecom DUX60 MMO,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows,
+03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
+03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
+03000095090000010000000000000000,Elecom JC-U609,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
+0300004112000000e500000000000000,Elecom JC-U909Z,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
+03000041120000001050000000000000,Elecom JC-U911,a:b1,b:b2,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b0,x:b4,y:b5,platform:Windows,
+030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+03000000250900000218000000000000,Elecom PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
+030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
+030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows,
+03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000062000001801000000000000,EMS TrioLinker Plus II,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Windows,
+03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows,
+03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00008101000000000000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03005036852100000000000000000000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows,
+03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
+03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
+03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows,
+03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
+03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
+0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
+03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,
+03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows,
+03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows,
+03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000ac0500002d02000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000ac0500004d04000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000ac0500001a06000000000000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000373500009410000000000000,GameSir Tegenaria Lite,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+0300000047530000616d000000000000,GameStop,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows,
+030000008f0e00001411000000000000,Gamo2 Divaller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000c21100000791000000000000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000c9110000f055000000000000,Be1 GC100XF Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000d11800000094000000000000,Google Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
+030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000007d0400000840000000000000,Gravis Destroyer Tilt,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows,
+030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000280400000140000000000000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a3,dpup:-a4,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
+03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000008a2e0000dd10000000000000,Hand Held Legend GC Ultimate,a:b0,b:b2,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,misc2:b24,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b1,y:b3,platform:Windows,
+030000008a2e0000df10000000000000,Hand Held Legend ProGCC,a:b1,b:b0,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b3,y:b2,platform:Windows,
+030000000d0f00004900000000000000,Hatsune Miku Sho PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
+030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
+03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00008500000000000000,Hori Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006201000000000000,Hori Fighting Commander Octa,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006401000000000000,Hori Fighting Commander Octa,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00005100000000000000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00008800000000000000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
+030000000d0f00008700000000000000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00000d00000000000000,Hori Fightstick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows,
+030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows,
+030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows,
+030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002301000000000000,Hori PS4 Controller Light,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+030000000d0f00001100000000000000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows,
+030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows,
+030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006400000000000000,Horipad 3TP,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006e00000000000000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000c100000000000000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000000d0f00000202000000000000,Horipad O Nintendo Switch 2 Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,misc2:b14,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000000d0f00009601000000000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc2:b2,paddle1:b5,paddle2:b15,paddle3:b18,paddle4:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
+03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows,
+03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
+03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows,
+03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
+03000000242e00000a20000000000000,Hyperkin Scout Premium SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
+03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
+03000000f00300008d04000000000000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:-a2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:+a5,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
+03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows,
+03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000511d00000230000000000000,iGUGU Gamecore,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b1,leftstick:b4,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b2,platform:Windows,
+03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
+030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500000030000000000000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows,
+03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows,
+03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
+03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows,
+03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows,
+03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows,
+030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,
+030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
+03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,
+03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows,
+03000000242f00002d00000000000000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000242f00008a00000000000000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
+03000000c4100000c082000000000000,KADE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows,
+03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
+03000000bd12000001e0000000000000,Leadership,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000008f0e00001300000000000000,Logic3,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,
+030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006d04000019c2000000000000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006d0400001ac2000000000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows,
+030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
+03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000380700008031000000000000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
+030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
+030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
+0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000242f0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
+03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
+03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows,
+030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
+03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows,
+0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,righttrigger:b2,start:b3,platform:Windows,
+030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows,
+030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
+030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows,
+03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows,
+03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000004523000015e0000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000491900000904000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000ffff00000000000000000000,Mocute M053,a:b3,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b11,leftstick:b7,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b6,righttrigger:b4,rightx:a3,righty:a4,start:b8,x:b1,y:b0,platform:Windows,
+03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c62400002b89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c62400001a89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows,
+03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
+030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+0300000085320000170d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+0300000085320000190d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000eb0300000000000000000000,NeGcon Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows,
+0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows,
+03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
+03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
+03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
+03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,
+03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows,
+03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
+03000000ec110000e1a7000000000000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows,
+030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,
+030000007e0500007320000000000000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Windows,
+030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows,
+030000007e0500001720000000000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Windows,
+03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows,
+03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows,
+030000005509000000b4000000000000,NVIDIA Virtual,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000004b120000014d000000000000,NYKO Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000791d00000900000000000000,Nyko Playpad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000782300000a10000000000000,Onlive Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows,
+030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000008916000001fd000000000000,Onza CE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
+0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
+03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
+03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00008901000000000000,PDP Realmz Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows,
+03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000d620000013a7000000000000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000d62000003340000000000000,PowerA OPS Pro Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000d62000002640000000000000,PowerA OPS Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000d620000014a7000000000000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000250900000088000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000151a00006222000000000000,PS2 Dual Plus Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
+030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows,
+030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows,
+03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,
+030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
+030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
+03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000004c0500005f0e000000000000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows,
+03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,
+03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
+03000000222c00000025000000000000,Qanba Dragon Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
+03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,
+03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows,
+03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
+03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
+030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
+030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
+030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows,
+030000009b280000d000000000000000,Raphnet Dreamcast Adapter,a:b1,b:b0,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,lefttrigger:+a5,leftx:a0,lefty:a1,righttrigger:+a2,start:b3,x:b5,y:b4,platform:Windows,
+030000009b2800006200000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
+030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
+030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
+030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows,
+030000009b2800003c00000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows,
+030000009b2800006100000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows,
+030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows,
+030000009b2800006400000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows,
+030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
+030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
+030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+030000009b2800002600000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800002e00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800002f00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows,
+030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
+030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
+03000000790000008f18000000000000,Rapoo Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
+0300000032150000a602000000000000,Razer Huntsman V3 Pro,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows,
+03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000321500000a10000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows,
+03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
+03000000632500007805000000000000,Retro Fighters Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows,
+03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Windows,
+0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
+0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
+03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows,
+030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000fefa000000000000,Rock Candy Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00008701000000000000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000830500007030000000000000,Rockfire Space Ranger,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b9,righttrigger:b8,start:b2,x:b3,y:b4,platform:Windows,
+03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
+03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
+03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
+03000000050b0000181a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
+03000000050b00001a1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
+03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
+030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,platform:Windows,
+030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e00001311000000000000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Windows,
+03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000a306000023f6000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
+03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,
+03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows,
+03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,
+03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b8,x:b0,y:b3,platform:Windows,
+03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+03000000a306000018f5000000000000,Saitek P3200,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00001001000000000000,Saitek P480 Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
+03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows,
+03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
+03000000a30600002106000000000000,Saitek PS1000 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
+03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows,
+03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows,
+03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows,
+03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
+030000009d0d00001130000000000000,Sanwa PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows,
+03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
+03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a2,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
+0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows,
+03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
+03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
+030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows,
+03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows,
+03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
+030000008f0e00000910000000000000,Sony DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
+03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
+03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000fe1400002a23000000000000,Sony PlayStation Adapter,a:b0,b:b1,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,x:b2,y:b3,platform:Windows,
+030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
+03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000d9040000160f000000000000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+030000004c0500003713000000000000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
+03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
+03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows,
+030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
+03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,
+03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
+030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
+03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+03000000341200001300000000000000,Super Racer,a:b2,b:b3,back:b8,leftshoulder:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b7,x:b0,y:b1,platform:Windows,
+03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,
+030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000e40a00000307000000000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows,
+03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows,
+03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
+03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
+03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
+03000000790000001c18000000000000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000790000002601000000000000,TGZ Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
+03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows,
+030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004f0400000ed0000000000000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004f04000008d0000000000000,Thrustmaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,
+030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
+030000004f04000003d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000004f04000009d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000666600000288000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+030000004f04000007d0000000000000,TMini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000571d00002100000000000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows,
+03000000571d00002000000000000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows,
+03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows,
+03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+030000000b0400003065000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
+03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows,
+03000000300f00000701000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000341a00002308000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000666600000188000000000000,USB Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
+030000006b1400000203000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000790000000a00000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
+03000000b404000081c6000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
+03000000b50700001503000000000000,USB Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
+03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
+03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000882800000305000000000000,V5 Game Pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,x:b2,y:b3,platform:Windows,
+03000000790000001a18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+03000000790000001b18000000000000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
+0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows,
+03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
+0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700002045000000000000,Xbox 360 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows,
+03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows,
+03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
+030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000ff02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+03000000450c00002043000000000000,Xeox SL6556BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
+03000000e0ff00000201000000000000,Xiaomi Black Shark (L),back:b0,dpdown:b11,dpleft:b9,dpright:b10,dpup:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,platform:Windows,
+03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
+03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows,
+03000000c0160000e105000000000000,XinMo Dual Arcade,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
+030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows,
+030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows,
+03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
+03000000073500000400000000000000,Zenaim Arcade Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
+03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
+03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
+
+# Mac OS X
+030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000c82d00001930000000000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
+03000000c82d00001930000000020000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
+03000000c82d00001930000001000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
+03000000c82d00000031000001000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00000531000000020000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
+03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Mac OS X,
+03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X,
+03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,lefttrigger:a5,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
+03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
+03000000c82d00002590000000010000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00002690000000010000,8BitDo NEOGEO,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b10,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000190000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000431000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00003028000000010000,8Bitdo SFC30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00004028000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001d30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001130000000020000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001330000000020000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001330000001000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,
+03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
+0300000008100000e501000019040000,Anbernic Handheld,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
+03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
+03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
+03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
+03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
+030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
+030000008a3500000402000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000008a3500000302000000010000,Backbone One PlayStation Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
+03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
+03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,
+03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X,
+030000006f0e00008401000003010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X,
+03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
+03000000ac0500001a06000002020000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000373500000411000023000000,GameSir X4A Xbox Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X,
+03000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
+030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,
+030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008800000000010000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00008700000000010000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X,
+030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f0000aa00000072050000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000000d0f00000002000017010000,Hori Split Pad Fit,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00000002000015010000,Hori Switch Split Pad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000000d0f0000c100000072050000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Mac OS X,
+03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X,
+03000000830500006020000000000000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
+03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,
+03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X,
+030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000242f00002d00000007010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000006d04000019c2000000000000,Logitech Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000019c2000000020000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000016c2000000000000,Logitech F310,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000006d04000018c2000000010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+0300000049190000020400001b010000,Manba One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X,
+03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
+03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X,
+0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000008f0e00001030000011010000,Mayflash Saturn Adapter,a:b0,b:b2,dpdown:b28,dpleft:b30,dpright:b26,dpup:b24,leftshoulder:b10,lefttrigger:b14,rightshoulder:b12,righttrigger:b4,start:b18,x:b6,y:b8,platform:Mac OS X,
+0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,
+03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X,
+03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
+03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
+030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X,
+030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X,
+030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X,
+030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
+030000004523000015e0000072050000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
+03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000853200008906000000010000,Nacon Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
+030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000ec110000e1a7000001010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X,
+030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+030000007e0500000920000010020000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X,
+050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X,
+030000007e0500007320000001010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Mac OS X,
+030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X,
+030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,
+030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X,
+0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000d620000011a7000010050000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
+030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
+030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
+030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+0300004b4c0500005f0e000000010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000005e040000e002000001000000,PXN P30 Pro Mobile,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
+03000000222c00000225000000010000,Qanba Dragon Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000009b2800005600000020020000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Mac OS X,
+030000009b2800008000000022020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Mac OS X,
+030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000321500000104000000010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+03000000321500000010000000010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000321500000011000000010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
+030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
+0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000632500002305000000010000,Redragon Saturn,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000921200004547000000020000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X,
+03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X,
+0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Mac OS X,
+03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X,
+030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000004c0500006802000002100000,Rii RK707,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b3,righttrigger:b9,rightx:a2,righty:a3,start:b1,x:b15,y:b12,platform:Mac OS X,
+030000006f0e00008701000005010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000e804000000a000001b010000,Samsung EIGP20,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b11,leftx:a1,lefty:a3,rightshoulder:b12,rightx:a4,righty:a5,start:b16,x:b7,y:b9,platform:Mac OS X,
+03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X,
+03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X,
+03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,
+03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,
+030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
+0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,
+030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+03000000666600006706000088020000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X,
+030000004c050000da0c000000010000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+030000004c0500003713000000010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
+03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
+03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
+05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
+050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X,
+03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
+03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
+030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
+03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
+03000000790000001c18000000010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
+03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X,
+030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
+030000004f0400000ed0000000020000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
+03000000571d00002100000021000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X,
+03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000571d00002000000021000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
+030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
+03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,
+03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000c0160000e105000000040000,Ultimate Atari Fight Stick,a:b2,b:b4,back:b18,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b8,righttrigger:b10,start:b16,x:b0,y:b6,platform:Mac OS X,
+03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X,
+030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
+050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,
+050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,
+030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4~,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e040000050b000003090000,Xbox Elite Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000200b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000200b000015050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
+030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
+030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
+03000000c62400003a54000000000000,Xbox One PowerA Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000130b000022050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+030000005e040000220b000021050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
+03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
+
+# Linux
+03000000c82d00001930000011010000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
+05000000c82d00001930000001000000,8BitDo 64,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
+03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000631000000010000,8BitDo Adapter 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
+03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Linux,
+03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000a20000000020000,8BitDo M30 Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
+03000000c82d00002090000011010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
+03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00006928000011010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
+05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
+05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
+05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
+03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c82d00000960000011010000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux,
+03000000c82d00000060000011010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
+030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000a31000014010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000631000010010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c82d00000631000014010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
+05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
+03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00003901000013020000,Afterglow Prismatic Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00001302000000010000,Afterglow Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00003901000020060000,Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000100000008200000011010000,Akishop Customs PS360,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000007c1800000006000010010000,Alienware Dual Compatible Game PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
+05000000491900000204000021000000,Amazon Fire Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
+05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
+0300000008100000e501000001010000,Anbernic Handheld,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux,
+03000000020500000913000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000373500000710000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000190e00000110000010010000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Linux,
+03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
+05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
+03000000050b00000579000011010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+03000000503200000110000011010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+05000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+05000000503200000110000044010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+05000000503200000110000046010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
+03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux,
+03000000503200000210000011010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
+05000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
+05000000503200000210000045010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
+05000000503200000210000046010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
+05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:-a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux,
+030000008a3500000201000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000008a3500000202000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000008a3500000302000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000008a3500000402000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000bc2000004d50000011010000,Beitong A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000300e000011010000,Brook Audio Fighting Board PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000310e000011010000,Brook Audio Fighting Board PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000d81d00000b00000010010000,Buffalo BSGP1601,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Linux,
+03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,
+030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,
+03000000632500007a05000001020000,Cosmic Byte Ares Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,
+03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
+030000005e0400008e02000002010000,Data Frog S80,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
+03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000242f00009100000000010000,EasySMX ESM-9101,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,
+030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
+030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
+03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000852100000201000010010000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
+19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+03000000373500000b10000019010000,GameSir Cyclone 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000373500009710000001020000,GameSir Kaleid Flux,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000ac0500001a06000011010000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000373500009410000010010000,GameSir Tegenaria Lite,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000f025000021c1000010010000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000f0250000c283000010010000,Gioteck VX2 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux,
+190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux,
+190000004b4800000011000000010000,GO-Super Gamepad,a:b0,b:b1,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b3,y:b2,platform:Linux,
+03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000d11800000094000011010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
+05000000d11800000094000000010000,Google Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
+0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000001010000,GPD Win Max 2 6800U Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,
+030000008f0e00001200000010010000,GreenAsia Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000008a2e0000dd10000011010000,Hand Held Legend GC Ultimate,a:b0,b:b2,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,misc2:b24,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b1,y:b3,platform:Linux,
+030000008a2e0000df10000011010000,Hand Held Legend ProGCC,a:b1,b:b0,back:b17,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,guide:b18,leftshoulder:b10,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b19,paddle1:b13,paddle2:b12,rightshoulder:b11,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b3,y:b2,platform:Linux,
+06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,
+03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000000d0f00005001000009040000,Hori Fighting Commander Octa Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux,
+030000000d0f00008800000011010000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00008700000011010000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
+030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux,
+030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00001100000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
+030000000d0f0000aa00000011010000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000000d0f00008501000017010000,Hori Split Pad Fit,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f0000c100000011010000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f0000ab01000011010000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000000d0f00009601000091000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
+05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
+03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux,
+03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux,
+03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000830500006020000010010000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
+03000000d80400004bea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,x:b2,y:b3,back:b4,platform:Linux,
+03000000d80400004aea000011010000,icedragon.io STAC Dance Pad,a:b0,b:b1,x:b2,y:b3,back:b4,platform:Linux,
+030000008a2e0000d910000011010000,icedragon.io STAC2 Dance Pad,a:b0,b:b1,x:b2,y:b3,back:b4,platform:Linux,
+030000008a2e0000e910000011010000,icedragon.io STAC2 Dance Pad,a:b8,b:b9,x:b10,y:b11,back:b12,platform:Linux,
+030000008f0e00001330000001010000,iCode Retro Adapter,b:b3,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b1,start:b7,x:b2,y:b0,platform:Linux,
+050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
+03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,
+03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
+03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,
+03000000fd0500000030000000010000,InterAct GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Linux,
+03000000fd0500002a26000000010000,InterAct HammerHead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,
+0500000049190000020400001b010000,Ipega PG 9069,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000300f00001101000010010000,Jess Tech Colour Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
+03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
+03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+03000000ba2200002010000001010000,Jess Technology Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,
+050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,
+030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,
+050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,
+03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000242f00002d00000011010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
+030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d0400001dc2000014400000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d0400001ec2000019200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d0400001ec2000020200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d04000019c2000011010000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d0400001fc2000005030000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,
+030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,
+05000000380700006652000025010000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700008532000010010000,Mad Catz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
+03000000380700008031000011010000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700008081000011010000,Mad Catz FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700008483000011010000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000380700001888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700003888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000380700001647000010040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000120c00000500000000010000,Manta DualShock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+030000008f0e00001330000010010000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
+0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000008f0e00001030000010010000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
+0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
+03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
+03000000790000000018000011010000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
+03000000b50700004f00000000010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
+03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux,
+030000005e0400000300000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
+030000005e0400000700000000010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
+030000005e0400000e00000000010000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
+030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux,
+030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+030000005e0400008902000021010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000062230000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000d102000001010000,Microsoft Xbox One a,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000d102000003020000,Microsoft Xbox One b,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000dd02000003020000,Microsoft Xbox One c,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000ea02000008040000,Microsoft Xbox One d,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000ea0200000f050000,Microsoft Xbox One e,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000120b000009050000,Microsoft Xbox One d,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000000b000007040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000016050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000017050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000120b000001050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
+03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+05000000e80400006e0400001b010000,Mocute 053X M59,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000d6200000e589000001000000,Moga 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
+05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
+05000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
+03000000c62400002b89000011010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
+030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux,
+030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000853200000706000012010000,Nacon GC-100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+05000000853200000503000000010000,Nacon MG-X Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux,
+03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,
+060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
+03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
+03000000ec110000e1a7000010010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux,
+060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+050000004c69632050726f20436f6e00,Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux,
+030000007e0500000920000000026803,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Linux,
+030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
+050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
+05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
+050000005a1d00000218000003000000,Nokia GC 5000,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
+030000007e0500007320000011010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Linux,
+030000007e0500001920000011810000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux,
+050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
+050000007e0500001920000001800000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux,
+030000007e0500001e20000011810000,NSO Sega Genesis Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,misc1:b3,rightshoulder:b2,righttrigger:b4,start:b5,platform:Linux,
+030000007e0500001720000011810000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
+050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux,
+050000007e0500001720000001800000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
+03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000550900001472000011010000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
+05000000550900001472000001000000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
+030000004b120000014d000000010000,NYKO Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
+19000000010000000200000011000000,ODROID Go 2,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux,
+05000000362800000100000002010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,
+05000000362800000100000003010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,
+05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux,
+03000000830500005020000010010000,Padix Rockfire PlayStation Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux,
+03000000ff1100003133000010010000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00008501000011010000,PDP Fightpad Pro Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00002801000011010000,PDP PS3 Rock Candy Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00002f01000011010000,PDP Wired PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e0000f102000000000000,PDP Xbox Atomic,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000540000001010000,PowerA Advantage Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d620000013a7000011010000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000d620000014a7000011010000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000220000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
+03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000520000050010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000b20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000250900000017000010010000,PS/SS/N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux,
+03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000120c0000160e000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+030000005f1400003102000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+050000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+030000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+0300004b4c0500005f0e000011010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000004c050000f20d000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+050000004c050000f20d000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
+03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,
+03000000222c00000225000011010000,Qanba Dragon Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000222c00000025000011010000,Qanba Dragon Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000222c00001220000011010000,Qanba Drone 2 Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick PS5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux,
+03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
+030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux,
+0300132d9b2800006500000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
+0300132d9b2800006500000001010000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
+030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
+030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
+030000009b2800003c00000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux,
+030000009b2800006100000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux,
+030000009b2800006300000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux,
+030000009b2800006400000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux,
+030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux,
+030000009b2800008000000001010000,Raphnet Wii Classic Adapter V3,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux,
+03000000f8270000bf0b000011010000,Razer Kishi,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000321500000010000011010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000321500000011000011010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
+050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
+0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+0300000032150000140a000001010000,Razer Wolverine Ultimate Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
+0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
+190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux,
+0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
+00000000526574726f53746f6e653200,RetroStone 2 Controller,a:b1,b:b0,back:b10,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Linux,
+03000000341200000400000000010000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Linux,
+030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00008701000011010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00001311000011010000,Saffun Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b0,platform:Linux,
+03000000a306000023f6000011010000,Saitek Cyborg PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
+03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,
+03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux,
+03000000a30600000cff000010010000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux,
+03000000a30600000d5f000010010000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
+03000000a30600000c04000011010000,Saitek P2900,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,
+03000000a306000018f5000010010000,Saitek P3200 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
+03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
+03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,
+03000000a30600000b04000000010000,Saitek P990 Dual Analog,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
+03000000a306000020f6000011010000,Saitek PS2700 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
+05000000e804000000a000001b010000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux,
+03000000952e00004b43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
+03000000952e00004d43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
+03000000952e00004e43000011010000,Scuf Envision,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
+03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux,
+03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
+03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
+03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000632500002605000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000632500007505000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000bc2000000055000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+030000004b2900000430000011000000,Snakebyte Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+03000000666600006706000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
+030000004c050000da0c000011010000,Sony PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000d9040000160f000000010000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
+030000004c0500003713000011010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
+03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
+030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
+03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
+03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
+03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
+03000000de2800000512000010010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux,
+03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux,
+03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux,
+03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,
+030000001f08000001e4000010010000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
+0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
+030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000457500000401000011010000,SZMY Power DS4 Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
+03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
+03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
+03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
+03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
+030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
+030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
+030000004f04000020b3000010010000,Thrustmaster Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
+030000004f04000023b3000000010000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000004f0400000ed0000011010000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux,
+030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux,
+030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,
+030000004f04000004b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
+030000004f04000026b3000002040000,Thrustmaster GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c6240000025b000002020000,Thrustmaster GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000004f04000008d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000004f04000009d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000004f04000007d0000000010000,Thrustmaster T Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000004f04000012b3000010010000,Thrustmaster Vibrating Gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
+03000000571d00002000000010010000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
+03000000bd12000015d0000010010000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
+03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
+030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+03000000680a00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
+03000000780300000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
+03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
+03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
+030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
+06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux,
+03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,
+03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,
+03000000790000001a18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000001b18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
+05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
+05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
+030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000014010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400009102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000a102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000a102000030060000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00001503000000020000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000000010000,Xbox 360 EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+0000000058626f782047616d65706100,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+030000005e0400008e02000072050000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006f0e00001304000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
+030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
+030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000ea02000001030000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000dd02000003020000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000ea02000015050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000ea02000017050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000ea02000016050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000011050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000014050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000015050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000007050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000130b000017050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000005e040000130b000022050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+060000005e040000120b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000200b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000200b000023050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+050000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
+03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
+03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,
+030000005e0400008e02000020010000,XInput Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000120c0000100e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000101e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000120c0000182e000011010000,Zeroplus PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+03000000790000002201000011010000,ZhiXu GuliKit D,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+
+# Android
+38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
+64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
+33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
+34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android,
+38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android,
+38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android,
+32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android,
+38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android,
+64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android,
+66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android,
+66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android,
+38426974446f204d6963726f2067616d,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android,
+61653365323561356263373333643266,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android,
+62613137616239666338343866326336,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android,
+33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
+38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
+05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38323035343766666239373834336637,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android,
+38426974446f204e3634204d6f646b69,8BitDo N64,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android,
+32363135613966656338666638666237,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+35363534633333373639386466346631,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38426974446f204e454f47454f204750,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+39383963623932353561633733306334,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android,
+38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+61333362366131643730353063616330,8BitDo Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Android,
+38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android,
+61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android,
+05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
+38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android,
+33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
+63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
+4c696e757820342e31392e3137322077,Anbernic Handheld,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android,
+35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,start:b6,platform:Android,
+32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+4f64696e20436f6e74726f6c6c657200,AYN Odin,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b14,dpright:b13,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:+a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android,
+4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android,
+30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android,
+05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+476f6f676c65204c4c43205374616469,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+5374616469614e3848532d6532633400,Google Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
+05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android,
+66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+484f524920434f2e2c4c544420205041,Hori Gem Pad 3,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android,
+65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b18,platform:Android,
+31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+32656664353964393561366362333636,Hori Switch Split Pad Pro,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+30306539356238653637313730656134,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android,
+62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android,
+31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
+5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
+0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android,
+5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android,
+64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android,
+532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android,
+65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android,
+33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
+35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
+4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android,
+38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+39373064396565646338333134303131,Joy-Con (R),a:b1,b:b2,back:b5,leftstick:b8,leftx:a1~,lefty:a0,start:b6,x:b0,y:b3,platform:Android,
+4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android,
+64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android,
+6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android,
+436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
+65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android,
+37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android,
+4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android,
+535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
+30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android,
+39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android,
+31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android,
+37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android,
+64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b9,x:b2,y:b3,platform:Android,
+33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android,
+30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android,
+32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+4d4f42415041442050726f2d48440000,Mobapad Chitu HD,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android,
+050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android,
+31316661666466633938376335383661,Nintendo Switch Pro Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,start:b6,x:b3,y:b2,platform:Android,
+34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android,
+36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android,
+4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android,
+534e455320436f6e74726f6c6c657200,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+64623863346133633561626136366634,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android,
+050000005509000003720000cf7f3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005509000010720000ffff3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005509000014720000df7f3f00,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
+050000005509000014720000df7f3f80,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android,
+37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android,
+4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android,
+506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android,
+61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android,
+32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android,
+050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+050000004c050000c4050000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+30303839663330346632363232623138,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+31326235383662333266633463653332,PS4 Controller,a:b1,b:b16,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android,
+31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+31663838336334393132303338353963,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+34613139376634626133336530386430,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+37626233336235343937333961353732,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+37626464343430636562316661643863,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38393161636261653636653532386639,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+63313733393535663339656564343962,PS4 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+63393662363836383439353064663939,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
+050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
+050000004c050000e60c0000fffe3f80,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b2,y:b17,platform:Android,
+050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
+37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
+61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
+64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,
+36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+05000000f8270000bf0b0000ffff3f00,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
+5a6869587520526574726f2042697420,Retro Bit Saturn Controller,a:b21,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b26,rightshoulder:b27,righttrigger:b28,start:b30,x:b23,y:b24,platform:Android,
+32417865732031314b6579732047616d,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+36313938306539326233393732613361,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
+526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android,
+61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android,
+526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+64633735616665613536653363336132,Retroid Pocket,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b19,paddle2:b20,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,start:b6,platform:Android,
+37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android,
+5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android,
+526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android,
+64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android,
+37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
+33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android,
+36363537303435333566386638366333,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+53616d73756e672047616d6520506164,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android,
+32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android,
+38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android,
+61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android,
+30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
+66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
+66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android,
+62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
+5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
+5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
+62653335326261303663356263626339,Sony PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android,
+536f6e7920496e746572616374697665,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+576972656c65737320436f6e74726f6c,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android,
+63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android,
+05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
+05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
+0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android,
+35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android,
+33313930373536613937326534303931,Taito Egret II Mini Control Panel,a:b25,b:b23,back:b27,guide:b30,leftx:a0,lefty:a1,rightshoulder:b21,righttrigger:b22,start:b28,x:b29,y:b24,platform:Android,
+54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android,
+38346162326232346533316164363336,THEGamepad,a:b23,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b24,y:b21,platform:Android,
+050000004f0400000ed00000fffe3f00,Thrustmaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,
+30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
+33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android,
+050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+58626f782033363020576972656c6573,Xbox 360 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+65353331386662343338643939643636,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+65613532386633373963616462363038,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+47656e6572696320582d426f78207061,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+4d6963726f736f667420582d426f7820,Xbox Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+64633436313965656664373634323364,Xbox Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e04000091020000ff073f00,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+050000005e04000091020000ff073f80,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000e00200000ffe3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android,
+050000005e040000e00200000ffe3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android,
+050000005e040000e0020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android,
+050000005e040000e0020000ffff3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android,
+050000005e040000fd020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,
+35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+65316262316265373335666131623538,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000000b000000783f80,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000050b0000ffff3f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000120b000000783f80,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
+050000001727000044310000ffff3f00,XiaoMi Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
+
+# iOS
+05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,
+05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,
+05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,
+05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS,
+05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS,
+05000000ac05000004000000a8986d04,8BitDo Micro,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,platform:iOS,
+05000000ac05000004000000fd216d04,8BitDo Pro 2,a:b3,b:b2,back:b6,dpdown:b9,dpleft:b10,dpright:b11,dpup:b12,guide:b4,leftshoulder:b13,leftstick:b14,lefttrigger:+a2,leftx:a0,lefty:a1~,paddle1:b1,paddle2:b0,rightshoulder:b16,rightstick:b17,righttrigger:+a5,rightx:a3,righty:a4~,start:b5,x:b8,y:b7,platform:iOS,
+05000000ac05000004000000209f6d04,8Bitdo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,platform:iOS,
+05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,platform:iOS,
+050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,
+4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,
+050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS,
+050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,platform:iOS,
+050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS,
+050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS,
+050000007e050000072000000f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS,
+050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS,
+050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS,
+050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,platform:iOS,
+05000000ac050000040000008e586d04,PlayStation VR2 Sense Controller (L),+leftx:+a3,+lefty:+a1,-leftx:+a2,-lefty:+a4,back:b2,leftstick:b4,lefttrigger:+a7,paddle2:b3,x:b0,y:b1,platform:iOS,
+05000000ac050000040000000eb86d04,PlayStation VR2 Sense Controller (R),+rightx:+a3,+righty:+a1,-rightx:+a2,-righty:+a4,a:b0,b:b1,paddle1:b3,rightstick:b4,righttrigger:+a7,start:b2,platform:iOS,
+050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS,
+050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,platform:iOS,
+050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS,
+05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,
+05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,
+05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,
+05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,
+050000005e040000050b0000df070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
+050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,
+050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml
index 8d5349550f..e0d4673725 100644
--- a/indra/newview/app_settings/key_bindings.xml
+++ b/indra/newview/app_settings/key_bindings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<keys xml_version="1">
+<keys xml_version="2">
<first_person>
<binding key="A" mask="NONE" command="slide_left"/>
<binding key="D" mask="NONE" command="slide_right"/>
@@ -7,6 +7,7 @@
<binding key="S" mask="NONE" command="push_backward"/>
<binding key="E" mask="NONE" command="jump"/>
<binding key="C" mask="NONE" command="push_down"/>
+ <binding key="C" mask="SHIFT" command="toggle_down"/>
<binding key="F" mask="NONE" command="toggle_fly"/>
<binding key="LEFT" mask="NONE" command="slide_left"/>
@@ -21,9 +22,20 @@
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
- <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+ <binding key="" mask="NONE" mouse="MMB" command="voice_follow_key"/>
<binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
+
+ <binding key="" mask="none" controller="axis_forward" command="push_forward"/>
+ <binding key="" mask="none" controller="axis_backward" command="push_backward"/>
+ <binding key="" mask="none" controller="axis_left" command="slide_left"/>
+ <binding key="" mask="none" controller="axis_right" command="slide_right"/>
+ <binding key="" mask="none" controller="button_a" command="jump"/>
+ <binding key="" mask="none" controller="button_b" command="push_down"/>
+ <binding key="" mask="none" controller="axis_turn_left" command="turn_left"/>
+ <binding key="" mask="none" controller="axis_turn_right" command="turn_right"/>
+ <binding key="" mask="none" controller="axis_look_up" command="pitch_forward"/>
+ <binding key="" mask="none" controller="axis_look_down" command="pitch_backward"/>
</first_person>
<third_person>
<binding key="A" mask="NONE" command="turn_left"/>
@@ -34,6 +46,7 @@
<binding key="S" mask="NONE" command="push_backward"/>
<binding key="E" mask="NONE" command="jump"/>
<binding key="C" mask="NONE" command="push_down"/>
+ <binding key="C" mask="SHIFT" command="toggle_down"/>
<binding key="F" mask="NONE" command="toggle_fly"/>
@@ -51,6 +64,20 @@
<binding key="PGDN" mask="NONE" command="push_down"/>
<binding key="HOME" mask="NONE" command="toggle_fly"/>
+ <!-- Controller gamepad bindings -->
+ <binding key="" mask="none" controller="axis_forward" command="push_forward"/>
+ <binding key="" mask="none" controller="axis_backward" command="push_backward"/>
+ <binding key="" mask="none" controller="axis_left" command="slide_left"/>
+ <binding key="" mask="none" controller="axis_right" command="slide_right"/>
+ <binding key="" mask="none" controller="axis_turn_left" command="turn_left"/>
+ <binding key="" mask="none" controller="axis_turn_right" command="turn_right"/>
+ <binding key="" mask="none" controller="axis_look_up" command="spin_over_agent"/>
+ <binding key="" mask="none" controller="axis_look_down" command="spin_under_agent"/>
+
+ <binding key="" mask="none" controller="button_a" command="jump"/>
+ <binding key="" mask="none" controller="button_b" command="push_down"/>
+ <binding key="" mask="none" controller="button_dpad_up" command="toggle_fly"/>
+
<!--Camera controls in third person on Alt-->
<binding key="LEFT" mask="ALT" command="spin_around_cw"/>
<binding key="RIGHT" mask="ALT" command="spin_around_ccw"/>
@@ -87,6 +114,11 @@
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
+
+ <binding key="Q" mask="SHIFT" command="roll_left"/>
+ <binding key="E" mask="SHIFT" command="roll_right"/>
+ <binding key="Q" mask="CTL_SHIFT" command="roll_reset"/>
+ <binding key="E" mask="CTL_SHIFT" command="roll_reset"/>
</third_person>
<sitting>
<binding key="A" mask="ALT" command="spin_around_cw"/>
@@ -160,6 +192,11 @@
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
+
+ <binding key="Q" mask="SHIFT" command="roll_left"/>
+ <binding key="E" mask="SHIFT" command="roll_right"/>
+ <binding key="Q" mask="CTL_SHIFT" command="roll_reset"/>
+ <binding key="E" mask="CTL_SHIFT" command="roll_reset"/>
</sitting>
<edit_avatar>
<!--Avatar editing camera controls-->
@@ -178,8 +215,48 @@
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
- <binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+ <binding key="" mask="NONE" mouse="MMB" command="voice_follow_key"/>
<binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
</edit_avatar>
+ <flycam>
+ <binding key="W" mask="NONE" command="flycam_move_forward"/>
+ <binding key="S" mask="NONE" command="flycam_move_backward"/>
+ <binding key="A" mask="NONE" command="flycam_truck_left"/>
+ <binding key="D" mask="NONE" command="flycam_truck_right"/>
+ <binding key="E" mask="NONE" command="flycam_move_up"/>
+ <binding key="C" mask="NONE" command="flycam_move_down"/>
+
+ <!--Camera controls on Alt, mirroring third_person-->
+ <binding key="A" mask="ALT" command="flycam_yaw_left"/>
+ <binding key="D" mask="ALT" command="flycam_yaw_right"/>
+ <binding key="W" mask="ALT" command="flycam_move_forward"/>
+ <binding key="S" mask="ALT" command="flycam_move_backward"/>
+ <binding key="E" mask="ALT" command="flycam_pitch_up"/>
+ <binding key="C" mask="ALT" command="flycam_pitch_down"/>
+
+ <!--mimic alt zoom behavior with keyboard only-->
+ <binding key="W" mask="CTL_ALT" command="flycam_pitch_up"/>
+ <binding key="S" mask="CTL_ALT" command="flycam_pitch_down"/>
+
+ <!--pan on Ctrl-Alt-Shift-->
+ <binding key="A" mask="CTL_ALT_SHIFT" command="flycam_truck_left"/>
+ <binding key="D" mask="CTL_ALT_SHIFT" command="flycam_truck_right"/>
+ <binding key="W" mask="CTL_ALT_SHIFT" command="flycam_move_up"/>
+ <binding key="S" mask="CTL_ALT_SHIFT" command="flycam_move_down"/>
+
+ <binding key="LEFT" mask="NONE" command="flycam_yaw_left"/>
+ <binding key="RIGHT" mask="NONE" command="flycam_yaw_right"/>
+ <binding key="UP" mask="NONE" command="flycam_pitch_up"/>
+ <binding key="DOWN" mask="NONE" command="flycam_pitch_down"/>
+
+ <binding key="HOME" mask="NONE" command="flycam_unroll"/>
+
+ <binding key="Z" mask="NONE" command="toggle_flycam"/>
+
+ <binding key="ENTER" mask="NONE" command="start_chat"/>
+ <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
+ </flycam>
</keys>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index f2ccd5bfd3..9dad7348a8 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -115,16 +115,16 @@
<key>AFKTimeout</key>
<map>
<key>Comment</key>
- <string>
- Time before automatically setting AFK (away from keyboard) mode (seconds, 0=never).
- Valid values are: 0, 120, 300, 600, 1800
-</string>
+ <string>
+ Time before automatically setting AFK (away from keyboard) mode (seconds, 0=never).
+ Valid values are: 0, 120, 300, 600, 1800
+ </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <real>300</real>
+ <integer>300</integer>
</map>
<key>AckCollectTime</key>
<map>
@@ -316,7 +316,7 @@
<key>AudioLevelMedia</key>
<map>
<key>Comment</key>
- <string>Audio level of Quicktime movies</string>
+ <string>Audio level of parcel Media</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -423,7 +423,7 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>AutoAcceptNewInventory</key>
+ <key>AutoAcceptNewInventory</key>
<map>
<key>Comment</key>
<string>Automatically accept new notecards/textures/landmarks</string>
@@ -2785,7 +2785,7 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>DoubleClickTeleport</key>
+ <key>DoubleClickTeleport</key>
<map>
<key>Comment</key>
<string>Enable double-click to teleport where allowed (afects minimap and people panel)</string>
@@ -2928,6 +2928,28 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>DebugShowControllerState</key>
+ <map>
+ <key>Comment</key>
+ <string>Display internal controller state values</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>GameControl</key>
+ <map>
+ <key>Comment</key>
+ <string>Game controller settings: global per-mode action mappings plus per-device hardware config. Empty means use built-in defaults.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>LLSD</string>
+ <key>Value</key>
+ <map/>
+ </map>
<key>EnableGestureSounds</key>
<map>
<key>Comment</key>
@@ -9666,7 +9688,7 @@
<key>Value</key>
<real>1.0</real>
</map>
-
+
<key>RenderReflectionProbeDrawDistance</key>
<map>
<key>Comment</key>
@@ -9676,7 +9698,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <integer>64</integer>
+ <real>64.0</real>
</map>
<key>RenderReflectionProbeAmbiance</key>
<map>
@@ -9865,7 +9887,7 @@
<key>Value</key>
<real>1.0</real>
</map>
-
+
<key>RenderReflectionProbeMaxLocalLightAmbiance</key>
<map>
<key>Comment</key>
@@ -10251,7 +10273,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <integer>10</integer>
+ <integer>0</integer>
</map>
<key>MaxAttachmentComplexity</key>
<map>
@@ -11499,7 +11521,7 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
- </map>
+ </map>
<key>NearbyListShowMap</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index b29d1706c4..72ed9f8c25 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -84,7 +84,6 @@
#include "llurlentry.h"
#include "llviewercontrol.h"
#include "llviewerdisplay.h"
-#include "llviewerjoystick.h"
#include "llviewermediafocus.h"
#include "llviewermenu.h"
#include "llviewerobjectlist.h"
@@ -114,6 +113,12 @@ const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f; // meters
const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_WALK = 1.5f; // seconds
const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_FLY = 2.5f; // seconds. Flying is less presize, needs a bit more time
+// Ground-sit requests that do not originate from a click on the ground (e.g. the
+// game-control/keyboard "toggle sit" action) have no target position to check
+// against, so refuse them outright when the ground below the agent is farther
+// than this away, rather than snapping the agent down onto distant terrain.
+const F32 MAX_SIT_ON_GROUND_DISTANCE = 30.f; // meters
+
const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f;
const F64 CHAT_AGE_FAST_RATE = 3.0;
@@ -458,7 +463,7 @@ LLAgent::LLAgent() :
mCurrentFidget(0),
mFirstLogin(false),
mOutfitChosen(false),
-
+ mCrouch(false),
mVoiceConnected(false),
mMouselookModeInSignal(nullptr),
@@ -794,13 +799,17 @@ void LLAgent::moveUp(S32 direction)
mLastJumpInputTime = LLTimer::getTotalSeconds();
}
setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP);
+ mCrouch = false;
}
else if (direction < 0)
{
setControlFlags(AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP);
}
- gAgentCamera.resetView();
+ if (!mCrouch)
+ {
+ gAgentCamera.resetView();
+ }
}
//-----------------------------------------------------------------------------
@@ -851,6 +860,11 @@ void LLAgent::movePitch(F32 mag)
}
}
+bool LLAgent::isCrouching() const
+{
+ return mCrouch && !getFlying();
+}
+
// Does this parcel allow you to fly?
bool LLAgent::canFly()
{
@@ -918,6 +932,7 @@ void LLAgent::setFlying(bool fly, bool fail_sound)
{
add(LLStatViewer::FLY, 1);
}
+ mCrouch = false;
setControlFlags(AGENT_CONTROL_FLY);
}
else
@@ -1346,9 +1361,32 @@ LLVector3d LLAgent::getPosGlobalFromAgent(const LLVector3 &pos_agent) const
return pos_agent_d + mAgentOriginGlobal;
}
+static void finish_sit_on_ground(bool success, void*)
+{
+ if (success && mAllowedToSit)
+ {
+ gAgent.setFlying(false);
+ gAgent.clearControlFlags(AGENT_CONTROL_STAND_UP); // might have been set by autopilot
+ gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+ }
+}
+
void LLAgent::sitDown()
{
- if (mAllowedToSit) setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+ // Sit on the ground directly beneath (or above) the agent's current position.
+ // Refuse if that spot is too far away, and otherwise walk/fly there first,
+ // rather than snapping straight down onto it (e.g. terrain far below a flying
+ // agent) as AGENT_CONTROL_SIT_ON_GROUND would do if sent immediately.
+ LLVector3d pos_global = getPositionGlobal();
+ LLVector3d sit_spot_global = pos_global;
+ sit_spot_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(pos_global);
+
+ if (dist_vec(pos_global, sit_spot_global) > MAX_SIT_ON_GROUND_DISTANCE)
+ {
+ return;
+ }
+
+ startAutoPilotGlobal(sit_spot_global, "Sit", NULL, finish_sit_on_ground, NULL, 0.7f);
}
//-----------------------------------------------------------------------------
@@ -1447,7 +1485,7 @@ LLVector3 LLAgent::getReferenceUpVector()
return up_vector;
}
-// Radians, positive is forward into ground
+// Radians, positive is downward toward ground
//-----------------------------------------------------------------------------
// pitch()
//-----------------------------------------------------------------------------
@@ -1461,27 +1499,23 @@ void LLAgent::pitch(F32 angle)
LLVector3 skyward = getReferenceUpVector();
+ // SL-19286 Avatar is upside down when viewed from below
+ // after left-clicking the mouse on the avatar and dragging down
+ //
+ // The issue is observed on angle below 10 degrees
+ const F32 look_down_limit = 179.f * DEG_TO_RAD;
+ const F32 look_up_limit = 10.f * DEG_TO_RAD;
+
+ F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);
+
// clamp pitch to limits
- if (angle >= 0.f)
+ if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit))
{
- const F32 look_down_limit = 179.f * DEG_TO_RAD;
- F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);
- if (angle_from_skyward + angle > look_down_limit)
- {
- angle = look_down_limit - angle_from_skyward;
- }
+ angle = look_down_limit - angle_from_skyward;
}
- else if (angle < 0.f)
+ else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit))
{
- const F32 look_up_limit = 5.f * DEG_TO_RAD;
- const LLVector3& viewer_camera_pos = LLViewerCamera::getInstance()->getOrigin();
- LLVector3 agent_focus_pos = getPosAgentFromGlobal(gAgentCamera.calcFocusPositionTargetGlobal());
- LLVector3 look_dir = agent_focus_pos - viewer_camera_pos;
- F32 angle_from_skyward = angle_between(look_dir, skyward);
- if (angle_from_skyward + angle < look_up_limit)
- {
- angle = look_up_limit - angle_from_skyward;
- }
+ angle = look_up_limit - angle_from_skyward;
}
if (fabs(angle) > 1e-4)
@@ -2134,7 +2168,7 @@ bool LLAgent::needsRenderAvatar()
return mShowAvatar && mOutfitChosen;
}
- if (gAgentCamera.cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson)
+ if (gAgentCamera.isHidingAvatarForFirstPerson() && !LLVOAvatar::sVisibleInFirstPerson)
{
return false;
}
@@ -2150,7 +2184,7 @@ bool LLAgent::needsRenderHead()
{
return mShowAvatar;
}
- return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !gAgentCamera.cameraMouselook());
+ return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !gAgentCamera.isHidingAvatarForFirstPerson());
}
//-----------------------------------------------------------------------------
@@ -5017,6 +5051,437 @@ void LLAgent::renderAutoPilotTarget()
}
}
+static U64 g_lastUpdateTime { 0 };
+static F32 g_deltaTime { 0.0f };
+static S32 g_lastUpdateFrame { 0 };
+static S32 g_deltaFrame { 0 };
+
+void LLAgent::updateGameControlMode()
+{
+ // Auto-derive the active mode from avatar/camera state. Cursor mode takes
+ // precedence over Flycam: toggling the mouse cursor on while Flycam is engaged
+ // reports CONTROL_MODE_CURSOR (so the left stick drives the on-screen cursor)
+ // while isUsingFlycam() stays true underneath -- LLAgent::updateFlycam() keeps
+ // driving the camera every frame regardless of the reported mode (it is gated
+ // on LLAgentCamera's own flycam state directly, not on AgentControlMode), and
+ // LLGameControl::setFlycamEngaged() below tells the input-mapping lookup to
+ // let Flycam's own axis/button config (Pan/Tilt/Boom/...) keep driving
+ // whatever physical inputs Cursor mode's own mouse-cursor actions don't claim.
+ // This is how a single Cursor mode ends up with two flavors -- "other axes"
+ // control the avatar/camera depending on whether Flycam is concurrently
+ // engaged -- without needing a distinct mode of its own.
+ // Next: mouselook (the camera mode can be entered while sitting too, so it is
+ // checked ahead of Captive), then sitting/controls-taken maps to Captive,
+ // otherwise the normal Avatar mode.
+ LLGameControl::AgentControlMode mode;
+ if (mUsingMouseCursor)
+ {
+ mode = LLGameControl::CONTROL_MODE_CURSOR;
+ }
+ else if (isUsingFlycam())
+ {
+ mode = LLGameControl::CONTROL_MODE_FLYCAM;
+ }
+ else if (gAgentCamera.cameraMouselook())
+ {
+ mode = LLGameControl::CONTROL_MODE_MOUSELOOK;
+ }
+ else if (isSitting())
+ {
+ mode = LLGameControl::CONTROL_MODE_CAPTIVE;
+ }
+ else
+ {
+ mode = LLGameControl::CONTROL_MODE_AVATAR;
+ }
+ LLGameControl::setFlycamEngaged(isUsingFlycam());
+ LLGameControl::setAgentControlMode(mode);
+ gAgentCamera.updateFlycamCursorVisibility(mode);
+}
+
+void LLAgent::applyExternalActions(const LLGameControl::AgentActions& actions)
+{
+ llassert(LLCoros::on_main_thread_main_coro());
+ // Valid whenever game control is driving avatar or flycam: in FlyCam mode this
+ // only services the flycam on/off toggle (movement bits are ignored below).
+ assert(LLGameControl::isEnabled()
+ && (LLGameControl::willControlAvatar() || LLGameControl::willControlFlycam()));
+
+ // Process the non-flag actions first (see AgentActions comment in
+ // llgamecontrol.h). Each bit in mMiscActionBits is already edge-triggered
+ // by LLGameControllerManager::computeAgentActions() (set only on the
+ // frame the bound button transitions from not-pressed to pressed), so no
+ // further debouncing is needed here -- just react to the bit directly.
+ const U32 misc_actions = actions.mMiscActionBits;
+
+ if (misc_actions & LLGameControl::AVATAR_ACTION_TOGGLE_FLY)
+ {
+ setFlying(!getFlying());
+ }
+
+ if (misc_actions & LLGameControl::AVATAR_ACTION_TOGGLE_FLYCAM)
+ {
+ toggleFlycam();
+ }
+
+ if (misc_actions & LLGameControl::AVATAR_ACTION_TOGGLE_SIT)
+ {
+ if (isSitting())
+ {
+ standUp();
+ }
+ else if (LLViewerObject* seat = find_nearby_seat())
+ {
+ handle_object_sit(seat, LLVector3::zero);
+ }
+ else
+ {
+ sitDown();
+ }
+ }
+
+ if (misc_actions & LLGameControl::AVATAR_ACTION_TOGGLE_SPEAK)
+ {
+ LLVoiceClient::getInstance()->toggleUserPTTState();
+ }
+
+ if (misc_actions & LLGameControl::AVATAR_ACTION_TOGGLE_MOUSELOOK)
+ {
+ // Mirrors LLViewMouselook's "View.Mouselook" toggle.
+ if (!gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToMouselook();
+ }
+ else
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+ }
+
+ if (misc_actions & LLGameControl::AVATAR_ACTION_TOGGLE_MOUSE_CURSOR)
+ {
+ toggleMouseCursorMode();
+ }
+
+ if (misc_actions & LLGameControl::AVATAR_ACTION_ESCAPE)
+ {
+ resetToAvatarMode();
+ }
+
+ // CONTROL_MODE_CURSOR: drive the actual on-screen cursor from
+ // actions.mMouseCursorDX/DY (the analog deflection of whatever's bound to "Mouse
+ // left/right"/"Mouse up/down") BEFORE the click dispatch below, so a synthesized
+ // click lands wherever the stick just moved the cursor to, in the same frame.
+ if (LLGameControl::getAgentControlMode() == LLGameControl::CONTROL_MODE_CURSOR)
+ {
+ constexpr F32 MOUSE_CURSOR_PIXELS_PER_SEC = 1200.f;
+ U64 mouse_cursor_now = LLFrameTimer::getTotalTime();
+ F32 mouse_cursor_dt = (mLastMouseCursorUpdate == 0)
+ ? 0.f : F32(mouse_cursor_now - mLastMouseCursorUpdate) / (F32)(USEC_PER_SEC);
+ mLastMouseCursorUpdate = mouse_cursor_now;
+
+ if (actions.mMouseCursorDX != 0.f || actions.mMouseCursorDY != 0.f)
+ {
+ LLCoordGL cursor_pos = gViewerWindow->getCurrentMouse();
+ S32 new_x = cursor_pos.mX + ll_round(actions.mMouseCursorDX * MOUSE_CURSOR_PIXELS_PER_SEC * mouse_cursor_dt);
+ // LLCoordGL's Y increases upward, but mMouseCursorDY is in screen-frame
+ // (Y increases downward, same as CURSOR_DY/CURSOR_PY on the wire), so it
+ // subtracts here rather than adds.
+ S32 new_y = cursor_pos.mY - ll_round(actions.mMouseCursorDY * MOUSE_CURSOR_PIXELS_PER_SEC * mouse_cursor_dt);
+ gViewerWindow->moveCursorTo(new_x, new_y);
+ }
+ }
+ else
+ {
+ mLastMouseCursorUpdate = 0;
+ }
+
+ // Simulated mouse buttons (see llgamecontrol.h's AvatarMouseButton) are
+ // level-triggered: actions.mMouseButtonBits reflects which buttons are
+ // currently held, so the press/release edges are found here by diffing
+ // against last frame's value. Each edge is dispatched through
+ // LLViewerWindow exactly like a real mouse click, at the current cursor
+ // position, so it drives hover/pick/pie-menu/tool-manager the same way a
+ // hardware click would (e.g. touching/grabbing objects, walk-to-clicked,
+ // pie menu on right click).
+ U32 mouse_pressed_edges = actions.mMouseButtonBits & ~mPrevMouseButtonBits;
+ U32 mouse_released_edges = ~actions.mMouseButtonBits & mPrevMouseButtonBits;
+ mPrevMouseButtonBits = actions.mMouseButtonBits;
+
+ if (mouse_pressed_edges & LLGameControl::AVATAR_MOUSE_BUTTON_LEFT)
+ {
+ gViewerWindow->handleMouseDown(gViewerWindow->getWindow(), gViewerWindow->getCurrentMouse(), MASK_NONE);
+ }
+ if (mouse_released_edges & LLGameControl::AVATAR_MOUSE_BUTTON_LEFT)
+ {
+ gViewerWindow->handleMouseUp(gViewerWindow->getWindow(), gViewerWindow->getCurrentMouse(), MASK_NONE);
+ }
+ if (mouse_pressed_edges & LLGameControl::AVATAR_MOUSE_BUTTON_RIGHT)
+ {
+ gViewerWindow->handleRightMouseDown(gViewerWindow->getWindow(), gViewerWindow->getCurrentMouse(), MASK_NONE);
+ }
+ if (mouse_released_edges & LLGameControl::AVATAR_MOUSE_BUTTON_RIGHT)
+ {
+ gViewerWindow->handleRightMouseUp(gViewerWindow->getWindow(), gViewerWindow->getCurrentMouse(), MASK_NONE);
+ }
+
+ // actions.mIsRunning is derived purely from how hard the controller's own
+ // movement axes are pushed (see computeAgentActions()'s analog hysteresis).
+ // Only let it drive the agent's running state while the controller is
+ // actually supplying movement this frame -- otherwise an idle-but-connected
+ // controller would fight the keyboard (e.g. clobbering double-tap-to-run)
+ // every frame even though the player is moving with the keyboard instead.
+ constexpr U32 CONTROLLER_MOVEMENT_FLAGS = AGENT_CONTROL_AT_POS | AGENT_CONTROL_AT_NEG
+ | AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_LEFT_NEG;
+ if ((actions.mControlFlags & CONTROLLER_MOVEMENT_FLAGS)
+ && actions.mIsRunning != getRunning())
+ {
+ if (actions.mIsRunning)
+ {
+ setRunning();
+ }
+ else
+ {
+ clearRunning();
+ }
+ sendWalkRun(actions.mIsRunning);
+ }
+
+ mExternalActionFlags = actions.mControlFlags;
+
+ // measure delta time and frame
+ // Note: it is possible for the deltas to be very large
+ // and it is the duty of the code that uses them to clamp as necessary
+ U64 now = LLFrameTimer::getTotalTime();
+ g_deltaTime = F32(now - g_lastUpdateTime) / (F32)(USEC_PER_SEC);
+ g_lastUpdateTime = now;
+
+ S32 frame_count = LLFrameTimer::getFrameCount();
+ g_deltaFrame = frame_count - g_lastUpdateFrame;
+ g_lastUpdateFrame = frame_count;
+
+ if (isUsingFlycam())
+ {
+ // Flycam will be updated later by exernal context
+ return;
+ }
+
+ S32 direction = (S32)(mExternalActionFlags & AGENT_CONTROL_AT_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_AT_NEG) >> 1);
+ if (direction != 0)
+ {
+ moveAt(direction);
+ }
+
+ static U32 last_non_fly_frame = 0;
+ static U64 last_non_fly_time = 0;
+ direction = (S32)(mExternalActionFlags & AGENT_CONTROL_UP_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_UP_NEG) >> 1);
+ if (direction != 0)
+ {
+ // HACK: this auto-fly logic based on original code still extant in llviewerinput.cpp::agent_jump()
+ // but has been cleaned up.
+ // TODO?: DRY this logic
+ if (direction > 0)
+ {
+ if (!getFlying()
+ && !upGrabbed()
+ && gSavedSettings.getBOOL("AutomaticFly"))
+ {
+ constexpr F32 FLY_TIME = 0.5f;
+ constexpr U32 FLY_FRAMES = 4;
+ F32 delta_time = (F32)(now - last_non_fly_time) / (F32)(USEC_PER_SEC);
+ U32 delta_frames = frame_count - last_non_fly_frame;
+ if( delta_time > FLY_TIME
+ && delta_frames > FLY_FRAMES)
+ {
+ setFlying(TRUE);
+ }
+ }
+ }
+ else
+ {
+ last_non_fly_frame = frame_count;
+ last_non_fly_time = now;
+ }
+
+ moveUp(direction);
+ }
+ else if (!getFlying())
+ {
+ last_non_fly_frame = frame_count;
+ last_non_fly_time = now;
+ }
+
+ direction = (S32)(mExternalActionFlags & AGENT_CONTROL_LEFT_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_LEFT_NEG) >> 1);
+ if (direction != 0)
+ {
+ moveLeft(direction);
+ }
+
+ direction = (S32)(mExternalActionFlags & AGENT_CONTROL_YAW_POS)
+ - (S32)((mExternalActionFlags & AGENT_CONTROL_YAW_NEG) >> 1);
+ // The "Slow".."Fast" preferences slider scales Mouselook's turn/look speed
+ // and Avatar's turn speed.
+ F32 turn_speed_factor = 1.0f;
+ F32 look_speed_factor = 1.0f;
+ LLGameControl::AgentControlMode control_mode = LLGameControl::getAgentControlMode();
+ if (control_mode == LLGameControl::CONTROL_MODE_MOUSELOOK)
+ {
+ turn_speed_factor = LLGameControl::getSpeedFactor(LLGameControl::getModeName(control_mode));
+ look_speed_factor = turn_speed_factor;
+ }
+ else if (control_mode == LLGameControl::CONTROL_MODE_AVATAR)
+ {
+ turn_speed_factor = LLGameControl::getSpeedFactor(LLGameControl::getModeName(control_mode));
+ }
+
+ if (direction != 0)
+ {
+ F32 sign = (direction < 0 ? -1.0f : 1.0f);
+ // actions.mYawAmplitude is the analog stick deflection ([-1, 1]) that
+ // set this flag; use its magnitude to modulate turn speed instead of
+ // always snapping to full rate
+ moveYaw(sign * fabs(actions.mYawAmplitude) * turn_speed_factor);
+ }
+
+ {
+ F32 pitch_sign = ((mExternalActionFlags & AGENT_CONTROL_PITCH_POS) > 0 ? 1.0f : 0.0f)
+ - ((mExternalActionFlags & AGENT_CONTROL_PITCH_NEG) > 0 ? 1.0f : 0.0f);
+ // Same analog modulation as yaw above, via actions.mPitchAmplitude.
+ movePitch(pitch_sign * fabs(actions.mPitchAmplitude) * look_speed_factor);
+ }
+
+ // actions.mZoomAmplitude ([-1, 1], from "Zoom +/-"/"Zoom +"/"Zoom -") drives the
+ // camera's field-of-view zoom. Positive amplitude zooms in (narrows the FOV);
+ if (actions.mZoomAmplitude != 0.f)
+ {
+ constexpr F32 FOV_ZOOM_RATE = 1.2f;
+ F32 fov_scale = powf(FOV_ZOOM_RATE, -actions.mZoomAmplitude * g_deltaTime);
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ camera->setDefaultFOV(camera->getDefaultFOV() * fov_scale);
+ gSavedSettings.setF32("CameraAngle", camera->getView());
+ }
+
+ // actions.mScrollAmplitude ([-1, 1], from "Scroll +/-"/"Scroll +"/"Scroll -")
+ // moves the camera toward/away from the avatar the same way the mousewheel does,
+ // so the third-person/follow-cam distance persists once the avatar moves (unlike
+ // the keyboard's camera in/out keys, which unlock the view from the avatar).
+ // Positive amplitude scrolls in (camera moves closer); scrollCamera()'s clicks
+ // are positive-out like the mousewheel's.
+ if (actions.mScrollAmplitude != 0.f)
+ {
+ constexpr F32 SCROLL_CLICKS_PER_SECOND = 8.f;
+ gAgentCamera.scrollCamera(-actions.mScrollAmplitude * SCROLL_CLICKS_PER_SECOND * g_deltaTime);
+ }
+
+ if (mExternalActionFlags & AGENT_CONTROL_STOP)
+ {
+ setControlFlags(AGENT_CONTROL_STOP);
+ }
+
+ // HACK: AGENT_CONTROL_NUDGE_AT_POS is used to toggle running
+ if ((mExternalActionFlags & AGENT_CONTROL_NUDGE_AT_POS) > 0)
+ {
+ if (mToggleRun)
+ {
+ if (getRunning())
+ {
+ clearRunning();
+ sendWalkRun(false);
+ }
+ else
+ {
+ setRunning();
+ sendWalkRun(true);
+ }
+ }
+ mToggleRun = false;
+ }
+ else
+ {
+ mToggleRun = true;
+ }
+
+ if ((mExternalActionFlags & AGENT_CONTROL_SIT_ON_GROUND) > 0
+ && isAgentAvatarValid() && !isSitting() && !getFlying() && !gAgentAvatarp->mInAir)
+ {
+ // "Sit": only sit if currently standing; a no-op otherwise
+ // (already sitting, flying, or airborne).
+ sitDown();
+ }
+ else if ((mExternalActionFlags & AGENT_CONTROL_STAND_UP) > 0 && isSitting())
+ {
+ // "Stand up": only stand if currently sitting.
+ standUp();
+ }
+}
+
+bool LLAgent::isUsingFlycam() const
+{
+ return gAgentCamera.isUsingFlycam();
+}
+
+void LLAgent::toggleFlycam()
+{
+ gAgentCamera.toggleFlycam();
+}
+
+void LLAgent::setFlycamKeyInput(U8 channel, F32 value)
+{
+ gAgentCamera.setFlycamKeyInput(channel, value);
+}
+
+void LLAgent::setFlycamKeyUnroll(bool unroll)
+{
+ gAgentCamera.setFlycamKeyUnroll(unroll);
+}
+
+bool LLAgent::isCameraExternallyDriven() const
+{
+ // Both flycam input sources now share one toggle state on LLAgentCamera --
+ // LLViewerJoystick::getOverrideCamera() forwards to the same flag.
+ return gAgentCamera.isUsingFlycam();
+}
+
+void LLAgent::toggleMouseCursorMode()
+{
+ mUsingMouseCursor = !mUsingMouseCursor;
+ mLastMouseCursorUpdate = 0; // avoid a jump from a stale delta-time baseline
+}
+
+void LLAgent::resetToAvatarMode()
+{
+ if (mUsingMouseCursor)
+ {
+ toggleMouseCursorMode();
+ }
+ if (isUsingFlycam())
+ {
+ toggleFlycam();
+ }
+ if (gAgentCamera.cameraMouselook())
+ {
+ gAgentCamera.changeCameraToDefault();
+ }
+}
+
+void LLAgent::pressGameControlButton(U8 button_index)
+{
+ mGameControlButtonsFromKeys |= (1U << button_index);
+}
+
+void LLAgent::releaseGameControlButton(U8 button_index)
+{
+ mGameControlButtonsFromKeys &= ~(1U << button_index);
+}
+
+void LLAgent::updateFlycam()
+{
+ gAgentCamera.updateFlycam(g_deltaTime);
+}
+
/********************************************************************************/
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index ddaa8dd68c..225453886b 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -33,6 +33,8 @@
#include "llcharacter.h"
#include "llcoordframe.h" // for mFrameAgent
#include "llavatarappearancedefines.h"
+#include "llgamecontrol.h"
+#include "llkeyboard.h"
#include "llpermissionsflags.h"
#include "llevents.h"
#include "v3dmath.h"
@@ -352,6 +354,15 @@ private:
S32 mCurrentFidget;
//--------------------------------------------------------------------
+ // Crouch
+ //--------------------------------------------------------------------
+public:
+ bool isCrouching() const;
+ void toggleCrouch() { mCrouch = !mCrouch; }
+private:
+ bool mCrouch;
+
+ //--------------------------------------------------------------------
// Fly
//--------------------------------------------------------------------
public:
@@ -492,6 +503,25 @@ public:
void resetControlFlags();
bool anyControlGrabbed() const; // True iff a script has taken over a control
bool isControlGrabbed(S32 control_index) const;
+ // Flycam's state now lives on LLAgentCamera (shared with LLViewerJoystick,
+ // which also drives it); these forward there so existing callers don't
+ // need to change.
+ bool isUsingFlycam() const;
+ void toggleFlycam();
+ // True while any flycam-like system (this one, or the legacy NDOF
+ // joystick's own) is driving LLViewerCamera directly, for code that
+ // needs to know the camera isn't under its usual control (e.g. tool
+ // selection, teleport look-at, camera-follow rendering).
+ bool isCameraExternallyDriven() const;
+ bool isUsingMouseCursor() const { return mUsingMouseCursor; }
+ void toggleMouseCursorMode();
+
+ // Drops straight back to plain Avatar mode, unwinding whichever of
+ // Mouselook/FlyCam/Cursor mode is currently active (any combination --
+ // see updateGameControlMode()). Bound to the game-control "ESC" action
+ // in those modes (see AVATAR_ACTION_ESCAPE/FLYCAM_ACTION_ESCAPE).
+ void resetToAvatarMode();
+
// Send message to simulator to force grabbed controls to be
// released, in case of a poorly written script.
void forceReleaseControls();
@@ -499,10 +529,58 @@ public:
private:
S32 mControlsTakenCount[TOTAL_CONTROLS];
S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS];
- U32 mControlFlags; // Replacement for the mFooKey's
+ // mControlFlags is a bitmask of behavior instructions for compact
+ // transmission to the server. It does NOT represent "input", rather
+ // the consequences of it, which will sometimes depend on "state".
+ U32 mControlFlags;
F64 mLastJumpInputTime; // Time of last jump input (key-down) in seconds from LLTimer::getTotalSeconds()
//--------------------------------------------------------------------
+ // GameControls
+ //--------------------------------------------------------------------
+public:
+ // ActionFlags are similar to, but not the same as, ControlFlags!
+ // An 'ActionFlags' bitmask stores 'simplified input' from key/button
+ // presses that correspond to avatar/camera movement actions
+ // whereas 'mControlFlags' are a more complicated set of behavior bits
+ // computed as a function of input and state, and are sent to the server
+ // to steer its character controller for the avatar.
+ //
+ void applyExternalActions(const LLGameControl::AgentActions& actions);
+ void updateFlycam();
+
+ // Auto-derive the active game-control AgentControlMode from current avatar
+ // state (flycam active -> FlyCam, else mouse-cursor mode active -> Mouse, else
+ // mouselook camera -> Mouselook, else sitting -> Captive, else Avatar) and push
+ // it to LLGameControl. Called once per frame before game-control input is
+ // processed so the runtime mapping/gating tracks avatar state automatically.
+ void updateGameControlMode();
+
+ void pressGameControlButton(U8 button);
+ void releaseGameControlButton(U8 button);
+ U32 getGameControlButtonsFromKeys() const { return mGameControlButtonsFromKeys; }
+
+ void setFlycamKeyInput(U8 channel, F32 value);
+ void setFlycamKeyUnroll(bool unroll);
+
+private:
+
+ U32 mExternalActionFlags { 0 };
+ U32 mGameControlButtonsFromKeys { 0 };
+ // Previous frame's LLGameControl::AgentActions::mMouseButtonBits, used by
+ // applyExternalActions() to find the press/release edges of the
+ // level-triggered simulated mouse buttons.
+ U32 mPrevMouseButtonBits { 0 };
+ bool mToggleRun { true };
+
+ // CONTROL_MODE_CURSOR: toggled by AVATAR_ACTION_TOGGLE_MOUSE_CURSOR, same pattern
+ // as LLAgentCamera's flycam toggle. mLastMouseCursorUpdate is the previous frame's
+ // timestamp used to compute the cursor's per-frame movement delta; reset to 0
+ // whenever the mode isn't active so re-entering doesn't jump the cursor.
+ bool mUsingMouseCursor { false };
+ U64 mLastMouseCursorUpdate { 0 };
+
+ //--------------------------------------------------------------------
// Animations
//--------------------------------------------------------------------
public:
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 195ca6cda5..52db5c4415 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -185,7 +185,9 @@ LLAgentCamera::LLAgentCamera() :
mPanLeftKey(0.f),
mPanRightKey(0.f),
mPanInKey(0.f),
- mPanOutKey(0.f)
+ mPanOutKey(0.f),
+ mRollLeftKey(0.f),
+ mRollRightKey(0.f)
{
mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT );
@@ -195,6 +197,7 @@ LLAgentCamera::LLAgentCamera() :
resetPanDiff();
resetOrbitDiff();
+ resetCameraRoll();
}
// Requires gSavedSettings to be initialized.
@@ -331,7 +334,8 @@ void LLAgentCamera::resetView(bool reset_camera, bool change_camera)
//Camera Tool is needed for Free Camera Control Mode
if (!LLFloaterCamera::inFreeCameraMode())
{
- LLFloaterReg::hideInstance("build");
+ if (LLFloaterReg::instanceVisible("build"))
+ LLFloaterReg::hideInstance("build");
// Switch back to basic toolset
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
@@ -355,6 +359,8 @@ void LLAgentCamera::resetView(bool reset_camera, bool change_camera)
setFocusOnAvatar(true, ANIMATE);
mCameraFOVZoomFactor = 0.f;
+
+ resetCameraRoll();
}
resetPanDiff();
resetOrbitDiff();
@@ -905,6 +911,19 @@ void LLAgentCamera::cameraOrbitOver(const F32 angle)
}
}
+//-----------------------------------------------------------------------------
+// cameraRollOver()
+//-----------------------------------------------------------------------------
+void LLAgentCamera::cameraRollOver(const F32 angle)
+{
+ mRollAngle += fmod(angle, F_TWO_PI);
+}
+
+void LLAgentCamera::resetCameraRoll()
+{
+ mRollAngle = 0.f;
+}
+
void LLAgentCamera::resetCameraOrbit()
{
LLVector3 camera_offset_unit(mCameraFocusOffsetTarget);
@@ -918,6 +937,7 @@ void LLAgentCamera::resetCameraOrbit()
cameraZoomIn(1.f);
resetOrbitDiff();
+ resetCameraRoll();
}
void LLAgentCamera::resetOrbitDiff()
@@ -1282,6 +1302,7 @@ void LLAgentCamera::updateCamera()
const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second
const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second
const F32 PAN_RATE = 5.f; // meters per second
+ const F32 ROLL_RATE = 45.f * DEG_TO_RAD; // radians per second
if (gAgentCamera.getOrbitUpKey() || gAgentCamera.getOrbitDownKey())
{
@@ -1323,6 +1344,12 @@ void LLAgentCamera::updateCamera()
cameraPanUp(input_rate * PAN_RATE / gFPSClamped );
}
+ if (getRollLeftKey() || getRollRightKey())
+ {
+ F32 input_rate = getRollRightKey() - getRollLeftKey();
+ cameraRollOver(input_rate * ROLL_RATE / gFPSClamped);
+ }
+
// Clear camera keyboard keys.
gAgentCamera.clearOrbitKeys();
gAgentCamera.clearPanKeys();
@@ -1553,7 +1580,7 @@ void LLAgentCamera::updateCamera()
LLVector3 chest_scale = chest_joint->getScale();
// shorten avatar skeleton to avoid foot interpenetration
-#if 0 // This offsets mouselook attachments, is disabled in other TPVs
+#if 0 // This screws up mouselook attachments
if (!gAgentAvatarp->mInAir)
{
LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation();
@@ -1568,9 +1595,36 @@ void LLAgentCamera::updateCamera()
diff.mV[VZ] = 0.f;
}
#endif
+ static LLCachedControl<bool> useRealisticMouselook(gSavedSettings, "AlchemyRealisticMouselook", false);
+ if (useRealisticMouselook)
+ {
+ auto frame_agent = gAgent.getFrameAgent();
+ LLQuaternion agent_rot(frame_agent.getQuaternion());
+ auto avatarp_parent = (LLViewerObject*)gAgentAvatarp->getParent();
+ if(avatarp_parent)
+ {
+ auto avatarp_root = (LLViewerObject*)gAgentAvatarp->getRoot();
+ if(avatarp_root)
+ {
+ auto decoupled = avatarp_root->flagCameraDecoupled();
+ if(decoupled)
+ {
+ agent_rot *= avatarp_parent->getRenderRotation();
+ }
- // SL-315
- gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff);
+ }
+ }
+
+ LLViewerCamera::getInstance()->updateCameraLocation(head_pos,
+ mCameraUpVector,
+ gAgentAvatarp->mHeadp->getWorldPosition() +
+ LLVector3(1.0, 0.0, 0.0) * agent_rot);
+ }
+ else
+ {
+ // SL-315
+ gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff);
+ }
gAgentAvatarp->mRoot->updateWorldMatrixChildren();
@@ -1597,6 +1651,18 @@ void LLAgentCamera::updateCamera()
torso_joint->setScale(torso_scale);
chest_joint->setScale(chest_scale);
}
+
+ // We have do this at the very end to make sure it takes all previous calculations into
+ // account and then applies our roll on top of it, besides it wouldn't even work otherwise.
+ LLQuaternion rot_quat = LLViewerCamera::instance().getQuaternion();
+ LLMatrix3 rot_mat(mRollAngle, 0.f, 0.f);
+ rot_quat = LLQuaternion(rot_mat)*rot_quat;
+
+ LLMatrix3 mat(rot_quat);
+
+ LLViewerCamera::instance().mXAxis = LLVector3(mat.mMatrix[0]);
+ LLViewerCamera::instance().mYAxis = LLVector3(mat.mMatrix[1]);
+ LLViewerCamera::instance().mZAxis = LLVector3(mat.mMatrix[2]);
}
void LLAgentCamera::updateLastCamera()
@@ -1713,7 +1779,6 @@ LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal()
LLVector3d LLAgentCamera::calcThirdPersonFocusOffset()
{
// ...offset from avatar
- LLVector3d focus_offset;
LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion();
if (isAgentAvatarValid() && gAgentAvatarp->getParent())
{
@@ -2123,14 +2188,67 @@ LLVector3 LLAgentCamera::getAvatarRootPosition()
//-----------------------------------------------------------------------------
void LLAgentCamera::handleScrollWheel(S32 clicks)
{
+ if (isUsingFlycam())
+ {
+ // Flycam preempts updateCamera() entirely (see the comment on
+ // mUsingFlycam in llagentcamera.h), so none of the mCameraMode-based
+ // zoom logic below applies to it; drive the flycam's own FOV-based
+ // "zoom" (LLFlycam::mView, also fed by the FLYCAM_ZOOM game-control
+ // channel in updateFlycam()) instead.
+ // Negative 'clicks' (forward/up scroll) narrows the FOV to zoom in,
+ // matching the sign convention used by the non-flycam paths below.
+ constexpr F32 FLYCAM_SCROLL_ZOOM_FACTOR_PER_CLICK = 0.9f;
+ F32 zoom_factor = (F32)pow(FLYCAM_SCROLL_ZOOM_FACTOR_PER_CLICK, -clicks);
+ mFlycam.setView(mFlycam.getView() * zoom_factor);
+ return;
+ }
+
+ // The Shift/Ctrl offset tweaks are wheel-only; everything else is shared with
+ // gamepad "Scroll" input via scrollCamera().
+ if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON && !mCameraAnimating)
+ {
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ if (!(selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD))
+ {
+ MASK mask = gKeyboard->currentMask(true);
+ if (mask & MASK_SHIFT)
+ {
+ LLVector3d offset = gSavedSettings.getVector3d("FocusOffsetRearView");
+ offset.mdV[VZ] += 0.1f * (F32)clicks;
+ gSavedSettings.setVector3d("FocusOffsetRearView", offset);
+ return;
+ }
+ else if (mask & MASK_CONTROL)
+ {
+ LLVector3 offset = gSavedSettings.getVector3("CameraOffsetRearView");
+ offset.mV[VZ] += 0.1f * (F32)clicks;
+ gSavedSettings.setVector3("CameraOffsetRearView", offset);
+ return;
+ }
+ }
+ }
+
+ scrollCamera((F32)clicks);
+}
+
+void LLAgentCamera::scrollCamera(F32 clicks)
+{
if (mCameraMode == CAMERA_MODE_FOLLOW && getFocusOnAvatar())
{
if (!mFollowCam.getPositionLocked()) // not if the followCam position is locked in place
{
- mFollowCam.zoom(clicks);
- if (mFollowCam.isZoomedToMinimumDistance())
+ // LLFollowCam::zoom() only takes whole clicks (and enforces a minimum
+ // step per call), so accumulate fractional ones until a click is due.
+ mFollowCamScrollClicks += clicks;
+ S32 whole_clicks = (S32)mFollowCamScrollClicks;
+ if (whole_clicks != 0)
{
- changeCameraToMouselook(false);
+ mFollowCamScrollClicks -= (F32)whole_clicks;
+ mFollowCam.zoom(whole_clicks);
+ if (mFollowCam.isZoomedToMinimumDistance())
+ {
+ changeCameraToMouselook(false);
+ }
}
}
}
@@ -2209,7 +2327,7 @@ void LLAgentCamera::resetCamera()
void LLAgentCamera::changeCameraToMouselook(bool animate)
{
if (!gSavedSettings.getBOOL("EnableMouselook")
- || LLViewerJoystick::getInstance()->getOverrideCamera())
+ || gAgent.isCameraExternallyDriven())
{
return;
}
@@ -2244,7 +2362,6 @@ void LLAgentCamera::changeCameraToMouselook(bool animate)
updateLastCamera();
mCameraMode = CAMERA_MODE_MOUSELOOK;
- const U32 old_flags = gAgent.getControlFlags();
gAgent.setControlFlags(AGENT_CONTROL_MOUSELOOK);
if (animate)
@@ -2265,7 +2382,7 @@ void LLAgentCamera::changeCameraToMouselook(bool animate)
//-----------------------------------------------------------------------------
void LLAgentCamera::changeCameraToDefault()
{
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ if (gAgent.isCameraExternallyDriven())
{
return;
}
@@ -2343,7 +2460,7 @@ void LLAgentCamera::changeCameraFromOTS()
//-----------------------------------------------------------------------------
void LLAgentCamera::changeCameraToFollow(bool animate)
{
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ if (gAgent.isCameraExternallyDriven())
{
return;
}
@@ -2399,7 +2516,7 @@ void LLAgentCamera::changeCameraToFollow(bool animate)
//-----------------------------------------------------------------------------
void LLAgentCamera::changeCameraToThirdPerson(bool animate)
{
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ if (gAgent.isCameraExternallyDriven())
{
return;
}
@@ -2470,7 +2587,7 @@ void LLAgentCamera::changeCameraToThirdPerson(bool animate)
//-----------------------------------------------------------------------------
void LLAgentCamera::changeCameraToCustomizeAvatar()
{
- if (LLViewerJoystick::getInstance()->getOverrideCamera() || !isAgentAvatarValid())
+ if (gAgent.isCameraExternallyDriven() || !isAgentAvatarValid())
{
return;
}
@@ -2551,6 +2668,7 @@ void LLAgentCamera::switchCameraPreset(ECameraPreset preset)
resetPanDiff();
resetOrbitDiff();
+ resetCameraRoll();
gSavedSettings.setU32("CameraPresetType", mCameraPreset);
}
@@ -2755,9 +2873,9 @@ void LLAgentCamera::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, con
if (mCameraAnimating)
{
- const F64 ANIM_METERS_PER_SECOND = 20.0;
+ const F64 ANIM_METERS_PER_SECOND = 25.0;
const F64 MIN_ANIM_SECONDS = 0.5;
- const F64 MAX_ANIM_SECONDS = 3.0;
+ const F64 MAX_ANIM_SECONDS = 1.0;
F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND );
anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS );
setAnimationDuration( (F32)anim_duration );
@@ -2968,6 +3086,403 @@ void LLAgentCamera::notifyFollowCamParamsCleared()
mLastValidFollowCamParamsTime = 0.0;
}
+//-----------------------------------------------------------------------------
+// resetFlycamToCurrentView()
+//-----------------------------------------------------------------------------
+void LLAgentCamera::resetFlycamToCurrentView()
+{
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ mFlycam.setTransform(gAgent.getPosGlobalFromAgent(camera->getOrigin()), camera->getQuaternion());
+ mFlycam.setView(camera->getView());
+}
+
+//-----------------------------------------------------------------------------
+// toggleFlycam()
+//-----------------------------------------------------------------------------
+void LLAgentCamera::toggleFlycam()
+{
+ mUsingFlycam = !mUsingFlycam;
+ if (mUsingFlycam)
+ {
+ resetFlycamToCurrentView();
+ // Flycam starts from the current view, which in mouselook is inside the
+ // avatar's head: keep the avatar hidden until it's out of view.
+ mFlycamHidingAvatar = cameraMouselook();
+ }
+ else
+ {
+ bool was_revealed = !mFlycamHidingAvatar;
+ mFlycamHidingAvatar = false;
+ if (was_revealed && cameraMouselook() && isAgentAvatarValid())
+ {
+ // Back to the mouselook view: re-hide the attachments
+ // updateFlycamAvatarVisibility() revealed.
+ gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_MOUSELOOK);
+ }
+ }
+}
+
+void LLAgentCamera::updateFlycamCursorVisibility(LLGameControl::AgentControlMode mode)
+{
+ // Seconds until the cursor hides again after the mouse moves...
+ constexpr F64 FLYCAM_CURSOR_MOUSE_TIMEOUT = 5.0;
+ // ...shortened to at most this while the flycam camera itself is moving.
+ constexpr F64 FLYCAM_CURSOR_CAMERA_TIMEOUT = 1.0;
+ // Tolerance when comparing mouse-move timestamps reconstructed from
+ // LLUI's F32 mouse idle time.
+ constexpr F64 MOUSE_MOVE_EPSILON = 0.005;
+
+ if (!gViewerWindow)
+ {
+ return;
+ }
+
+ // Mouselook (which flycam can be engaged from) manages its own hidden
+ // cursor, so leave the cursor alone while it is active.
+ bool mouselook = cameraMouselook();
+ bool want_hiding = mode == LLGameControl::CONTROL_MODE_FLYCAM
+ && LLGameControl::isFlycamHideCursorEnabled()
+ && !mouselook;
+
+ if (!want_hiding)
+ {
+ if (mFlycamCursorHidden && !mouselook)
+ {
+ gViewerWindow->showCursor();
+ }
+ mFlycamCursorHiding = false;
+ mFlycamCursorHidden = false;
+ return;
+ }
+
+ F64 now = LLFrameTimer::getElapsedSeconds();
+ // LLViewerWindow::handleMouseMove() resets LLUI's mouse idle timer
+ // whenever the mouse moves, so this is when it last moved.
+ F64 mouse_move_time = now - (F64)LLUI::getInstance()->getMouseIdleTime();
+
+ // Detect flycam camera motion by comparing its transform (global, so
+ // unaffected by region-origin rebases) and view angle against the
+ // previous frame's.
+ LLVector3d flycam_position;
+ LLQuaternion flycam_rotation;
+ mFlycam.getTransform(flycam_position, flycam_rotation);
+ F32 flycam_view = mFlycam.getView();
+ bool flycam_moved = flycam_position != mFlycamCursorLastPosition
+ || flycam_rotation != mFlycamCursorLastRotation
+ || flycam_view != mFlycamCursorLastView;
+ mFlycamCursorLastPosition = flycam_position;
+ mFlycamCursorLastRotation = flycam_rotation;
+ mFlycamCursorLastView = flycam_view;
+
+ if (!mFlycamCursorHiding)
+ {
+ // Just entered FlyCam mode: hide immediately.
+ mFlycamCursorHiding = true;
+ mFlycamCursorHidden = true;
+ mFlycamCursorMouseMoveTime = mouse_move_time;
+ gViewerWindow->hideCursor();
+ return;
+ }
+
+ if (mFlycamCursorHidden && !gViewerWindow->getCursorHidden())
+ {
+ // Something else re-showed the cursor behind our back: treat it as
+ // visible, with a fresh timeout.
+ mFlycamCursorHidden = false;
+ mFlycamCursorHideTime = now + FLYCAM_CURSOR_MOUSE_TIMEOUT;
+ }
+
+ if (mouse_move_time > mFlycamCursorMouseMoveTime + MOUSE_MOVE_EPSILON)
+ {
+ // The mouse moved: show the cursor (if hidden) and restart the timeout.
+ mFlycamCursorMouseMoveTime = mouse_move_time;
+ mFlycamCursorHideTime = mouse_move_time + FLYCAM_CURSOR_MOUSE_TIMEOUT;
+ if (mFlycamCursorHidden)
+ {
+ mFlycamCursorHidden = false;
+ gViewerWindow->showCursor();
+ }
+ }
+
+ if (mFlycamCursorHidden)
+ {
+ return;
+ }
+
+ if (flycam_moved)
+ {
+ mFlycamCursorHideTime = llmin(mFlycamCursorHideTime, now + FLYCAM_CURSOR_CAMERA_TIMEOUT);
+ }
+
+ if (now >= mFlycamCursorHideTime)
+ {
+ mFlycamCursorHidden = true;
+ gViewerWindow->hideCursor();
+ }
+}
+
+bool LLAgentCamera::isHidingAvatarForFirstPerson() const
+{
+ return cameraMouselook() && (!mUsingFlycam || mFlycamHidingAvatar);
+}
+
+//-----------------------------------------------------------------------------
+// updateFlycamAvatarVisibility()
+//-----------------------------------------------------------------------------
+void LLAgentCamera::updateFlycamAvatarVisibility()
+{
+ if (!mFlycamHidingAvatar)
+ {
+ return;
+ }
+ if (!cameraMouselook() || !isAgentAvatarValid())
+ {
+ // Nothing left to hide from (e.g. the camera mode changed underneath).
+ mFlycamHidingAvatar = false;
+ return;
+ }
+
+ // Bounding sphere of the avatar, including its attachments.
+ LLVector3 center = gAgentAvatarp->getRenderPosition();
+ F32 radius = 0.f;
+ if (gAgentAvatarp->mDrawable.notNull())
+ {
+ const LLVector4a* extents = gAgentAvatarp->mDrawable->getSpatialExtents();
+ LLVector3 min(extents[0].getF32ptr());
+ LLVector3 max(extents[1].getF32ptr());
+ center = (min + max) * 0.5f;
+ radius = (max - min).magVec() * 0.5f;
+ }
+ // Pad for stale extents and animation beyond the bounds.
+ constexpr F32 MIN_AVATAR_RADIUS = 1.f; // meters
+ constexpr F32 AVATAR_RADIUS_PADDING = 1.25f;
+ radius = llmax(radius * AVATAR_RADIUS_PADDING, MIN_AVATAR_RADIUS);
+
+ // Conservative test: the avatar is out of view if its bounding sphere lies
+ // entirely outside the cone that encloses the view frustum (half-angle to
+ // the frustum's corners).
+ const LLViewerCamera* camera = LLViewerCamera::getInstance();
+ LLVector3 to_avatar = center - camera->getOrigin();
+ F32 distance = to_avatar.normVec();
+ if (distance <= radius)
+ {
+ return; // camera is inside the bounds
+ }
+ F32 tan_half_view = tanf(0.5f * camera->getView());
+ F32 frustum_half_angle = atanf(tan_half_view * sqrtf(1.f + camera->getAspect() * camera->getAspect()));
+ F32 avatar_half_angle = asinf(radius / distance);
+ F32 angle_to_avatar = acosf(llclamp(to_avatar * camera->getAtAxis(), -1.f, 1.f));
+ if (angle_to_avatar > frustum_half_angle + avatar_half_angle)
+ {
+ mFlycamHidingAvatar = false;
+ gAgentAvatarp->updateAttachmentVisibility(getCameraMode());
+ }
+}
+
+//-----------------------------------------------------------------------------
+// applyNdofFlycamFrameDelta()
+//-----------------------------------------------------------------------------
+void LLAgentCamera::applyNdofFlycamFrameDelta(const F32 local_delta[7],
+ bool auto_level, F32 auto_level_fraction,
+ bool direct_view, F32 direct_view_value)
+{
+ mFlycam.applyFrameDelta(local_delta, auto_level, auto_level_fraction, direct_view, direct_view_value);
+
+ LLVector3d pos_global;
+ LLQuaternion rot;
+ mFlycam.getTransform(pos_global, rot);
+ LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
+ LLMatrix3 mat(rot);
+ LLViewerCamera::getInstance()->setOrigin(pos);
+ LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
+ LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
+ LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
+
+ LLViewerCamera::getInstance()->setView(mFlycam.getView());
+
+ updateFlycamAvatarVisibility();
+}
+
+//-----------------------------------------------------------------------------
+// updateFlycam()
+//-----------------------------------------------------------------------------
+void LLAgentCamera::updateFlycam(F32 delta_time)
+{
+ // Note: flycam_inputs arrive in range [-1,1]
+ std::vector<F32> flycam_inputs;
+ U32 flycam_misc_actions = 0;
+ U32 flycam_modifiers = 0;
+ LLGameControl::getFlycamInputs(flycam_inputs, flycam_misc_actions, flycam_modifiers);
+
+ // The channel order is defined by LLGameControl::FlycamChannel.
+
+ // Defensive: getFlycamInputs() should return one value per channel.
+ if ((S32)flycam_inputs.size() < LLGameControl::FLYCAM_NUM_CHANNELS)
+ {
+ return;
+ }
+
+ if (flycam_misc_actions & LLGameControl::FLYCAM_ACTION_ESCAPE)
+ {
+ // Bail out of FlyCam mode immediately; no point applying this frame's
+ // (about to be abandoned) flycam deltas below.
+ gAgent.resetToAvatarMode();
+ return;
+ }
+
+ // Blend in keyboard-driven flycam input (independent of LLGameControl,
+ // which only sees a physical controller). mFlycamKeyboardInput is
+ // level-triggered by flycam_axis_key<> in llviewerinput.cpp -- it must be
+ // re-set every frame a key is held, so clear it here once consumed.
+ for (U8 i = 0; i < LLGameControl::FLYCAM_NUM_CHANNELS; ++i)
+ {
+ flycam_inputs[i] = llclamp(flycam_inputs[i] + mFlycamKeyboardInput[i], -1.f, 1.f);
+ }
+ mFlycamKeyboardInput.fill(0.f);
+ bool flycam_key_unroll_requested = mFlycamKeyboardUnrollRequested;
+ mFlycamKeyboardUnrollRequested = false;
+
+ // Unroll only undoes roll, and roll is already kept at zero every frame
+ // (LLFlycam::setRollRate()/integrate()) whenever roll is disallowed, so
+ // treat an Unroll request as a no-op rather than kicking off a pointless
+ // startReset() lerp while "Allow Roll" is unchecked.
+ if (LLGameControl::isFlycamRollAllowed()
+ && ((flycam_misc_actions & LLGameControl::FLYCAM_ACTION_UNROLL) || flycam_key_unroll_requested))
+ {
+ // Re-orient the flycam in place: keep its current position and
+ // forward (local X) axis unchanged, but unroll it so its local vertical
+ // axis lies on the plane defined by forward axis and world-up, with positive
+ // dot-product with world-up.
+ // mFlycam.startReset() smoothly lerps into this transform (see
+ // LLFlycam::integrate()); flycam input has no effect until the lerp
+ // completes.
+ constexpr F32 FLYCAM_UNROLL_DURATION = 1.0f; // seconds; may be tuned later
+
+ LLVector3d current_position;
+ LLQuaternion current_rotation;
+ mFlycam.getTransform(current_position, current_rotation);
+
+ LLMatrix3 level(current_rotation);
+ LLVector3 forward(level.getFwdRow());
+ forward.normVec();
+
+ LLVector3 world_up = LLVector3::z_axis;
+ LLVector3 new_up = world_up - (world_up * forward) * forward;
+ constexpr F32 MIN_UNROLL_SIN = 0.01f; // ~0.6 degrees off vertical
+ if (new_up.lengthSquared() > MIN_UNROLL_SIN * MIN_UNROLL_SIN)
+ {
+ new_up.normVec();
+ // Right-handed (forward, left, up) basis, per
+ // LLMatrix3::orthogonalize()'s up = forward % left: up % forward == left.
+ LLVector3 new_left = new_up % forward;
+ level.setRows(forward, new_left, new_up);
+ level.orthogonalize(); // numerical cleanup only; rows are already orthonormal by construction
+
+ mFlycam.startReset(current_position, LLQuaternion(level), FLYCAM_UNROLL_DURATION);
+ }
+ }
+
+ // Orbit modifier: while held, Truck stops meaning strafe and instead adds
+ // into Pan's yaw (both sweep the camera left/right around the focal
+ // point), and Dolly stops meaning advance and instead adjusts the radius
+ // (see LLFlycam::setOrbitRadialRate()/integrate()). Tilt, Roll, Boom,
+ // and Zoom keep their normal meaning either way: Tilt already rotates the
+ // camera about its own local left axis, which is exactly what swings it
+ // up/down around the focal point once position is derived from
+ // orientation; Roll still passes straight through (it just changes which
+ // region-frame axis Tilt's local axis happens to be next frame).
+ bool flycam_orbit_held = (flycam_modifiers & LLGameControl::FLYCAM_MODIFIER_ORBIT) != 0;
+ constexpr F32 FLYCAM_ORBIT_DEFAULT_FOCAL_DISTANCE = 20.0f; // meters; hard-coded for now, may be tuned later
+ constexpr F32 FLYCAM_ORBIT_MAX_TRACE_DISTANCE = 512.0f; // meters; matches the general world-raycast convention used elsewhere (e.g. LLViewerWindow::cursorIntersect)
+ F32 flycam_orbit_focal_distance = FLYCAM_ORBIT_DEFAULT_FOCAL_DISTANCE;
+ if (flycam_orbit_held && !mFlycam.isOrbitEngaged())
+ {
+ // Rising edge: ray-trace forward from the flycam to see what it's
+ // pointing at, so Orbit pivots around that instead of an arbitrary
+ // fixed distance whenever there's something in view; falls back to
+ // the default distance if nothing is hit within range.
+ LLVector3d camera_pos_global;
+ LLQuaternion camera_rot;
+ mFlycam.getTransform(camera_pos_global, camera_rot);
+ LLVector3 camera_pos = gAgent.getPosAgentFromGlobal(camera_pos_global);
+ LLVector3 forward(LLMatrix3(camera_rot).getFwdRow());
+ LLVector3 trace_end = camera_pos + forward * FLYCAM_ORBIT_MAX_TRACE_DISTANCE;
+
+ LLVector4a start, end;
+ start.load3(camera_pos.mV);
+ end.load3(trace_end.mV);
+
+ LLVector4a intersection;
+ S32 face_hit = -1;
+ LLViewerObject* hit_object = gPipeline.lineSegmentIntersectInWorld(
+ start, end,
+ /*pick_transparent=*/ false,
+ /*pick_rigged=*/ true,
+ /*pick_unselectable=*/ true,
+ /*pick_reflection_probe=*/ false,
+ &face_hit, nullptr, nullptr,
+ &intersection);
+ if (hit_object)
+ {
+ LLVector3 hit_pos;
+ hit_pos.set(intersection.getF32ptr());
+ flycam_orbit_focal_distance = (hit_pos - camera_pos).length();
+ }
+ }
+ mFlycam.setOrbitEngaged(flycam_orbit_held, flycam_orbit_focal_distance);
+
+ F32 yaw_input = flycam_inputs[LLGameControl::FLYCAM_PAN];
+ F32 truck_input = flycam_inputs[LLGameControl::FLYCAM_TRUCK];
+ F32 dolly_input = flycam_inputs[LLGameControl::FLYCAM_DOLLY];
+ if (flycam_orbit_held)
+ {
+ // Truck/Dolly are negated here (Pan/Tilt/Roll/Boom/Zoom are not) --
+ // determined empirically to match the expected orbit sweep/radial
+ // directions.
+ truck_input = -truck_input;
+ dolly_input = -dolly_input;
+ yaw_input = llclamp(yaw_input + truck_input, -1.f, 1.f);
+ truck_input = 0.f;
+ mFlycam.setOrbitRadialRate(dolly_input);
+ dolly_input = 0.f;
+ }
+ else
+ {
+ mFlycam.setOrbitRadialRate(0.f);
+ }
+
+ // Must precede setLinearVelocity()/setPitchRate()/setYawRate()/setRollRate():
+ // those setters apply mSpeedFactor/mAllowRoll immediately rather than at
+ // integrate() time.
+ mFlycam.setSpeedFactor(LLGameControl::getSpeedFactor(LLGameControl::getModeName(LLGameControl::CONTROL_MODE_FLYCAM)));
+ mFlycam.setAllowRoll(LLGameControl::isFlycamRollAllowed());
+
+ LLVector3 linear_velocity(dolly_input, truck_input, flycam_inputs[LLGameControl::FLYCAM_BOOM]);
+ constexpr F32 MAX_FLYCAM_SPEED = 10.0f;
+ mFlycam.setLinearVelocity(MAX_FLYCAM_SPEED * linear_velocity);
+
+ mFlycam.setPitchRate(flycam_inputs[LLGameControl::FLYCAM_TILT]);
+ mFlycam.setYawRate(yaw_input);
+ mFlycam.setRollRate(flycam_inputs[LLGameControl::FLYCAM_ROLL]);
+ mFlycam.setZoomRate(flycam_inputs[LLGameControl::FLYCAM_ZOOM]);
+
+ mFlycam.integrate(delta_time);
+
+ LLVector3d pos_global;
+ LLQuaternion rot;
+ mFlycam.getTransform(pos_global, rot);
+ LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
+ LLMatrix3 mat(rot);
+ LLViewerCamera::getInstance()->setOrigin(pos);
+ LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
+ LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
+ LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
+
+ LLViewerCamera::getInstance()->setView(mFlycam.getView());
+
+ updateFlycamAvatarVisibility();
+}
+
bool LLAgentCamera::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position)
{
// disallow pointing at attachments and avatars
@@ -3030,6 +3545,8 @@ void LLAgentCamera::clearOrbitKeys()
mOrbitDownKey = 0.f;
mOrbitInKey = 0.f;
mOrbitOutKey = 0.f;
+ mRollLeftKey = 0.f;
+ mRollRightKey = 0.f;
}
void LLAgentCamera::clearPanKeys()
diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h
index 8b7a69deff..5ed12b5b24 100644
--- a/indra/newview/llagentcamera.h
+++ b/indra/newview/llagentcamera.h
@@ -27,7 +27,11 @@
#ifndef LL_LLAGENTCAMERA_H
#define LL_LLAGENTCAMERA_H
+#include <array>
+
+#include "llflycam.h"
#include "llfollowcam.h" // Ventrella
+#include "llgamecontrol.h" // LLGameControl::FLYCAM_NUM_CHANNELS
#include "llhudeffectlookat.h" // EPointAtType
#include "llhudeffectpointat.h" // ELookAtType
@@ -179,6 +183,94 @@ public:
void notifyFollowCamParamsCleared();
private:
LLFollowCam mFollowCam; // Ventrella
+ // Fractional scrollCamera() clicks not yet applied to mFollowCam, whose
+ // zoom() only takes whole clicks.
+ F32 mFollowCamScrollClicks { 0.f };
+
+ //--------------------------------------------------------------------
+ // Flycam
+ //--------------------------------------------------------------------
+ // Free-flying camera engine (mFlycam + toggle state below), shared by two
+ // independent input sources that each feed it differently:
+ // - game-control/keyboard: updateFlycam() + mFlycamKeyboard* state here.
+ // - legacy NDOF joystick: applyNdofFlycamFrameDelta() below, called
+ // from LLViewerJoystick, whose OWN per-axis tuning state
+ // (mJoystickFlycamDelta/mJoystickFlycamLastDelta) lives over there,
+ // not on this class.
+ // Orthogonal to mCameraMode above: while active it preempts
+ // updateCamera() entirely (driven by updateFlycam()/
+ // applyNdofFlycamFrameDelta() instead, called directly from the main
+ // loop), rather than being a peer state in that mode's own
+ // animated-transition machinery.
+public:
+ bool isUsingFlycam() const { return mUsingFlycam; }
+ void toggleFlycam();
+
+ // Game-control/keyboard-driven update -- see LLViewerJoystick::moveFlycam()
+ // for the other (legacy NDOF joystick) input source, below.
+ void updateFlycam(F32 delta_time);
+ void setFlycamKeyInput(U8 channel, F32 value) { mFlycamKeyboardInput[channel] = value; }
+ void setFlycamKeyUnroll(bool unroll) { mFlycamKeyboardUnrollRequested = unroll; }
+ // Snapshots the live LLViewerCamera transform into the flycam. Used both
+ // when entering flycam (see toggleFlycam()) and whenever an input source
+ // (e.g. the NDOF joystick regaining focus) needs to recalibrate its own
+ // axis-delta state against the camera's current position/orientation.
+ void resetFlycamToCurrentView();
+
+ // Entry point for input sources (the legacy NDOF joystick) that compute
+ // their own per-axis dead-zone/scale/feathering deltas and only need this
+ // class to own the resulting transform update + push to LLViewerCamera --
+ // see LLFlycam::applyFrameDelta() for the delta format.
+ void applyNdofFlycamFrameDelta(const F32 local_delta[7],
+ bool auto_level, F32 auto_level_fraction,
+ bool direct_view, F32 direct_view_value);
+
+ // True when the self avatar should be hidden for a first-person view: in
+ // mouselook, unless flycam has since taken the camera out of the head (see
+ // mFlycamHidingAvatar). Use this rather than cameraMouselook() when deciding
+ // whether to render the self avatar.
+ bool isHidingAvatarForFirstPerson() const;
+
+ // Hides the mouse cursor while in CONTROL_MODE_FLYCAM (when enabled by
+ // LLGameControl::isFlycamHideCursorEnabled()). The cursor reappears while
+ // the mouse itself moves and hides again when its timeout expires: the
+ // timeout is reset to 5 seconds whenever the mouse moves and cut to at most
+ // 1 second whenever the flycam camera moves. Restored on leaving the mode.
+ void updateFlycamCursorVisibility(LLGameControl::AgentControlMode mode);
+private:
+ // Clears mFlycamHidingAvatar once the self avatar is completely out of the
+ // flycam's view, so it doesn't pop into existence on screen. Called after
+ // each flycam transform update.
+ void updateFlycamAvatarVisibility();
+
+ LLFlycam mFlycam;
+ bool mUsingFlycam { false };
+ // Set when flycam is entered from mouselook: the camera starts inside the
+ // avatar's head, so the avatar stays hidden (as in mouselook) until
+ // updateFlycamAvatarVisibility() finds it out of view.
+ bool mFlycamHidingAvatar { false };
+
+ // Keyboard's contribution to the shared/game-control flycam channels
+ // (blended with LLGameControl::getFlycamInputs() each frame in
+ // updateFlycam()) -- unrelated to the legacy joystick's own tuning state,
+ // which lives on LLViewerJoystick (mJoystickFlycamDelta/LastDelta).
+ std::array<F32, LLGameControl::FLYCAM_NUM_CHANNELS> mFlycamKeyboardInput {};
+ bool mFlycamKeyboardUnrollRequested { false };
+
+ // updateFlycamCursorVisibility() state: mFlycamCursorHiding is true while
+ // FlyCam cursor hiding is in effect, mFlycamCursorHidden while the cursor is
+ // actually hidden by it. Times are LLFrameTimer::getElapsedSeconds():
+ // mFlycamCursorMouseMoveTime is the last mouse move seen, and
+ // mFlycamCursorHideTime is when a visible cursor hides again. The
+ // mFlycamCursorLast* values are the previous frame's flycam transform and
+ // view angle, used to detect flycam motion.
+ bool mFlycamCursorHiding { false };
+ bool mFlycamCursorHidden { false };
+ F64 mFlycamCursorMouseMoveTime { 0.0 };
+ F64 mFlycamCursorHideTime { 0.0 };
+ LLVector3d mFlycamCursorLastPosition;
+ LLQuaternion mFlycamCursorLastRotation;
+ F32 mFlycamCursorLastView { 0.f };
//--------------------------------------------------------------------
// Sit
@@ -275,13 +367,19 @@ public:
void cameraOrbitAround(const F32 radians); // Rotate camera CCW radians about build focus point
void cameraOrbitOver(const F32 radians); // Rotate camera forward radians over build focus point
void cameraOrbitIn(const F32 meters); // Move camera in toward build focus point
+ void cameraRollOver(const F32 radians); // Roll the camera
void resetCameraOrbit();
void resetOrbitDiff();
+ void resetCameraRoll();
//--------------------------------------------------------------------
// Zoom
//--------------------------------------------------------------------
public:
void handleScrollWheel(S32 clicks); // Mousewheel driven zoom
+ // Mousewheel-equivalent camera distance change, minus the wheel-only Shift/Ctrl
+ // offset tweaks; 'clicks' may be fractional (e.g. per-frame gamepad "Scroll"
+ // input). Positive moves the camera out, same sign as handleScrollWheel().
+ void scrollCamera(F32 clicks);
void cameraZoomIn(const F32 factor); // Zoom in by fraction of current distance
F32 getCameraZoomFraction(bool get_third_person = false); // Get camera zoom as fraction of minimum and maximum zoom
void setCameraZoomFraction(F32 fraction); // Set camera zoom as fraction of minimum and maximum zoom
@@ -369,6 +467,8 @@ public:
F32 getOrbitDownKey() const { return mOrbitDownKey; }
F32 getOrbitInKey() const { return mOrbitInKey; }
F32 getOrbitOutKey() const { return mOrbitOutKey; }
+ F32 getRollLeftKey() const { return mRollLeftKey; }
+ F32 getRollRightKey() const { return mRollRightKey; }
void setOrbitLeftKey(F32 mag) { mOrbitLeftKey = mag; }
void setOrbitRightKey(F32 mag) { mOrbitRightKey = mag; }
@@ -376,6 +476,8 @@ public:
void setOrbitDownKey(F32 mag) { mOrbitDownKey = mag; }
void setOrbitInKey(F32 mag) { mOrbitInKey = mag; }
void setOrbitOutKey(F32 mag) { mOrbitOutKey = mag; }
+ void setRollLeftKey(F32 mag) { mRollLeftKey = mag; }
+ void setRollRightKey(F32 mag) { mRollRightKey = mag; }
void clearOrbitKeys();
private:
@@ -389,6 +491,10 @@ private:
F32 mOrbitAroundRadians;
F32 mOrbitOverAngle;
+ F32 mRollLeftKey;
+ F32 mRollRightKey;
+ F32 mRollAngle = 0.f;
+
//--------------------------------------------------------------------
// Pan
//--------------------------------------------------------------------
@@ -421,7 +527,9 @@ private:
/** Keys
** **
*******************************************************************************/
-
+public:
+ void storeCameraPosition();
+ void loadCameraPosition();
};
extern LLAgentCamera gAgentCamera;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 5000110fff..64307e697f 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -46,6 +46,7 @@
#include "llagentwearables.h"
#include "lldirpicker.h"
#include "llfloaterimcontainer.h"
+#include "llfloaterpreference.h"
#include "llimprocessing.h"
#include "llwindow.h"
#include "llviewerstats.h"
@@ -55,6 +56,7 @@
#include "llmarketplacenotifications.h"
#include "llmd5.h"
#include "llmeshrepository.h"
+#include "llpanelpreferencegamecontrol.h"
#include "llpumpio.h"
#include "llmimetypes.h"
#include "llslurl.h"
@@ -62,6 +64,7 @@
#include "llfocusmgr.h"
#include "llurlfloaterdispatchhandler.h"
#include "llviewerjoystick.h"
+#include "llgamecontrol.h"
#include "llcalc.h"
#include "llconversationlog.h"
#if LL_WINDOWS
@@ -198,6 +201,7 @@
#include "lldebugview.h"
#include "llconsole.h"
#include "llcontainerview.h"
+#include "lltoolfocus.h"
#include "lltooltip.h"
#include "llsdutil.h"
@@ -224,6 +228,7 @@
#include "llvosurfacepatch.h"
#include "llviewerfloaterreg.h"
#include "llcommandlineparser.h"
+#include "llfloaterpreference.h"
#include "llfloatermemleak.h"
#include "llfloaterreg.h"
#include "llfloatersimplesnapshot.h"
@@ -1163,6 +1168,31 @@ bool LLAppViewer::init()
LLViewerJoystick::getInstance()->init(false);
}
+ LLGameControl::init(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "gamecontrollerdb.txt"),
+ [](const std::vector<std::string>& keys) -> LLSD
+ {
+ LLSD result = LLSD::emptyMap();
+ for (const std::string& key : keys)
+ {
+ if (gSavedSettings.controlExists(key))
+ {
+ result[key] = gSavedSettings.getLLSD(key);
+ }
+ }
+ return result;
+ },
+ [](const LLSD& key_values)
+ {
+ for (auto it = key_values.beginMap(); it != key_values.endMap(); ++it)
+ {
+ if (gSavedSettings.controlExists(it->first))
+ {
+ gSavedSettings.setLLSD(it->first, it->second);
+ }
+ }
+ },
+ []() { LLPanelPreferenceGameControl::updateDeviceList(); });
+
try
{
initializeSecHandler();
@@ -1272,6 +1302,7 @@ bool LLAppViewer::init()
LLWorld::createInstance();
LLViewerStatsRecorder::createInstance();
LLSelectMgr::createInstance();
+ LLToolCamera::createInstance();
LLViewerCamera::createInstance();
LL::GLTFSceneManager::createInstance();
@@ -1359,6 +1390,66 @@ bool LLAppViewer::frame()
return ret;
}
+void sendGameControlData()
+{
+ LLMessageSystem* msg = gMessageSystem;
+ const LLGameControl::ServerState& state = LLGameControl::getServerState();
+
+ msg->newMessageFast(_PREHASH_GameControlData);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
+ msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
+ msg->addU8Fast(_PREHASH_Packet, LLGameControl::getNextPacketNum());
+ msg->addU8Fast(_PREHASH_ActionMode, state.mActionMode);
+
+ // Non-modal canonical axes/buttons: pack every available value every message,
+ // whether or not it changed since the last one (no per-field diffing). Trailing
+ // zero axes are truncated and the Buttons block is skipped entirely when zero --
+ // the server assumes anything not packed is zero -- to save bytes.
+ size_t num_axes = state.mAxes.size();
+ while (num_axes > 0 && state.mAxes[num_axes - 1] == 0)
+ {
+ --num_axes;
+ }
+ for (size_t i = 0; i < num_axes; ++i)
+ {
+ msg->nextBlockFast(_PREHASH_Axes);
+ msg->addS16Fast(_PREHASH_Value, state.mAxes[i]);
+ }
+ if (state.mButtons != 0)
+ {
+ msg->nextBlockFast(_PREHASH_Buttons);
+ msg->addU32Fast(_PREHASH_Flags, state.mButtons);
+ }
+
+ // Modal semantic axes/buttons: same truncation policy, except the number of
+ // axes considered depends on ActionMode -- see message_template.msg's
+ // GameControlData doc and LLGameControl::numSemanticAxesForMode() -- since the
+ // server computes its own expected axis count from the mode and zeros anything
+ // not packed.
+ size_t num_mode_axes = LLGameControl::numSemanticAxesForMode((LLGameControl::AgentControlMode)state.mActionMode);
+ while (num_mode_axes > 0 && state.mSemanticAxes[num_mode_axes - 1] == 0)
+ {
+ --num_mode_axes;
+ }
+ for (size_t i = 0; i < num_mode_axes; ++i)
+ {
+ msg->nextBlockFast(_PREHASH_ModeAxes);
+ msg->addS16Fast(_PREHASH_Value, state.mSemanticAxes[i]);
+ }
+ if (state.mSemanticButtons != 0)
+ {
+ msg->nextBlockFast(_PREHASH_ModeButtons);
+ msg->addU32Fast(_PREHASH_Flags, state.mSemanticButtons);
+ }
+
+ LLGameControl::updateResendPeriod();
+ gAgent.sendMessage();
+
+ // Mirror the just-sent channel values into the preferences "Data Output" tab.
+ LLPanelPreferenceGameControl::updateDataOutput();
+}
+
bool LLAppViewer::doFrame()
{
// SIGTERM asks for a normal logout. Quitting immediately skips
@@ -1445,7 +1536,7 @@ bool LLAppViewer::doFrame()
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
}
- gViewerWindow->getWindow()->gatherInput();
+ gViewerWindow->getWindow()->gatherInput(gFocusMgr.getAppHasFocus());
}
//memory leaking simulation
@@ -2149,6 +2240,8 @@ bool LLAppViewer::cleanup()
LLViewerJoystick::getInstance()->terminate();
}
+ LLGameControl::terminate();
+
LL_INFOS() << "Shutting down message system" << LL_ENDL;
end_messaging_system();
@@ -4927,6 +5020,7 @@ void LLAppViewer::loadKeyBindings()
}
}
LLUrlRegistry::instance().setKeybindingHandler(&gViewerInput);
+ LLUrlRegistry::instance().setGameControllerHandler(LLGameControl::getInstance());
}
// As per GHI #4498, remove old, stale CEF cache folders from previous sessions
@@ -5399,6 +5493,68 @@ void LLAppViewer::idle()
gAgent.autoPilot(&yaw);
}
+ // Auto-derive the active game-control mode (Avatar/Captive/FlyCam) from
+ // current avatar state so the runtime mappings and gating track it.
+ gAgent.updateGameControlMode();
+
+ // Read the agent's control flags now, before applyExternalActions() below
+ // (which drives the avatar from a real game controller) has a chance to
+ // fold any controller-driven movement into them this frame -- so the
+ // keyboard-derived GameControl state computed here can never be sourced
+ // from the controller's own output. See LLGameControllerManager::
+ // setExternalInput()/accumulateFinalState() for where the two are
+ // combined (only as fully-independent final ServerStates).
+ U32 control_flags = gAgent.getControlFlags();
+
+ // apply to GameControl
+ LLGameControl::setExternalInput(control_flags, gAgent.getGameControlButtonsFromKeys(), gAgent.getRunning());
+
+ // Feed the actual on-screen cursor position to GameControl
+ // Matches the same whole-window clamp LLViewerWindow::moveCursorTo()
+ // uses to keep a gamepad-driven cursor on-screen.
+ if (LLGameControl::getAgentControlMode() == LLGameControl::CONTROL_MODE_CURSOR)
+ {
+ LLCoordGL cursor_pos = gViewerWindow->getCurrentMouse();
+ S32 rect_width = gViewerWindow->getWindowWidthScaled();
+ S32 rect_height = gViewerWindow->getWindowHeightScaled();
+ S32 pixel_x = llclamp(cursor_pos.mX, 0, rect_width);
+ S32 pixel_y = llclamp(rect_height - cursor_pos.mY, 0, rect_height);
+ LLGameControl::setMouseCursorPosition(pixel_x, pixel_y, rect_width, rect_height);
+ }
+
+ if (LLPanelPreferenceGameControl::isWaitingForInputChannel())
+ {
+ LLPanelPreferenceGameControl::applyGameControlInput();
+ }
+ else
+ {
+ // Recompute canonical controller state (also populates the internal
+ // state consumed below) and send it to the server when it changed,
+ // but only if the agent's region advertises support for it (the
+ // "GameControlEnabled" simulator feature). While unsupported the
+ // resend deadline is left untouched, so the first frame after the
+ // feature appears sends immediately.
+ if (LLGameControl::computeFinalStateAndCheckForChanges())
+ {
+ LLViewerRegion* regionp = gAgent.getRegion();
+ if (regionp && regionp->gameControlEnabled())
+ {
+ sendGameControlData();
+ }
+ }
+
+ // Drive the local avatar from the controller. In Avatar/Captive
+ // modes this moves the avatar; in FlyCam mode applyExternalActions
+ // ignores movement bits (it early-returns while flycam is active) but
+ // still services the flycam on/off toggle, so we run it either way.
+ // Flycam *motion* is driven separately below via gAgent.updateFlycam().
+ if (LLGameControl::willControlAvatar() || LLGameControl::willControlFlycam())
+ {
+ LLGameControl::AgentActions game_control_actions = LLGameControl::computeAgentActions();
+ gAgent.applyExternalActions(game_control_actions);
+ }
+ }
+
send_agent_update(false);
// After calling send_agent_update() in the mainloop we always clear
@@ -5666,9 +5822,14 @@ void LLAppViewer::idle()
{
gAgentPilot.moveCamera();
}
- else if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ else if (gAgent.isUsingFlycam())
{
+ // Flycam is now a single shared state (LLAgentCamera) driven by
+ // whichever input sources are actually present; each is a no-op
+ // when its device/mode isn't active, so it's safe to feed both
+ // every frame rather than picking one exclusively.
LLViewerJoystick::getInstance()->moveFlycam();
+ gAgent.updateFlycam();
}
else
{
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index e7017655c2..71f266019d 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -37,6 +37,7 @@
#include "llmd5.h"
#include "llfindlocale.h"
#include "llversioninfo.h"
+#include "llfocusmgr.h"
#include <exception>
@@ -262,7 +263,7 @@ SDL_AppResult SDL_AppIterate(void *appstate)
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
- return LLWindowSDL::handleEvents(*event);
+ return LLWindowSDL::handleEvents(*event, gFocusMgr.getAppHasFocus());
}
void SDL_AppQuit(void *appstate, SDL_AppResult result)
diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp
index 871f924316..00e6aee234 100644
--- a/indra/newview/llfloaterjoystick.cpp
+++ b/indra/newview/llfloaterjoystick.cpp
@@ -44,6 +44,7 @@
#include "llwindow.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
+#include "llgamecontrol.h"
#if LL_WINDOWS && !LL_MESA_HEADLESS
// Require DirectInput version 8
@@ -78,15 +79,22 @@ BOOL CALLBACK di8_list_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr,
// Capable of detecting devices like Oculus Rift
if (device_instance_ptr && pvRef)
{
+ // We always include the device if it is from 3DConnexion, otherwise
+ // if the GameControl feature is enabled then we perfer to route other devices to it.
std::string product_name = ll_convert<std::string>(std::wstring(device_instance_ptr->tszProductName));
- S32 size = sizeof(GUID);
- LLSD::Binary data; //just an std::vector
- data.resize(size);
- memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size);
+ bool include_device = LLViewerJoystick::is3DConnexionDevice(product_name);
- LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef;
- LLSD value = data;
- floater->addDevice(product_name, value);
+ if (include_device)
+ {
+ S32 size = sizeof(GUID);
+ LLSD::Binary data; //just an std::vector
+ data.resize(size);
+ memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size);
+
+ LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef;
+ LLSD value = data;
+ floater->addDevice(product_name, value);
+ }
}
return DIENUM_CONTINUE;
}
@@ -303,8 +311,12 @@ void LLFloaterJoystick::refreshListOfDevices()
#if LL_WINDOWS && !LL_MESA_HEADLESS
LL_WARNS() << "NDOF connected to device without using SL provided handle" << LL_ENDL;
#endif
- std::string desc = joystick->getDescription();
- if (!desc.empty())
+ // We always include the device if it is from 3DConnexion, otherwise we only
+ // support the device in this context when GameControl feature is disabled.
+ std::string desc = LLViewerJoystick::getInstance()->getDescription();
+ bool include_device = LLViewerJoystick::is3DConnexionDevice(desc);
+
+ if (include_device)
{
LLSD value = LLSD::Integer(1); // value for selection
addDevice(desc, value);
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 54789278f1..00fbc36f09 100644..100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -55,6 +55,7 @@
#include "llfloaterperformance.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterimsession.h"
+#include "llgamecontrol.h"
#include "llkeyboard.h"
#include "llmodaldialog.h"
#include "llnavigationbar.h"
@@ -63,6 +64,7 @@
#include "llnotificationsutil.h"
#include "llnotificationtemplate.h"
#include "llpanellogin.h"
+#include "llpanelpreferencegamecontrol.h"
#include "llpanelvoicedevicesettings.h"
#include "llradiogroup.h"
#include "llsearchcombobox.h"
@@ -288,6 +290,39 @@ public:
};
LLKeybindingHandler gKeybindHandler;
+// TODO: move this out of llfloaterpreference.cpp
+class LLGameControlBindingHandler: public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLGameControlBindingHandler(): LLCommandHandler("gamecontroller", UNTRUSTED_CLICK_ONLY)
+ {
+ }
+
+ bool handle(const LLSD& params, const LLSD& query_map,
+ const std::string& grid, LLMediaCtrl* web)
+ {
+ if (params.size() < 1) return false;
+
+ LLFloaterPreference* prefsfloater = dynamic_cast<LLFloaterPreference*>
+ (LLFloaterReg::showInstance("preferences"));
+
+ if (prefsfloater)
+ {
+ // find 'controls' panel and bring it the front
+ LLTabContainer* tabcontainer = prefsfloater->getChild<LLTabContainer>("pref core");
+ LLPanel* panel = prefsfloater->getChild<LLPanel>("game_control");
+ if (tabcontainer && panel)
+ {
+ tabcontainer->selectTabPanel(panel);
+ }
+ }
+
+ return true;
+ }
+};
+LLGameControlBindingHandler gGameControlBindingHandler;
+
//////////////////////////////////////////////
// LLFloaterPreference
@@ -408,6 +443,7 @@ void LLFloaterPreference::saveAvatarProperties( void )
}
}
+// static
void LLFloaterPreference::saveAvatarPropertiesCoro(const std::string cap_url, bool allow_publish)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
@@ -583,21 +619,19 @@ void LLFloaterPreference::draw()
void LLFloaterPreference::saveSettings()
{
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
- child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
- child_list_t::const_iterator end = tabcontainer->getChildList()->end();
- for ( ; iter != end; ++iter)
+ for (LLView* view : *tabcontainer->getChildList())
{
- LLView* view = *iter;
- LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
- if (panel)
+ if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view))
+ {
panel->saveSettings();
+ }
}
saveIgnoredNotifications();
}
void LLFloaterPreference::apply()
{
- LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(gAgent.getID(), this);
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
if (sSkin != gSavedSettings.getString("SkinCurrent"))
@@ -605,14 +639,14 @@ void LLFloaterPreference::apply()
LLNotificationsUtil::add("ChangeSkin");
refreshSkin(this);
}
+
// Call apply() on all panels that derive from LLPanelPreference
- for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
- iter != tabcontainer->getChildList()->end(); ++iter)
+ for (LLView* view : *tabcontainer->getChildList())
{
- LLView* view = *iter;
- LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
- if (panel)
+ if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view))
+ {
panel->apply();
+ }
}
gViewerWindow->requestResolutionUpdate(); // for UIScaleFactor
@@ -624,7 +658,9 @@ void LLFloaterPreference::apply()
std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
setCacheLocation(cache_location);
- if (hasChild("web_proxy_enabled", true) &&hasChild("web_proxy_editor", true) && hasChild("web_proxy_port", true))
+ LLViewerMedia::getInstance()->setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue());
+
+ if (hasChild("web_proxy_enabled", true) && hasChild("web_proxy_editor", true) && hasChild("web_proxy_port", true))
{
bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue();
std::string proxy_address = getChild<LLUICtrl>("web_proxy_editor")->getValue();
@@ -661,13 +697,12 @@ void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip
{
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
// Call cancel() on all panels that derive from LLPanelPreference
- for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
- iter != tabcontainer->getChildList()->end(); ++iter)
+ for (LLView* view : *tabcontainer->getChildList())
{
- LLView* view = *iter;
- LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
- if (panel)
+ if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view))
+ {
panel->cancel(settings_to_skip);
+ }
}
// hide joystick pref floater
LLFloaterReg::hideInstance("pref_joystick");
@@ -696,7 +731,7 @@ void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip
}
//Need to reload the navmesh if the pathing console is up
LLHandle<LLFloaterPathfindingConsole> pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle();
- if ( !pathfindingConsoleHandle.isDead() )
+ if (!pathfindingConsoleHandle.isDead())
{
LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get();
pPathfindingConsole->onRegionBoundaryCross();
@@ -713,6 +748,15 @@ void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip
void LLFloaterPreference::onOpen(const LLSD& key)
{
+ LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
+ for (LLView* view : *tabcontainer->getChildList())
+ {
+ if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view))
+ {
+ panel->onOpen(key);
+ }
+ }
+
// this variable and if that follows it are used to properly handle do not disturb mode response message
static bool initialized = false;
// if user is logged in and we haven't initialized do not disturb mode response yet, do it
@@ -792,8 +836,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
// while preferences floater was closed.
buildPopupLists();
-
- //get the options that were checked
+ // get the options that were checked
onNotificationsChange("FriendIMOptions");
onNotificationsChange("NonFriendIMOptions");
onNotificationsChange("ConferenceIMOptions");
@@ -805,8 +848,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
refresh();
// Make sure the current state of prefs are saved away when
- // when the floater is opened. That will make cancel do its
- // job
+ // the floater is opened. That will make cancel() do its job
saveSettings();
// Make sure there is a default preference file
@@ -974,6 +1016,8 @@ void LLFloaterPreference::onClose(bool app_quitting)
LLPanelLogin::setAlwaysRefresh(false);
if (!app_quitting)
{
+ // is this a BUG? cancel() should only be called in onBtnCancel()
+ // but not during closing after onBtnOK()
cancel();
}
}
@@ -1006,9 +1050,9 @@ void LLFloaterPreference::onBtnOK(const LLSD& userdata)
}
//Conversation transcript and log path changed so reload conversations based on new location
- if(mPriorInstantMessageLogPath.length())
+ if (mPriorInstantMessageLogPath.length())
{
- if(moveTranscriptsAndLog())
+ if (moveTranscriptsAndLog())
{
//When floaters are empty but have a chat history files, reload chat history into them
LLFloaterIMSessionTab::reloadEmptyFloaters();
@@ -1025,11 +1069,11 @@ void LLFloaterPreference::onBtnOK(const LLSD& userdata)
LLUIColorTable::instance().saveUserSettings();
gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), true);
- //Only save once logged in and loaded per account settings
- if(mGotPersonalInfo)
+ // Only save once logged in and loaded per account settings
+ if (mGotPersonalInfo)
{
gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), true);
- }
+ }
}
else
{
@@ -1072,26 +1116,33 @@ void LLFloaterPreference::onBtnCancel(const LLSD& userdata)
}
}
+//static
+void LLFloaterPreference::refreshInstance()
+{
+ if (LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"))
+ {
+ instance->refresh();
+ }
+}
+
// static
void LLFloaterPreference::updateUserInfo(const std::string& visibility)
{
- LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
- if (instance)
+ if (LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"))
{
instance->setPersonalInfo(visibility);
}
}
+// static
void LLFloaterPreference::refreshEnabledGraphics()
{
- LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
- if (instance)
+ if (LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"))
{
instance->refresh();
}
- LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced");
- if (advanced)
+ if (LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced"))
{
advanced->refresh();
}
@@ -1133,7 +1184,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName)
bool show_notifications_alert = true;
for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++)
{
- if(it_notification->second != "No action")
+ if (it_notification->second != "No action")
{
show_notifications_alert = false;
break;
@@ -1145,8 +1196,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName)
void LLFloaterPreference::onNameTagOpacityChange(const LLSD& newvalue)
{
- LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("background");
- if (color_swatch)
+ if (LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("background"))
{
LLColor4 new_color = color_swatch->get();
color_swatch->set(new_color.setAlpha((F32)newvalue.asReal()));
@@ -1327,7 +1377,16 @@ void LLAvatarComplexityControls::setIndirectMaxArc()
void LLFloaterPreference::refresh()
{
- LLPanel::refresh();
+ LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
+ for (LLView* view : *tabcontainer->getChildList())
+ {
+ if (LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view))
+ {
+ panel->refresh();
+ break;
+ }
+ }
+ LLFloater::refresh();
setMaxNonImpostorsText(
gSavedSettings.getU32("RenderAvatarMaxNonImpostors"),
getChild<LLTextBox>("IndirectMaxNonImpostorsText", true));
@@ -1335,8 +1394,7 @@ void LLFloaterPreference::refresh()
gSavedSettings.getU32("RenderAvatarMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText", true));
refreshEnabledState();
- LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced");
- if (advanced)
+ if (LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced"))
{
advanced->refresh();
}
@@ -1358,7 +1416,7 @@ void LLFloaterPreference::onCommitWindowedMode()
void LLFloaterPreference::onChangeQuality(const LLSD& data)
{
- U32 level = (U32)(data.asReal());
+ U32 level = (U32)data.asReal();
constexpr U32 LVL_HIGH = 4;
if (level >= LVL_HIGH && mLastQualityLevel < level)
{
@@ -1466,7 +1524,6 @@ void LLFloaterPreference::onClickLogPath()
std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
mPriorInstantMessageLogPath.clear();
-
(new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeLogPath, this, _1, _2), proposed_name))->getFile();
}
@@ -1491,10 +1548,10 @@ bool LLFloaterPreference::moveTranscriptsAndLog()
bool madeDirectory = false;
//Does the directory really exist, if not then make it
- if(!LLFile::isdir(chatLogPath))
+ if (!LLFile::isdir(chatLogPath))
{
//mkdir success is defined as zero
- if(LLFile::mkdir(chatLogPath) != 0)
+ if (LLFile::mkdir(chatLogPath) != 0)
{
return false;
}
@@ -1504,10 +1561,10 @@ bool LLFloaterPreference::moveTranscriptsAndLog()
std::string originalConversationLogDir = LLConversationLog::instance().getFileName();
std::string targetConversationLogDir = gDirUtilp->add(chatLogPath, "conversation.log");
//Try to move the conversation log
- if(!LLConversationLog::instance().moveLog(originalConversationLogDir, targetConversationLogDir))
+ if (!LLConversationLog::instance().moveLog(originalConversationLogDir, targetConversationLogDir))
{
//Couldn't move the log and created a new directory so remove the new directory
- if(madeDirectory)
+ if (madeDirectory)
{
LLFile::remove(chatLogPath);
}
@@ -1520,7 +1577,7 @@ bool LLFloaterPreference::moveTranscriptsAndLog()
LLLogChat::getListOfTranscriptFiles(listOfTranscripts);
- if(!LLLogChat::moveTranscripts(gDirUtilp->getChatLogsDir(),
+ if (!LLLogChat::moveTranscripts(gDirUtilp->getChatLogsDir(),
instantMessageLogPath,
listOfTranscripts,
listOfFilesMoved))
@@ -1533,7 +1590,7 @@ bool LLFloaterPreference::moveTranscriptsAndLog()
//Move the conversation log back
LLConversationLog::instance().moveLog(targetConversationLogDir, originalConversationLogDir);
- if(madeDirectory)
+ if (madeDirectory)
{
LLFile::remove(chatLogPath);
}
@@ -1580,7 +1637,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility)
getChild<LLUICtrl>("voice_call_friends_only_check")->setValue(gSavedPerAccountSettings.getBOOL("VoiceCallsFriendsOnly"));
}
-
void LLFloaterPreference::refreshUI()
{
refresh();
@@ -1885,8 +1941,7 @@ void LLFloaterPreference::onClickActionChange()
void LLFloaterPreference::onAtmosShaderChange()
{
- LLCheckBoxCtrl* ctrl_alm = getChild<LLCheckBoxCtrl>("UseLightShaders");
- if(ctrl_alm)
+ if (LLCheckBoxCtrl* ctrl_alm = getChild<LLCheckBoxCtrl>("UseLightShaders"))
{
//Deferred/SSAO/Shadows
bool bumpshiny = LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump");
@@ -1961,12 +2016,9 @@ void LLFloaterPreference::updateClickActionControls()
// In such case we won't need to do this 'dynamic_cast' nightmare.
// updateTable() can also be avoided
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
- for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
- iter != tabcontainer->getChildList()->end(); ++iter)
+ for (LLView* view : *tabcontainer->getChildList())
{
- LLView* view = *iter;
- LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view);
- if (panel)
+ if (LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view))
{
panel->setKeyBind("walk_to",
EMouseClickType::CLICK_LEFT,
@@ -2000,12 +2052,9 @@ void LLFloaterPreference::updateClickActionViews()
// Todo: This is a very ugly way to get access to keybindings.
// Reconsider possible options.
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
- for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin();
- iter != tabcontainer->getChildList()->end(); ++iter)
+ for (LLView* view : *tabcontainer->getChildList())
{
- LLView* view = *iter;
- LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view);
- if (panel)
+ if (LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view))
{
click_to_walk = panel->canKeyBindHandle("walk_to",
EMouseClickType::CLICK_LEFT,
@@ -2061,6 +2110,16 @@ void LLFloaterPreference::selectPanel(const LLSD& name)
}
}
+void LLFloaterPreference::setPanelVisibility(const LLSD& name, bool visible)
+{
+ LLTabContainer * tab_containerp = getChild<LLTabContainer>("pref core");
+ LLPanel * panel = tab_containerp->getPanelByName(name.asStringRef());
+ if (NULL != panel)
+ {
+ tab_containerp->setTabVisibility(panel, visible);
+ }
+}
+
void LLFloaterPreference::selectPrivacyPanel()
{
selectPanel("im");
@@ -2093,7 +2152,6 @@ void LLFloaterPreference::changed()
// set 'enable' property for 'Delete transcripts...' button
updateDeleteTranscriptsButton();
-
}
void LLFloaterPreference::saveGraphicsPreset(std::string& preset)
@@ -2201,7 +2259,6 @@ bool LLPanelPreference::postBuild()
if (hasChild("media_enabled", true))
{
bool media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia");
-
getChild<LLCheckBoxCtrl>("media_enabled")->set(media_enabled);
getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(media_enabled);
}
@@ -2247,7 +2304,6 @@ bool LLPanelPreference::postBuild()
}
#endif
- apply();
return true;
}
@@ -2258,41 +2314,41 @@ LLPanelPreference::~LLPanelPreference()
delete mBandWidthUpdater;
}
}
+
+// virtual
void LLPanelPreference::apply()
{
// no-op
}
+// virtual
void LLPanelPreference::saveSettings()
{
- LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced");
-
// Save the value of all controls in the hierarchy
mSavedValues.clear();
std::list<LLView*> view_stack;
view_stack.push_back(this);
- if (advanced)
+ // Search for 'Advanced' panel and add it if found
+ if (LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced"))
{
view_stack.push_back(advanced);
}
- while(!view_stack.empty())
+
+ while (!view_stack.empty())
{
// Process view on top of the stack
LLView* curview = view_stack.front();
view_stack.pop_front();
- LLColorSwatchCtrl* color_swatch = dynamic_cast<LLColorSwatchCtrl *>(curview);
- if (color_swatch)
+ if (LLColorSwatchCtrl* color_swatch = dynamic_cast<LLColorSwatchCtrl*>(curview))
{
mSavedColors[color_swatch->getName()] = color_swatch->get();
}
else
{
- LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview);
- if (ctrl)
+ if (LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview))
{
- LLControlVariable* control = ctrl->getControlVariable();
- if (control)
+ if (LLControlVariable* control = ctrl->getControlVariable())
{
mSavedValues[control] = control->getValue();
}
@@ -2300,10 +2356,9 @@ void LLPanelPreference::saveSettings()
}
// Push children onto the end of the work stack
- for (child_list_t::const_iterator iter = curview->getChildList()->begin();
- iter != curview->getChildList()->end(); ++iter)
+ for (LLView* view : *curview->getChildList())
{
- view_stack.push_back(*iter);
+ view_stack.push_back(view);
}
}
@@ -2445,7 +2500,7 @@ public:
mAccountIndependentSettings.push_back("AutoDisengageMic");
}
- /*virtual*/ void saveSettings()
+ void saveSettings() override
{
LLPanelPreference::saveSettings();
@@ -2460,7 +2515,7 @@ public:
if (find(mAccountIndependentSettings.begin(),
mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end())
{
- mSavedValues.erase(it++);
+ it = mSavedValues.erase(it);
}
else
{
@@ -2625,9 +2680,11 @@ void LLPanelPreferenceGraphics::cancel(const std::vector<std::string> settings_t
{
LLPanelPreference::cancel(settings_to_skip);
}
+
void LLPanelPreferenceGraphics::saveSettings()
{
resetDirtyChilds();
+
std::string preset_graphic_active = gSavedSettings.getString("PresetGraphicActive");
if (preset_graphic_active.empty())
{
@@ -2638,8 +2695,10 @@ void LLPanelPreferenceGraphics::saveSettings()
instance->saveGraphicsPreset(preset_graphic_active);
}
}
+
LLPanelPreference::saveSettings();
}
+
void LLPanelPreferenceGraphics::setHardwareDefaults()
{
resetDirtyChilds();
@@ -2832,6 +2891,12 @@ LLPanelPreferenceControls::~LLPanelPreferenceControls()
{
}
+void LLPanelPreferenceControls::refresh()
+{
+ populateControlTable();
+ LLPanelPreference::refresh();
+}
+
bool LLPanelPreferenceControls::postBuild()
{
// populate list of controls
@@ -2903,12 +2968,9 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename)
cell_params.column = "";
cell_params.value = "";
-
- for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = contents.rows.begin();
- row_it != contents.rows.end();
- ++row_it)
+ for (LLScrollListItem::Params& row_params : contents.rows)
{
- std::string control = row_it->value.getValue().asString();
+ std::string control = row_params.value.getValue().asString();
if (!control.empty() && control != "menu_separator")
{
bool show = true;
@@ -2927,7 +2989,7 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename)
if (show)
{
// At the moment viewer is hardcoded to assume that columns are named as lst_ctrl%d
- LLScrollListItem::Params item_params(*row_it);
+ LLScrollListItem::Params item_params(row_params);
item_params.enabled.setValue(enabled);
S32 num_columns = pControlsTable->getNumColumns();
@@ -2952,7 +3014,7 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename)
// value = "menu_separator"
// column = "lst_action" / >
//</rows>
- pControlsTable->addRow(*row_it, EAddPosition::ADD_BOTTOM);
+ pControlsTable->addRow(row_params, EAddPosition::ADD_BOTTOM);
}
}
return true;
@@ -2974,6 +3036,22 @@ void LLPanelPreferenceControls::addControlTableSeparator()
void LLPanelPreferenceControls::populateControlTable()
{
+ // The mode combo is the source of truth for which bindings to display.
+ // Keep mEditingMode in sync with it and make sure that mode's bindings are
+ // loaded before we render; otherwise the table shows empty cells on first
+ // open (refresh() populates before any load has happened, and mEditingMode
+ // may not match the mode currently selected in the combo).
+ if (pKeyModeBox)
+ {
+ mEditingMode = pKeyModeBox->getValue().asInteger();
+ }
+ if (mEditingMode >= 0
+ && mEditingMode < (S32)LLKeyConflictHandler::MODE_COUNT
+ && mConflictHandler[mEditingMode].empty())
+ {
+ mConflictHandler[mEditingMode].loadFromSettings((LLKeyConflictHandler::ESourceMode)mEditingMode);
+ }
+
pControlsTable->clearRows();
pControlsTable->clearColumns();
@@ -2985,6 +3063,7 @@ void LLPanelPreferenceControls::populateControlTable()
case LLKeyConflictHandler::MODE_FIRST_PERSON:
case LLKeyConflictHandler::MODE_EDIT_AVATAR:
case LLKeyConflictHandler::MODE_SITTING:
+ case LLKeyConflictHandler::MODE_FLYCAM:
filename = "control_table_contents_columns_basic.xml";
break;
default:
@@ -3012,6 +3091,14 @@ void LLPanelPreferenceControls::populateControlTable()
addControlTableRows("control_table_contents_movement.xml");
addControlTableSeparator();
addControlTableRows("control_table_contents_media.xml");
+ addControlTableSeparator();
+ addControlTableRows("control_table_contents_game_control.xml");
+ }
+ else if (mEditingMode == LLKeyConflictHandler::MODE_FLYCAM)
+ {
+ // Flycam has its own dedicated set of actions; camera/editing/media
+ // groups don't apply to it.
+ addControlTableRows("control_table_contents_flycam.xml");
}
// MODE_THIRD_PERSON; MODE_EDIT_AVATAR; MODE_SITTING
else if (mEditingMode < LLKeyConflictHandler::MODE_SAVED_SETTINGS)
@@ -3028,6 +3115,9 @@ void LLPanelPreferenceControls::populateControlTable()
addControlTableSeparator();
addControlTableRows("control_table_contents_media.xml");
+ addControlTableSeparator();
+
+ addControlTableRows("control_table_contents_game_control.xml");
}
else
{
@@ -3403,6 +3493,7 @@ void LLPanelPreferenceControls::onDefaultKeyBind(bool all_modes)
mConflictHandler[mEditingMode].saveToSettings(true);
}
}
+
updateTable();
if (mEditingMode == LLKeyConflictHandler::MODE_THIRD_PERSON || all_modes)
@@ -3421,6 +3512,8 @@ void LLPanelPreferenceControls::onCancelKeyBind()
pControlsTable->deselectAllItems();
}
+//------------------------LLFloaterPreferenceProxy--------------------------------
+
LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key)
: LLFloater(key),
mSocksSettingsDirty(false)
@@ -3464,7 +3557,7 @@ void LLFloaterPreferenceProxy::onOpen(const LLSD& key)
void LLFloaterPreferenceProxy::onClose(bool app_quitting)
{
- if(app_quitting)
+ if (app_quitting)
{
cancel();
}
@@ -3488,7 +3581,7 @@ void LLFloaterPreferenceProxy::saveSettings()
mSavedValues.clear();
std::list<LLView*> view_stack;
view_stack.push_back(this);
- while(!view_stack.empty())
+ while (!view_stack.empty())
{
// Process view on top of the stack
LLView* curview = view_stack.front();
@@ -3575,13 +3668,9 @@ void LLFloaterPreferenceProxy::onClickCloseBtn(bool app_quitting)
void LLFloaterPreferenceProxy::cancel()
{
-
- for (control_values_map_t::iterator iter = mSavedValues.begin();
- iter != mSavedValues.end(); ++iter)
+ for (const auto& iter : mSavedValues)
{
- LLControlVariable* control = iter->first;
- LLSD ctrl_value = iter->second;
- control->set(ctrl_value);
+ iter.first->set(iter.second);
}
mSocksSettingsDirty = false;
closeFloater();
@@ -3606,21 +3695,20 @@ void LLFloaterPreferenceProxy::onChangeSocksSettings()
// Check for invalid states for the other HTTP proxy radio
LLRadioGroup* otherHttpProxy = getChild<LLRadioGroup>("other_http_proxy_type");
if ((otherHttpProxy->getSelectedValue().asString() == "Socks" &&
- !getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get())||(
+ getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get() == false )||(
otherHttpProxy->getSelectedValue().asString() == "Web" &&
- !getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get()))
+ getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get() == false ) )
{
otherHttpProxy->selectFirstItem();
}
-
}
void LLFloaterPreference::onUpdateFilterTerm(bool force)
{
- LLWString seachValue = utf8str_to_wstring(mFilterEdit->getValue());
- LLWStringUtil::toLower(seachValue);
+ LLWString seachValue = utf8str_to_wstring( mFilterEdit->getValue() );
+ LLWStringUtil::toLower( seachValue );
- if (!mSearchData || (mSearchData->mLastFilter == seachValue && !force))
+ if( !mSearchData || (mSearchData->mLastFilter == seachValue && !force))
return;
if (mSearchDataDirty)
@@ -3631,7 +3719,7 @@ void LLFloaterPreference::onUpdateFilterTerm(bool force)
mSearchData->mLastFilter = seachValue;
- if (!mSearchData->mRootTab)
+ if( !mSearchData->mRootTab )
return;
mSearchData->mRootTab->hightlightAndHide( seachValue );
@@ -3654,10 +3742,10 @@ void LLFloaterPreference::filterIgnorableNotifications()
void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel, ll::prefs::TabContainerDataPtr aParentTabContainer )
{
- if (!aView)
+ if( !aView )
return;
- llassert_always(aParentPanel || aParentTabContainer);
+ llassert_always( aParentPanel || aParentTabContainer );
for (LLView* pView : *aView->getChildList())
{
@@ -3667,56 +3755,56 @@ void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel,
ll::prefs::PanelDataPtr pCurPanelData = aParentPanel;
ll::prefs::TabContainerDataPtr pCurTabContainer = aParentTabContainer;
- LLPanel const *pPanel = dynamic_cast<LLPanel const*>(pView);
- LLTabContainer const *pTabContainer = dynamic_cast<LLTabContainer const*>(pView);
- ll::ui::SearchableControl const *pSCtrl = dynamic_cast<ll::ui::SearchableControl const*>( pView );
+ LLPanel const *pPanel = dynamic_cast< LLPanel const *>( pView );
+ LLTabContainer const *pTabContainer = dynamic_cast< LLTabContainer const *>( pView );
+ ll::ui::SearchableControl const *pSCtrl = dynamic_cast< ll::ui::SearchableControl const *>( pView );
- if (pTabContainer)
+ if( pTabContainer )
{
pCurPanelData.reset();
- pCurTabContainer = ll::prefs::TabContainerDataPtr(new ll::prefs::TabContainerData);
- pCurTabContainer->mTabContainer = const_cast< LLTabContainer *>(pTabContainer);
+ pCurTabContainer = ll::prefs::TabContainerDataPtr( new ll::prefs::TabContainerData );
+ pCurTabContainer->mTabContainer = const_cast< LLTabContainer *>( pTabContainer );
pCurTabContainer->mLabel = pTabContainer->getLabel();
pCurTabContainer->mPanel = 0;
- if (aParentPanel)
- aParentPanel->mChildPanel.push_back(pCurTabContainer);
- if (aParentTabContainer)
- aParentTabContainer->mChildPanel.push_back(pCurTabContainer);
+ if( aParentPanel )
+ aParentPanel->mChildPanel.push_back( pCurTabContainer );
+ if( aParentTabContainer )
+ aParentTabContainer->mChildPanel.push_back( pCurTabContainer );
}
- else if (pPanel)
+ else if( pPanel )
{
pCurTabContainer.reset();
- pCurPanelData = ll::prefs::PanelDataPtr(new ll::prefs::PanelData);
+ pCurPanelData = ll::prefs::PanelDataPtr( new ll::prefs::PanelData );
pCurPanelData->mPanel = pPanel;
pCurPanelData->mLabel = pPanel->getLabel();
llassert_always( aParentPanel || aParentTabContainer );
- if (aParentTabContainer)
- aParentTabContainer->mChildPanel.push_back(pCurPanelData);
- else if (aParentPanel)
- aParentPanel->mChildPanel.push_back(pCurPanelData);
+ if( aParentTabContainer )
+ aParentTabContainer->mChildPanel.push_back( pCurPanelData );
+ else if( aParentPanel )
+ aParentPanel->mChildPanel.push_back( pCurPanelData );
}
- else if (pSCtrl && pSCtrl->getSearchText().size())
+ else if( pSCtrl && pSCtrl->getSearchText().size() )
{
- ll::prefs::SearchableItemPtr item = ll::prefs::SearchableItemPtr(new ll::prefs::SearchableItem());
+ ll::prefs::SearchableItemPtr item = ll::prefs::SearchableItemPtr( new ll::prefs::SearchableItem() );
item->mView = pView;
item->mCtrl = pSCtrl;
- item->mLabel = utf8str_to_wstring(pSCtrl->getSearchText());
- LLWStringUtil::toLower(item->mLabel);
+ item->mLabel = utf8str_to_wstring( pSCtrl->getSearchText() );
+ LLWStringUtil::toLower( item->mLabel );
- llassert_always(aParentPanel || aParentTabContainer);
+ llassert_always( aParentPanel || aParentTabContainer );
- if (aParentPanel)
- aParentPanel->mChildren.push_back(item);
- if (aParentTabContainer)
- aParentTabContainer->mChildren.push_back(item);
+ if( aParentPanel )
+ aParentPanel->mChildren.push_back( item );
+ if( aParentTabContainer )
+ aParentTabContainer->mChildren.push_back( item );
}
- collectChildren(pView, pCurPanelData, pCurTabContainer);
+ collectChildren( pView, pCurPanelData, pCurTabContainer );
}
}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 07ed39d46c..58a4fbde02 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -36,9 +36,13 @@
#include "llfloater.h"
#include "llavatarpropertiesprocessor.h"
#include "llconversationlog.h"
+#include "llgamecontrol.h"
+#include "llkeyconflict.h"
+#include "llscrolllistcell.h"
+#include "llscrolllistctrl.h"
#include "llsearcheditor.h"
#include "llsetkeybinddialog.h"
-#include "llkeyconflict.h"
+#include "llspinctrl.h"
class LLConversationLogObserver;
class LLPanelPreference;
@@ -80,12 +84,14 @@ public:
void apply();
void cancel(const std::vector<std::string> settings_to_skip = {});
- /*virtual*/ void draw();
- /*virtual*/ bool postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
- /*virtual*/ void onClose(bool app_quitting);
- /*virtual*/ void changed();
- /*virtual*/ void changed(const LLUUID& session_id, U32 mask) {};
+ virtual void draw() override;
+ virtual bool postBuild() override;
+ virtual void onOpen(const LLSD& key) override;
+ virtual void onClose(bool app_quitting) override;
+ virtual void changed() override;
+ virtual void changed(const LLUUID& session_id, U32 mask) override {};
+
+ static void refreshInstance();
// static data update, called from message handler
static void updateUserInfo(const std::string& visibility);
@@ -99,7 +105,7 @@ public:
// update Show Favorites checkbox
static void updateShowFavoritesCheckbox(bool val);
- void processProperties( void* pData, EAvatarProcessorType type );
+ void processProperties( void* pData, EAvatarProcessorType type ) override;
void saveAvatarProperties( void );
static void saveAvatarPropertiesCoro(const std::string url, bool allow_publish);
void selectPrivacyPanel();
@@ -168,7 +174,7 @@ public:
void setPersonalInfo(const std::string& visibility);
void refreshEnabledState();
void onCommitWindowedMode();
- void refresh(); // Refresh enable/disable
+ void refresh() override; // Refresh enable/disable
// if the quality radio buttons are changed
void onChangeQuality(const LLSD& data);
@@ -198,6 +204,7 @@ public:
void buildPopupLists();
static void refreshSkin(void* data);
void selectPanel(const LLSD& name);
+ void setPanelVisibility(const LLSD& name, bool visible);
void saveGraphicsPreset(std::string& preset);
void setRecommendedSettings();
@@ -259,7 +266,7 @@ class LLPanelPreference : public LLPanel
{
public:
LLPanelPreference();
- /*virtual*/ bool postBuild();
+ virtual bool postBuild() override;
virtual ~LLPanelPreference();
@@ -305,12 +312,12 @@ private:
class LLPanelPreferenceGraphics : public LLPanelPreference
{
public:
- bool postBuild();
- void draw();
- void cancel(const std::vector<std::string> settings_to_skip = {});
- void saveSettings();
+ bool postBuild() override;
+ void draw() override;
+ void cancel(const std::vector<std::string> settings_to_skip = {}) override;
+ void saveSettings() override;
void resetDirtyChilds();
- void setHardwareDefaults();
+ void setHardwareDefaults() override;
void setPresetText();
protected:
@@ -348,11 +355,13 @@ public:
LLPanelPreferenceControls();
virtual ~LLPanelPreferenceControls();
- bool postBuild();
+ bool postBuild() override;
- void apply();
- void cancel(const std::vector<std::string> settings_to_skip = {});
- void saveSettings();
+ void refresh() override;
+
+ void apply() override;
+ void cancel(const std::vector<std::string> settings_to_skip = {}) override;
+ void saveSettings() override;
void resetDirtyChilds();
void onListCommit();
@@ -368,9 +377,12 @@ public:
void updateAndApply();
// from interface
- /*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);
- /*virtual*/ void onDefaultKeyBind(bool all_modes);
- /*virtual*/ void onCancelKeyBind();
+ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) override;
+ void onDefaultKeyBind(bool all_modes) override;
+ void onCancelKeyBind() override;
+
+ // Cleans content and then adds content from xml files according to current mEditingMode
+ void populateControlTable();
private:
// reloads settings, discards current changes, updates table
@@ -381,9 +393,6 @@ private:
bool addControlTableRows(const std::string &filename);
void addControlTableSeparator();
- // Cleans content and then adds content from xml files according to current mEditingMode
- void populateControlTable();
-
// Updates keybindings from storage to table
void updateTable();
@@ -419,13 +428,13 @@ public:
void cancel();
protected:
- bool postBuild();
- void onOpen(const LLSD& key);
- void onClose(bool app_quitting);
+ bool postBuild() override;
+ void onOpen(const LLSD& key) override;
+ void onClose(bool app_quitting) override;
void saveSettings();
void onBtnOk();
void onBtnCancel();
- void onClickCloseBtn(bool app_quitting = false);
+ void onClickCloseBtn(bool app_quitting = false) override;
void onChangeSocksSettings();
diff --git a/indra/newview/llflycam.cpp b/indra/newview/llflycam.cpp
new file mode 100644
index 0000000000..9ba631c0a5
--- /dev/null
+++ b/indra/newview/llflycam.cpp
@@ -0,0 +1,325 @@
+/**
+ * @file llflycam.cpp
+ * @brief LLFlycam class implementation
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llflycam.h"
+
+#include <algorithm>
+#include "llcamera.h"
+#include "llcoordframe.h"
+#include "m3math.h"
+
+void LLFlycam::setTransform(const LLVector3d& position, const LLQuaternion& rotation)
+{
+ mPosition = position;
+ mRotation = rotation;
+ mRotation.normalize();
+}
+
+void LLFlycam::getTransform(LLVector3d& position_out, LLQuaternion& rotation_out)
+{
+ position_out = mPosition;
+ rotation_out = mRotation;
+}
+
+// 'view' is expected to be in radians
+void LLFlycam::setView(F32 view)
+{
+ mView = std::clamp(view, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW);
+}
+
+
+void LLFlycam::setLinearVelocity(const LLVector3& velocity)
+{
+ // Note: this math expects velocity components to be in range [-1.0, 1.0]
+ mLinearVelocity = velocity * mSpeedFactor;
+}
+
+
+void LLFlycam::setPitchRate(F32 pitch_rate)
+{
+ // Note: this math expects pitch_rate to be in range [-1.0, 1.0]
+ constexpr F32 PITCH_RATE_FACTOR = 0.75f;
+ mPitchRate = pitch_rate * mSpeedFactor * PITCH_RATE_FACTOR;
+}
+
+
+void LLFlycam::setYawRate(F32 yaw_rate)
+{
+ // Note: this math expects yaw_rate to be in range [-1.0, 1.0]
+ constexpr F32 YAW_RATE_FACTOR = 0.90f;
+ mYawRate = yaw_rate * mSpeedFactor * YAW_RATE_FACTOR;
+}
+
+
+void LLFlycam::setRollRate(F32 roll_rate)
+{
+ // Note: this math expects roll_rate to be in range [-1.0, 1.0]
+ constexpr F32 ROLL_RATE_FACTOR = 0.90f;
+ mRollRate = mAllowRoll ? roll_rate * mSpeedFactor * ROLL_RATE_FACTOR : 0.0f;
+}
+
+
+void LLFlycam::setSpeedFactor(F32 speed_factor)
+{
+ mSpeedFactor = std::clamp(speed_factor, MIN_FLYCAM_SPEED_FACTOR, MAX_FLYCAM_SPEED_FACTOR);
+}
+
+
+void LLFlycam::setZoomRate(F32 zoom_rate)
+{
+ // Note: this math expects zoom_rate to be in range [-1.0, 1.0]
+ constexpr F32 FULL_ZOOM_PERIOD = 5.0f; // seconds
+ constexpr F32 ZOOM_RATE_FACTOR = (MAX_FIELD_OF_VIEW - MIN_FIELD_OF_VIEW) / FULL_ZOOM_PERIOD;
+ mZoomRate = zoom_rate * ZOOM_RATE_FACTOR;
+}
+
+
+void LLFlycam::setOrbitEngaged(bool engaged, F32 focal_distance)
+{
+ if (engaged && !mOrbitEngaged)
+ {
+ // Rising edge: fix the focal point 'focal_distance' meters in front of
+ // the camera's current forward axis. It stays put in world space for
+ // as long as orbit stays engaged, even as Pan/Truck/Tilt/Roll rotate
+ // the camera around it (see integrate()).
+ LLVector3 forward(LLMatrix3(mRotation).getFwdRow());
+ mOrbitFocalPoint = mPosition + LLVector3d(forward) * (F64)focal_distance;
+ }
+ mOrbitEngaged = engaged;
+}
+
+
+void LLFlycam::setOrbitRadialRate(F32 radial_rate)
+{
+ // Note: this math expects radial_rate to be in range [-1.0, 1.0]. The
+ // resulting rate is a FRACTION of the current distance-to-focal-point per
+ // second (not a fixed speed), so approach slows near the focal point and
+ // retreat speeds up far away from it.
+ constexpr F32 ORBIT_RADIAL_RATE_FACTOR = 1.0f; // fraction of distance/sec at full deflection; may be tuned later
+ mOrbitRadialRate = radial_rate * ORBIT_RADIAL_RATE_FACTOR;
+}
+
+
+void LLFlycam::startReset(const LLVector3d& target_position, const LLQuaternion& target_rotation, F32 duration)
+{
+ mResetStartPosition = mPosition;
+ mResetStartRotation = mRotation;
+ mResetTargetPosition = target_position;
+ mResetTargetRotation = target_rotation;
+ mResetDuration = std::max(duration, 0.001f);
+ mResetTimeRemaining = mResetDuration;
+
+ // Drop any live rates so leftover input doesn't fight the lerp, or get
+ // applied unexpectedly the moment the reset completes.
+ mLinearVelocity.clear();
+ mPitchRate = mYawRate = mRollRate = mZoomRate = 0.0f;
+}
+
+
+void LLFlycam::integrate(F32 delta_time)
+{
+ // cap delta_time to slow camera motion when framerates are low
+ constexpr F32 MAX_DELTA_TIME = 0.2f;
+ if (delta_time > MAX_DELTA_TIME)
+ {
+ delta_time = MAX_DELTA_TIME;
+ }
+
+ if (mResetTimeRemaining > 0.0f)
+ {
+ // Reset in progress: lerp toward the target transform and ignore
+ // whatever rates setLinearVelocity()/setPitchRate()/etc. set this
+ // frame -- flycam input has no effect until the lerp completes.
+ mResetTimeRemaining = std::max(mResetTimeRemaining - delta_time, 0.0f);
+ F32 fraction = 1.0f - (mResetTimeRemaining / mResetDuration);
+ mPosition = lerp(mResetStartPosition, mResetTargetPosition, fraction);
+ mRotation = nlerp(fraction, mResetStartRotation, mResetTargetRotation);
+ return;
+ }
+
+ F32 angle;
+ bool needs_renormalization = false;
+
+ // Before we adjust the rotation let's prepare precautions against Eulerian spinlock
+ LLVector3 forward = LLVector3::x_axis * mRotation;
+ F32 forward_up = forward.mV[VZ];
+ if (fabsf(forward_up) > 1.0f)
+ {
+ forward_up = forward_up / fabsf(forward_up);
+ }
+ F32 sin_pitch = sqrtf(1.0f - std::min(forward_up*forward_up, 1.0f));
+
+ // Yaw
+ angle = delta_time * mYawRate * (mView / DEFAULT_FIELD_OF_VIEW);
+ angle *= std::max(sin_pitch, 0.1f);
+ if (fabsf(angle) > 0.0f)
+ {
+ LLQuaternion dQ;
+ dQ.setAngleAxis(angle, 0.0f, 0.0f, 1.0f);
+ if (mAllowRoll)
+ {
+ mRotation = dQ * mRotation;
+ }
+ else
+ {
+ mRotation = dQ * mRotation;
+
+ // Un-roll: keep the just-applied forward axis, but rebuild "up" to
+ // lie in the plane spanned by forward and world-up, which removes
+ // any roll the pitch+yaw quaternion multiplications above may have
+ // introduced (they don't commute).
+ LLMatrix3 level(mRotation);
+ LLVector3 forward(level.getFwdRow());
+ forward.normVec();
+
+ LLVector3 world_up = LLVector3::z_axis;
+ LLVector3 new_up = world_up - (world_up * forward) * forward;
+ constexpr F32 MIN_UNROLL_SIN = 0.01f; // ~0.6 degrees off vertical
+ if (new_up.lengthSquared() > MIN_UNROLL_SIN * MIN_UNROLL_SIN)
+ {
+ new_up.normVec();
+ // Right-handed (forward, left, up) basis, per
+ // LLMatrix3::orthogonalize()'s up = forward % left: up % forward == left.
+ LLVector3 new_left = new_up % forward;
+ level.setRows(forward, new_left, new_up);
+ mRotation = LLQuaternion(level);
+ }
+ }
+ needs_renormalization = true;
+ }
+
+ // Pitch
+ // Note: we modulate pitch and yaw rates by view ratio
+ // to make pitch and yaw work better when zoomed in close
+ angle = delta_time * mPitchRate * (mView / DEFAULT_FIELD_OF_VIEW);
+ // and avoid overshooting the vertical by using small angle approximation trick
+ F32 small_angle_approx_to_vertical = 1.0f - fabsf(forward_up);
+ if (angle != 0.0f
+ && !(forward_up > 0.0f && angle < -small_angle_approx_to_vertical)
+ && !(forward_up < 0.0f && angle > small_angle_approx_to_vertical))
+ {
+ LLQuaternion dQ;
+ dQ.setAngleAxis(angle, 0.0f, 1.0f, 0.0f);
+ mRotation = dQ * mRotation;
+ needs_renormalization = true;
+ }
+
+ // Roll about the camera's forward (local X) axis. Like pitch this is a
+ // body-frame rotation, so it pre-multiplies mRotation.
+ angle = delta_time * mRollRate * (mView / DEFAULT_FIELD_OF_VIEW);
+ if (fabsf(angle) > 0.0f)
+ {
+ LLQuaternion dQ;
+ dQ.setAngleAxis(angle, 1.0f, 0.0f, 0.0f);
+ mRotation = dQ * mRotation;
+ needs_renormalization = true;
+ }
+
+ if (mOrbitEngaged)
+ {
+ // Re-derive position from the just-rotated forward axis, so the
+ // camera stays (radially adjusted) 'distance' meters from the fixed
+ // focal point, always facing it. Pan/Truck (yaw, above) and Tilt
+ // (pitch, above) therefore sweep/swing the camera around the focal
+ // point as a side effect of simply rotating the camera; only the
+ // radius itself is orbit-specific here.
+ constexpr F32 MIN_ORBIT_DISTANCE = 0.1f; // meters
+ F32 distance = (F32)(mPosition - mOrbitFocalPoint).length();
+ distance = std::max(distance * (1.0f + delta_time * mOrbitRadialRate), MIN_ORBIT_DISTANCE);
+ // 'forward' points from the camera toward the focal point, so the
+ // camera itself sits behind the focal point along that axis.
+ LLVector3 forward(LLMatrix3(mRotation).getFwdRow());
+ mPosition = mOrbitFocalPoint - LLVector3d(forward) * (F64)distance;
+ }
+
+ if (mLinearVelocity.lengthSquared() > 0.0f)
+ {
+ // Boom (local Z) still translates the camera directly here, on top of
+ // the orbit reposition above, regardless of mOrbitEngaged -- Truck/
+ // Dolly's contributions are zeroed out by LLAgentCamera::updateFlycam()
+ // while orbiting, since they're redirected into yaw/radial rate instead.
+ LLVector3d translation((delta_time * mLinearVelocity) * mRotation);
+ mPosition += translation;
+ if (mOrbitEngaged)
+ {
+ // Boom doesn't reorient the camera or change its distance from
+ // the focal point -- drag the focal point along with it instead,
+ // so the next frame's orbit reposition still measures 'distance'
+ // from wherever boom just moved it to.
+ mOrbitFocalPoint += translation;
+ }
+ }
+
+ if (mZoomRate != 0.0f)
+ {
+ // Note: we subtract the delta because "positive" zoom (e.g. "zoom in")
+ // produces smaller view angle
+ mView = std::clamp(mView - delta_time * mZoomRate, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW);
+ }
+
+ if (needs_renormalization)
+ {
+ mRotation.normalize();
+ }
+}
+
+
+void LLFlycam::applyFrameDelta(const F32 local_delta[7],
+ bool auto_level, F32 auto_level_fraction,
+ bool direct_view, F32 direct_view_value)
+{
+ mPosition += LLVector3d(local_delta[VX], local_delta[VY], local_delta[VZ]) * mRotation;
+
+ LLMatrix3 rot_mat(local_delta[3], local_delta[4], local_delta[5]);
+ mRotation = LLQuaternion(rot_mat) * mRotation;
+
+ if (auto_level)
+ {
+ LLMatrix3 level(mRotation);
+
+ LLVector3 x = LLVector3(level.mMatrix[0]);
+ LLVector3 y = LLVector3(level.mMatrix[1]);
+ LLVector3 z = LLVector3(level.mMatrix[2]);
+
+ y.mV[2] = 0.f;
+ y.normVec();
+
+ level.setRows(x, y, z);
+ level.orthogonalize();
+
+ LLQuaternion quat(level);
+ mRotation = nlerp(auto_level_fraction, mRotation, quat);
+ }
+
+ if (direct_view)
+ {
+ setView(direct_view_value);
+ }
+ else
+ {
+ setView(mView + local_delta[6]);
+ }
+}
diff --git a/indra/newview/llflycam.h b/indra/newview/llflycam.h
new file mode 100644
index 0000000000..4c3afea491
--- /dev/null
+++ b/indra/newview/llflycam.h
@@ -0,0 +1,139 @@
+/**
+ * @file llflycam.h
+ * @brief LLFlycam class header file
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llcamera.h"
+#include "llquaternion.h"
+#include "v3math.h"
+#include "v3dmath.h"
+
+constexpr F32 MIN_FLYCAM_SPEED_FACTOR = 0.5f;
+constexpr F32 MAX_FLYCAM_SPEED_FACTOR = 2.0f;
+constexpr F32 DEFAULT_FLYCAM_SPEED_FACTOR = 1.0f;
+
+class LLFlycam
+{
+public:
+
+ LLFlycam() = default;
+
+ // Note: position is in global (region-independent) coordinates, since it
+ // must remain valid across the region-origin rebases that happen when the
+ // agent crosses a region boundary while this transform is in use.
+ void setTransform(const LLVector3d& position, const LLQuaternion& rotation);
+ void getTransform(LLVector3d& position_out, LLQuaternion& rotation_out);
+
+ void setView(F32 view);
+ F32 getView() const { return mView; }
+
+ void setLinearVelocity(const LLVector3& velocity);
+ void setPitchRate(F32 pitch_rate);
+ void setYawRate(F32 yaw_rate);
+ void setRollRate(F32 roll_rate);
+ void setZoomRate(F32 zoom_rate);
+
+ // Whether Roll input is allowed to rotate the flycam about its forward
+ // axis; when false, setRollRate() discards its input and the flycam
+ // never rolls. Off by default; driven by the "GameControl" FlyCam
+ // settings' AllowRoll flag (see LLGameControl::isFlycamRollAllowed()).
+ void setAllowRoll(bool allow) { mAllowRoll = allow; }
+ bool getAllowRoll() const { return mAllowRoll; }
+
+ // Multiplier applied to the Pitch/Yaw/Roll RATE_FACTOR coefficients in
+ // setPitchRate()/setYawRate()/setRollRate(), and to the Truck/Dolly/Boom
+ // velocity passed to setLinearVelocity() (e.g. "Slow" .. "Fast"). Clamped
+ // to [MIN_FLYCAM_SPEED_FACTOR, MAX_FLYCAM_SPEED_FACTOR]; defaults to
+ // DEFAULT_FLYCAM_SPEED_FACTOR. Driven by the "GameControl" FlyCam settings'
+ // SpeedFactor value (see LLGameControl::getSpeedFactor()).
+ void setSpeedFactor(F32 speed_factor);
+ F32 getSpeedFactor() const { return mSpeedFactor; }
+
+ // Orbit modifier: while engaged, position is re-derived every integrate()
+ // from the camera's own (pitch/yaw-rotated) forward axis so the camera
+ // stays 'focal_distance' meters from a focal point fixed in front of it
+ // the moment orbit engages -- Pan/Truck/Tilt/Roll keep rotating the
+ // camera exactly as they do outside orbit (see integrate()); only the
+ // radial (dolly) rate is orbit-specific. Boom still translates the camera
+ // directly (see integrate()), but doesn't reorient it or change its
+ // distance from the focal point: the same translation is applied to the
+ // focal point too, dragging it along with the camera.
+ void setOrbitEngaged(bool engaged, F32 focal_distance);
+ bool isOrbitEngaged() const { return mOrbitEngaged; }
+ void setOrbitRadialRate(F32 radial_rate);
+
+ // Begins a smooth transition from the current transform to
+ // 'target_position'/'target_rotation', taking 'duration' seconds. While
+ // the transition is in progress, integrate() ignores the rates set by
+ // setLinearVelocity()/setPitchRate()/etc. and instead lerps toward the
+ // target; normal input-driven integration resumes once it completes.
+ void startReset(const LLVector3d& target_position, const LLQuaternion& target_rotation, F32 duration);
+ bool isResetting() const { return mResetTimeRemaining > 0.0f; }
+
+ void integrate(F32 delta_time);
+
+ // Applies one frame of already-tuned deltas directly to the transform,
+ // bypassing the rate-based setPitchRate()/etc. + integrate() path. Used
+ // by input sources (the legacy NDOF joystick) that compute their own
+ // per-axis dead-zone/scale/feathering and only need this class to own
+ // the resulting transform update, so their feel is preserved exactly.
+ // 'local_delta' holds, in order: [0..2] local-frame translation delta
+ // (x,y,z); [3..5] rotation delta (roll,pitch,yaw, as fed to
+ // LLMatrix3(r,p,y)); [6] zoom delta added to the view angle (ignored if
+ // 'direct_view' is set, in which case 'direct_view_value' replaces the
+ // view angle outright).
+ void applyFrameDelta(const F32 local_delta[7],
+ bool auto_level, F32 auto_level_fraction,
+ bool direct_view, F32 direct_view_value);
+
+protected:
+ LLVector3d mPosition;
+ LLVector3 mLinearVelocity;
+ LLQuaternion mRotation;
+ F32 mPitchRate { 0.0f };
+ F32 mYawRate { 0.0f };
+ F32 mRollRate { 0.0f };
+ F32 mZoomRate { 0.0f };
+ F32 mView { DEFAULT_FIELD_OF_VIEW };
+ bool mAllowRoll { false };
+ F32 mSpeedFactor { DEFAULT_FLYCAM_SPEED_FACTOR };
+
+ // Orbit-in-progress state: see setOrbitEngaged()/setOrbitRadialRate() and
+ // the orbit branch in integrate().
+ bool mOrbitEngaged { false };
+ LLVector3d mOrbitFocalPoint;
+ F32 mOrbitRadialRate { 0.0f };
+
+ // Reset-in-progress state: integrate() lerps mPosition/mRotation from
+ // mResetStart* to mResetTarget* as mResetTimeRemaining counts down from
+ // mResetDuration to zero.
+ LLVector3d mResetStartPosition;
+ LLQuaternion mResetStartRotation;
+ LLVector3d mResetTargetPosition;
+ LLQuaternion mResetTargetRotation;
+ F32 mResetDuration { 0.0f };
+ F32 mResetTimeRemaining { 0.0f };
+};
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index c082c632f1..edd5f5e20c 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -34,6 +34,7 @@
#include "llkeyconflict.h"
+#include "llgamecontrol.h"
#include "llinitparam.h"
#include "llkeyboard.h"
#include "lltrans.h"
@@ -99,29 +100,34 @@ LLKeyConflictHandler::~LLKeyConflictHandler()
// Note: does not reset bindings if temporary file was used
}
-bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask)
+bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) const
{
- return mControlsMap[control_name].canHandle(mouse_ind, key, mask);
+ control_map_t::const_iterator iter = mControlsMap.find(control_name);
+ if (iter != mControlsMap.end())
+ {
+ return iter->second.canHandle(mouse_ind, key, mask);
+ }
+ return false;
}
-bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask)
+bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask) const
{
return canHandleControl(control_name, CLICK_NONE, key, mask);
}
-bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask)
+bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask) const
{
return canHandleControl(control_name, mouse_ind, KEY_NONE, mask);
}
-bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask)
+bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask) const
{
return canHandleControl(control_name, (EMouseClickType)mouse_ind, KEY_NONE, mask);
}
-bool LLKeyConflictHandler::canAssignControl(const std::string &control_name)
+bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) const
{
- control_map_t::iterator iter = mControlsMap.find(control_name);
+ control_map_t::const_iterator iter = mControlsMap.find(control_name);
if (iter != mControlsMap.end())
{
return iter->second.mAssignable;
@@ -238,6 +244,8 @@ std::string LLKeyConflictHandler::getStringFromKeyData(const LLKeyData& keydata)
result += LLKeyboard::stringFromMouse(keydata.mMouse);
+ result += LLGameControl::controllerInputStringFromAction((LLGameControl::ActionType)keydata.mControllerActionType, keydata.mControllerAction);
+
return result;
}
@@ -284,12 +292,25 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymod
LLKeyboard::keyFromString(it->key, &key);
}
LLKeyboard::maskFromString(it->mask, &mask);
- // Note: it->command is also the name of UI element, howhever xml we are loading from
+ // Note: it->command is also the name of UI element, however xml we are loading from
// might not know all the commands, so UI will have to know what to fill by its own
// Assumes U32_MAX conflict mask, and is assignable by default,
// but assignability might have been overriden by generatePlaceholders.
LLKeyConflict &type_data = (*destination)[it->command];
- type_data.mKeyBind.addKeyData(mouse, key, mask, true);
+
+ if (it->controller.isProvided() && !it->controller.getValue().empty())
+ {
+ LLGameControl::ActionType actionType = LLGameControl::ActionType::NONE;
+ U8 action = 0;
+ if(LLGameControl::actionFromString(it->controller.getValue(),actionType, action))
+ {
+ type_data.mKeyBind.addKeyData(LLKeyData((U8)actionType, action));
+ }
+ }
+ else
+ {
+ type_data.mKeyBind.addKeyData(mouse, key, mask, true);
+ }
}
}
@@ -338,6 +359,13 @@ bool LLKeyConflictHandler::loadFromSettings(const ESourceMode &load_mode, const
res = true;
}
break;
+ case MODE_FLYCAM:
+ if (keys.flycam.isProvided())
+ {
+ loadFromSettings(keys.flycam, destination);
+ res = true;
+ }
+ break;
default:
LL_ERRS() << "Not implememted mode " << load_mode << LL_ENDL;
break;
@@ -513,6 +541,14 @@ void LLKeyConflictHandler::saveToSettings(bool temporary)
// just copy old keys.xml and rename to key_bindings.xml, it should work
binding.mouse.set(LLKeyboard::stringFromMouse(data.mMouse, false), true);
}
+ if(data.mControllerActionType > LLGameControl::ActionType::BUTTON)
+ {
+ binding.controller.setProvided(false);
+ }
+ else
+ {
+ binding.controller.set(LLGameControl::stringFromAction((LLGameControl::ActionType)(data.mControllerActionType), data.mControllerAction));
+ }
binding.command = iter->first;
mode.bindings.add(binding);
}
@@ -544,6 +580,14 @@ void LLKeyConflictHandler::saveToSettings(bool temporary)
keys.sitting.bindings.set(mode.bindings, true);
}
break;
+ case MODE_FLYCAM:
+ // Unlike the long-established modes above, 'flycam' is a new
+ // block: a key_bindings.xml written before this mode existed
+ // has no <flycam> tag at all, so isProvided() would be false
+ // forever and this mode's bindings would never get written
+ // back out. Therefore set it unconditionally.
+ keys.flycam.bindings.set(mode.bindings, true);
+ break;
default:
LL_ERRS() << "Not implememted mode " << mLoadMode << LL_ENDL;
break;
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index 6c01ddb7a7..c813544422 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -44,7 +44,7 @@ public:
LLKeyData getKeyData(U32 index) { return mKeyBind.getKeyData(index); }
void setPrimaryKeyData(const LLKeyData& data) { mKeyBind.replaceKeyData(data, 0); }
void setKeyData(const LLKeyData& data, U32 index) { mKeyBind.replaceKeyData(data, index); }
- bool canHandle(EMouseClickType mouse, KEY key, MASK mask) { return mKeyBind.canHandle(mouse, key, mask); }
+ bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const { return mKeyBind.canHandle(mouse, key, mask); }
LLKeyBind mKeyBind;
bool mAssignable; // whether user can change key or key simply acts as placeholder
@@ -61,6 +61,7 @@ public:
MODE_THIRD_PERSON,
MODE_EDIT_AVATAR,
MODE_SITTING,
+ MODE_FLYCAM,
MODE_SAVED_SETTINGS, // for settings from saved settings
MODE_COUNT
};
@@ -76,11 +77,11 @@ public:
LLKeyConflictHandler(ESourceMode mode);
~LLKeyConflictHandler();
- bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask);
- bool canHandleKey(const std::string &control_name, KEY key, MASK mask);
- bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask);
- bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask); //Just for convinience
- bool canAssignControl(const std::string &control_name);
+ bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) const;
+ bool canHandleKey(const std::string &control_name, KEY key, MASK mask) const;
+ bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask) const;
+ bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask) const; //Just for convenience
+ bool canAssignControl(const std::string &control_name) const;
static bool isReservedByMenu(const KEY &key, const MASK &mask);
static bool isReservedByMenu(const LLKeyData &data);
diff --git a/indra/newview/llpanelpreferencegamecontrol.cpp b/indra/newview/llpanelpreferencegamecontrol.cpp
new file mode 100755
index 0000000000..43d26356ec
--- /dev/null
+++ b/indra/newview/llpanelpreferencegamecontrol.cpp
@@ -0,0 +1,2200 @@
+/**
+ * @file llfloaterpreference.cpp
+ * @brief Global preferences with and without persistence.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+/*
+ * App-wide preferences. Note that these are not per-user,
+ * because we need to load many preferences before we have
+ * a login name.
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelpreferencegamecontrol.h"
+
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llsliderctrl.h"
+#include "lltabcontainer.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+
+
+namespace
+{
+ // Singleton instance pointer - only one game control panel exists at a time
+ static LLPanelPreferenceGameControl* sGameControlPanel { nullptr };
+
+ // Track current UI selection state for input/output channel assignment.
+ // When user clicks a cell to change its mapping, these track which cell is being edited.
+ static LLScrollListCtrl* sSelectedGrid { nullptr };
+ static LLScrollListItem* sSelectedItem { nullptr };
+ static LLScrollListCell* sSelectedCell { nullptr };
+ static S32 sSelectedRow { -1 };
+ static S32 sSelectedCol { -1 };
+ static LLRect sSelectedOpenRect;
+
+ // The combobox popup currently overlaying sSelectedCell (one of the four
+ // action-mapping/output selectors below). Stashed so applyGameControlInput()
+ // can drive it (and reuse onCommitInputChannel()) without having to re-derive
+ // which selector initCombobox() chose.
+ static LLComboBox* sSelectedCombobox { nullptr };
+
+ // The selector combobox overlays the edited cell, but its drop-down button
+ // texture is semi-transparent, so the cell's own text shows through and
+ // "doubles" with the selector's label. While a selector is open we blank
+ // the cell's text and stash its value here, restoring it when the selector
+ // closes (see initCombobox / clearSelectionState).
+ static LLSD sSelectedCellValue;
+
+ // Selector items use the label "None" for the unmapped entry.
+ // Table cells should render that as a blank cell rather than the word.
+ const std::string NONE_LABEL("None");
+
+ // Kinds of action mapping, used both as the LLGameControl mapping key and as
+ // the block discriminator stored in each action-table row's value.
+ const std::string MODE_INPUT_TYPE_AXES("Axes");
+ const std::string MODE_INPUT_TYPE_BUTTONS("Buttons");
+ const std::string MODE_INPUT_TYPE_AXES_INVERT("AxesInvert");
+
+ LLSD blankIfNone(const LLSD& label)
+ {
+ return label.asString() == NONE_LABEL ? LLSD() : label;
+ }
+
+ // SecondLife-game-control glyph(s) for a canonical controller input value.
+ // Codepoints are from the SecondLife-game-control package's promptfont.h,
+ // preferring the generic vendor-neutral "gamepad"/"dpad"/"analog" sets and
+ // falling back to the Xbox set for shoulders/triggers (no generic equivalents
+ // exist). Rendered with the "SecondLife-game-control" family declared in
+ // fonts.xml. Inputs with no entry (e.g. BUTTON_21..31, *_NONE) return empty
+ // and keep their text label.
+ std::string promptFontGlyph(const std::string& input_value)
+ {
+ static const std::map<std::string, LLWString> sGlyphs = {
+ // Face buttons
+ { "BUTTON_SOUTH", { 0x21A7 } }, // PF_GAMEPAD_A (bottom)
+ { "BUTTON_EAST", { 0x21A6 } }, // PF_GAMEPAD_B (right)
+ { "BUTTON_WEST", { 0x21A4 } }, // PF_GAMEPAD_X (left)
+ { "BUTTON_NORTH", { 0x21A5 } }, // PF_GAMEPAD_Y (top)
+ // D-pad
+ { "BUTTON_DPAD_UP", { 0x219F } }, // PF_DPAD_UP
+ { "BUTTON_DPAD_DOWN", { 0x21A1 } }, // PF_DPAD_DOWN
+ { "BUTTON_DPAD_LEFT", { 0x219E } }, // PF_DPAD_LEFT
+ { "BUTTON_DPAD_RIGHT", { 0x21A0 } }, // PF_DPAD_RIGHT
+ // Shoulders / stick clicks
+ { "BUTTON_LEFT_SHOULDER", { 0x2198 } }, // PF_XBOX_LEFT_SHOULDER
+ { "BUTTON_RIGHT_SHOULDER", { 0x2199 } }, // PF_XBOX_RIGHT_SHOULDER
+ { "BUTTON_LEFT_STICK", { 0x21BA } }, // PF_ANALOG_L_CLICK (L3)
+ { "BUTTON_RIGHT_STICK", { 0x21BB } }, // PF_ANALOG_R_CLICK (R3)
+ // Menu cluster
+ { "BUTTON_SELECT", { 0x21F7 } }, // PF_GAMEPAD_SELECT (menu left)
+ { "BUTTON_HOME", { 0x21F9 } }, // PF_GAMEPAD_HOME (menu middle)
+ { "BUTTON_START", { 0x21F8 } }, // PF_GAMEPAD_START (menu right)
+ // Misc / paddles / touchpad
+ { "BUTTON_15", { 0x2212 } }, // PF_GAMEPAD_M1 (Misc1)
+ { "BUTTON_PADDLE1", { 0x2277 } }, // PF_GAMEPAD_R4
+ { "BUTTON_PADDLE2", { 0x2276 } }, // PF_GAMEPAD_L4
+ { "BUTTON_PADDLE3", { 0x2279 } }, // PF_GAMEPAD_R5
+ { "BUTTON_PADDLE4", { 0x2278 } }, // PF_GAMEPAD_L5
+ { "BUTTON_TOUCHPAD", { 0x21E7 } }, // PF_SONY_TOUCHPAD
+ // Axes
+ { "AXIS_LEFTX", { 0x21C4 } }, // PF_ANALOG_L_LEFT_RIGHT
+ { "AXIS_LEFTY", { 0x21C5 } }, // PF_ANALOG_L_UP_DOWN
+ { "AXIS_RIGHTX", { 0x21C6 } }, // PF_ANALOG_R_LEFT_RIGHT
+ { "AXIS_RIGHTY", { 0x21F5 } }, // PF_ANALOG_R_UP_DOWN
+ { "AXIS_LEFT_TRIGGER", { 0x2196 } }, // PF_XBOX_LEFT_TRIGGER
+ { "AXIS_RIGHT_TRIGGER", { 0x2197 } }, // PF_XBOX_RIGHT_TRIGGER
+ // Combined trigger pair: show both trigger glyphs side by side.
+ { "AXIS_TRIGGERS", { 0x2196, 0x2197 } },
+ };
+ auto it = sGlyphs.find(input_value);
+ if (it == sGlyphs.end())
+ {
+ return LLStringUtil::null;
+ }
+ return wstring_to_utf8str(it->second);
+ }
+
+ // The SecondLife-game-control glyphs live on real Unicode arrow codepoints,
+ // so they must be drawn with the dedicated SecondLife-game-control family
+ // rather than the default text font. Sized larger than the SansSerif rows
+ // so the icons read clearly.
+ const LLFontGL* promptFontForCell()
+ {
+ return LLFontGL::getFont(LLFontDescriptor("SecondLife-game-control", "Huge", 0));
+ }
+}
+
+ static LLRect computeCellScreenRect(LLScrollListCtrl* grid, LLView* relative_to, S32 row_index, S32 col_index);
+
+// Static entry point called when device list changes (device connected/disconnected).
+// Delegates to the singleton instance if it exists.
+void LLPanelPreferenceGameControl::updateDeviceList()
+{
+ if (sGameControlPanel)
+ {
+ sGameControlPanel->updateDeviceListInternal();
+ }
+}
+
+// Constructor - registers this instance as the singleton
+LLPanelPreferenceGameControl::LLPanelPreferenceGameControl()
+{
+ sGameControlPanel = this;
+}
+
+// Destructor - clears singleton pointer
+LLPanelPreferenceGameControl::~LLPanelPreferenceGameControl()
+{
+ sGameControlPanel = nullptr;
+}
+
+static LLPanelInjector<LLPanelPreferenceGameControl> t_pref_game_control("panel_preference_game_control");
+
+// Snapshot the panel's UI state as the single "GameControl" setting.
+// The returned map can be persisted (saveSettings) or applied directly to
+// LLGameControl runtime state via LLGameControl::applySettingsFromLLSD().
+LLSD LLPanelPreferenceGameControl::getSettingsAsLLSD()
+{
+ // Fold each device's current options into GameControl/Devices/<guid>/Config.
+ // The global per-mode action mappings are already live in LLGameControl (edited
+ // via its accessors), so snapshotting the whole GameControl structure captures both.
+ for (auto& [guid, device] : mDeviceOptions)
+ {
+ // force_empty=true: persist every known device's name even when its
+ // options are still at defaults, so "Show all known devices" can find
+ // it again after it's unplugged.
+ device.settings = device.options.saveToString(device.name, true);
+ LLGameControl::setDeviceConfig(guid, device.settings);
+ }
+
+ LLSD result = LLSD::emptyMap();
+ result["GameControl"] = LLGameControl::getGameControlSettings();
+ return result;
+}
+
+// Saves current UI state to settings by pushing the "GameControl" snapshot
+// (global action mappings + per-device Config) into gSavedSettings.
+void LLPanelPreferenceGameControl::saveSettings()
+{
+ LLPanelPreference::saveSettings();
+
+ if (mOrigSettings.isEmpty())
+ {
+ rememberOriginalSettings();
+ }
+
+ // Push every entry of the snapshot into gSavedSettings, also tracking
+ // the new value in mSavedValues so the base panel's accounting stays in sync.
+ LLSD settings = getSettingsAsLLSD();
+ for (auto it = settings.beginMap(); it != settings.endMap(); ++it)
+ {
+ if (LLControlVariable* control = gSavedSettings.getControl(it->first))
+ {
+ control->set(it->second);
+ mSavedValues[control] = control->getValue();
+ }
+ }
+}
+
+// Handles row selection in the Actions table. If the user clicked the editable
+// Input column of a real (non-spacer) row, shows the appropriate input selector.
+void LLPanelPreferenceGameControl::onGridSelect(LLUICtrl* ctrl)
+{
+ clearSelectionState();
+
+ LLScrollListCtrl* table = dynamic_cast<LLScrollListCtrl*>(ctrl);
+ if (!table || !table->getEnabled())
+ return;
+
+ // Deselect everything in the other scroll_list
+ LLScrollListCtrl* sibling = (table == mActionMappingsAxes) ? mActionMappingsButtons : mActionMappingsAxes;
+ sibling->deselectAllItems(true);
+
+ if (LLScrollListItem* item = table->getFirstSelected())
+ {
+ if (table == mActionMappingsAxes)
+ {
+ // Always sync the Invert checkbox -- clicking it selects the row (firing
+ // this same commit callback) but doesn't itself persist the new value.
+ // Only meaningful when the row has a real axis mapped (the checkbox is
+ // disabled and inert otherwise, matching populateActionMappings()).
+ std::string mode = currentEditMode();
+ LLSD row_value = item->getValue();
+ std::string action = row_value["action"].asString();
+ LLSD mapping = LLGameControl::getModeMapping(mode, MODE_INPUT_TYPE_AXES);
+ std::string input_value = mapping.has(action) ? mapping[action].asString() : LLStringUtil::null;
+ std::string none_value = mAxisInputSelector->getAllData().back()->getValue().asString();
+ if (!input_value.empty() && input_value != none_value)
+ {
+ S32 invert_col = mActionMappingsAxes->getColumn("invert")->mIndex;
+ LLGameControl::setAxisInvert(mode, action, item->getColumn(invert_col)->getValue().asBoolean());
+ }
+ }
+
+ // Try to show combobox for editing; if not applicable, deselect
+ if (initCombobox(item, table))
+ return;
+
+ table->deselectAllItems();
+ }
+}
+
+// Initializes and displays the appropriate combobox over the selected cell.
+// Chooses the combobox and editable column from the table and (for the Actions
+// table) the row's block input_type. Returns true if a combobox was shown, false if the
+// click wasn't on an editable cell.
+bool LLPanelPreferenceGameControl::initCombobox(LLScrollListItem* item, LLScrollListCtrl* grid)
+{
+ LLComboBox* combobox = nullptr;
+ S32 col = -1;
+
+ if (grid == mActionMappingsAxes || grid == mActionMappingsButtons)
+ {
+ // Two editable columns map to the same input: the SecondLife-game-control
+ // icon column (1) opens the glyph selector, the text description column
+ // (2) opens the text selector. Both commit through onCommitInputChannel,
+ // which rebuilds the row so the icon and description update together.
+ LLSD row_value = item->getValue();
+ if (!row_value.isMap())
+ return false;
+ bool axes = (grid == mActionMappingsAxes);
+ S32 sel = item->getSelectedCell();
+ if (sel == 1)
+ {
+ combobox = axes ? mAxisInputGlyphSelector : mButtonInputGlyphSelector;
+ }
+ else if (sel == 2)
+ {
+ combobox = axes ? mAxisInputSelector : mButtonInputSelector;
+ }
+ else
+ {
+ return false;
+ }
+ col = sel;
+ }
+ else if (grid == mAxisChannels)
+ {
+ // Two editable columns map to the same output: the SecondLife-game-control
+ // icon column ("output") opens the glyph selector, the text column
+ // ("output_description") opens the text selector. Both commit through
+ // onCommitInputChannel, which refreshes both cells so the icon and
+ // description stay in sync. The Input columns are the fixed physical axis
+ // and are not editable.
+ S32 sel = item->getSelectedCell();
+ S32 desc_col = grid->getColumn("output_description")->mIndex;
+ S32 glyph_col = grid->getColumn("output")->mIndex;
+ if (sel == glyph_col)
+ {
+ combobox = mAxisOutputGlyphSelector;
+ }
+ else if (sel == desc_col)
+ {
+ combobox = mAxisOutputSelector;
+ }
+ else
+ {
+ return false;
+ }
+ col = sel;
+ }
+ else if (grid == mButtonChannels)
+ {
+ // Two editable columns map to the same output: the SecondLife-game-control
+ // icon column ("output") opens the glyph selector, the text column
+ // ("output_description") opens the text selector. Both commit through
+ // onCommitInputChannel, which refreshes both cells so the icon and
+ // description stay in sync. The Input columns are the fixed physical
+ // button and are not editable.
+ S32 sel = item->getSelectedCell();
+ S32 desc_col = grid->getColumn("output_description")->mIndex;
+ S32 glyph_col = grid->getColumn("output")->mIndex;
+ if (sel == glyph_col)
+ {
+ combobox = mButtonInputGlyphSelector;
+ }
+ else if (sel == desc_col)
+ {
+ combobox = mButtonInputSelector;
+ }
+ else
+ {
+ return false;
+ }
+ col = sel;
+ }
+
+ if (!combobox)
+ return false;
+
+ LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(col));
+ if (!cell)
+ return false;
+
+ // compute new rect for combobox
+ S32 row_index = grid->getItemIndex(item);
+ fitInRect(combobox, grid, row_index, col);
+ sSelectedRow = row_index;
+ sSelectedCol = col;
+ sSelectedOpenRect = computeCellScreenRect(grid, combobox->getParent(), row_index, col);
+
+
+ // Pre-select the item matching the cell's current input.
+ std::string value;
+ if (grid == mActionMappingsAxes || grid == mActionMappingsButtons)
+ {
+ // Use the action's stored mapping value directly, so pre-selection is
+ // correct even when the icon cell is blank (input has no glyph).
+ LLSD row_value = item->getValue();
+ LLSD mapping = LLGameControl::getModeMapping(currentEditMode(), row_value["input_type"].asString());
+ std::string action = row_value["action"].asString();
+ value = mapping.has(action) ? mapping[action].asString() : LLStringUtil::null;
+ }
+ else
+ {
+ // Device tables: match the cell's current text against the selector items
+ // (works regardless of the value naming scheme).
+ std::string cell_value = cell->getValue();
+ for (const LLScrollListItem* combo_item : combobox->getAllData())
+ {
+ if (combo_item->getColumn(0)->getValue().asString() == cell_value)
+ {
+ value = combo_item->getValue().asString();
+ break;
+ }
+ }
+ }
+ if (value.empty())
+ {
+ // No match (e.g. a blank "None" cell): select the last item, which is "None".
+ value = combobox->getAllData().back()->getValue().asString();
+ }
+
+ combobox->setValue(value);
+ combobox->setVisible(true);
+ combobox->showList();
+
+ sSelectedGrid = grid;
+ sSelectedItem = item;
+ sSelectedCell = cell;
+ sSelectedCombobox = combobox;
+
+ // Hide the cell's text under the (translucent) selector so it doesn't
+ // double with the selector's label; clearSelectionState() restores it.
+ sSelectedCellValue = cell->getValue();
+ cell->setValue(LLSD());
+
+ return true;
+}
+
+// Called when the user selects a value from an input/output selector combobox.
+// The originating grid determines the meaning: Actions table -> action mapping;
+// axis/button channels table -> per-device physical-to-canonical remap.
+void LLPanelPreferenceGameControl::onCommitInputChannel(LLUICtrl* ctrl)
+{
+ if (!sSelectedGrid || !sSelectedItem || !sSelectedCell)
+ return;
+
+ LLComboBox* combobox = dynamic_cast<LLComboBox*>(ctrl);
+ llassert(combobox);
+ if (!combobox)
+ return;
+
+ // Editing an action mapping can change whether the input cell shows a text
+ // label or a SecondLife-game-control glyph, which means recreating the cell
+ // with the right font; remember to rebuild the action tables once the commit
+ // is applied.
+ bool action_grid_edited = (sSelectedGrid == mActionMappingsAxes || sSelectedGrid == mActionMappingsButtons);
+ // Editing an axis- or button-channels output likewise changes both its text and
+ // icon cells, so both are refreshed from the device map once the commit is applied.
+ bool axis_channels_edited = (sSelectedGrid == mAxisChannels);
+ bool button_channels_edited = (sSelectedGrid == mButtonChannels);
+
+ if (sSelectedGrid == mActionMappingsAxes || sSelectedGrid == mActionMappingsButtons)
+ {
+ // The edited row identifies the action + block; the combobox supplies the input.
+ LLSD row_value = sSelectedItem->getValue();
+ std::string mode = currentEditMode();
+ std::string input_type = row_value["input_type"].asString();
+ std::string action = row_value["action"].asString();
+ const LLComboBox* input_selector = (input_type == MODE_INPUT_TYPE_AXES) ? mAxisInputSelector : mButtonInputSelector;
+ std::string input_value = combobox->getValue().asString();
+ std::string input_label = combobox->getSelectedItemLabel();
+
+ if (input_label != NONE_LABEL && isFlycamRollDisallowed(mode, action))
+ {
+ // Roll/Unroll are unavailable while "Allow Roll" is off: refuse to
+ // create a new mapping. Clearing to None (input_label == NONE_LABEL)
+ // still falls through below, so an existing mapping remains removable.
+ // clearSelectionState() (below) restores the cell's pre-edit text.
+ }
+ else
+ {
+ if (input_label != NONE_LABEL)
+ {
+ // An input can drive at most one action within a block: clear it elsewhere.
+ removeDuplicateActionInput(mode, input_type, action, input_value, input_selector);
+ }
+
+ // Store the mapping directly in LLGameControl's live GameControl settings.
+ // gSavedSettings is updated later via saveSettings() when the user clicks OK.
+ LLGameControl::updateModeMapping(mode, input_type, action, input_value);
+ sSelectedCell->setValue(blankIfNone(input_label));
+ }
+ }
+ else if (sSelectedGrid == mAxisChannels)
+ {
+ // The row is a physical axis; the selected item's value names the output it
+ // maps to: an individual canonical axis, "Triggers left/right" (the fan-out
+ // pair), or "None". Output codes are resolved by LLGameControl so the panel
+ // stays agnostic of the axis-map encoding.
+ S32 axis = mAxisChannels->getItemIndex(sSelectedItem);
+ std::string output_name = combobox->getValue().asString();
+ LLGameControl::Options& options = getSelectedDeviceOptions();
+ options.getAxisMap()[axis] = LLGameControl::axisOutputFromName(output_name);
+ LLGameControl::setDeviceOptions(mSelectedDeviceGUID, options);
+ // Both output cells (icon + description) are re-rendered from the actual
+ // map by populateAxisChannelsCells() below.
+ }
+ else if (sSelectedGrid == mButtonChannels)
+ {
+ // The row is a physical button; the selected item's index is the canonical
+ // button it maps to. "None" (index >= NUM_BUTTONS) is not a valid output.
+ S32 button = mButtonChannels->getItemIndex(sSelectedItem);
+ S32 output = combobox->getCurrentIndex();
+ LLGameControl::Options& options = getSelectedDeviceOptions();
+ if (output >= 0 && output < (S32)LLGameControl::NUM_BUTTONS)
+ {
+ options.getButtonMap()[button] = (U8)output;
+ LLGameControl::setDeviceOptions(mSelectedDeviceGUID, options);
+ }
+ // Both output cells (icon + description) are re-rendered from the actual
+ // map by populateButtonChannelsCells() below.
+ }
+
+ // The branches above set the cell to its committed value; keep the
+ // restore-on-close value in sync so clearSelectionState() doesn't revert
+ // the cell back to its pre-edit text.
+ sSelectedCellValue = sSelectedCell->getValue();
+
+ sSelectedGrid->deselectAllItems();
+ clearSelectionState();
+
+ // Rebuild the action tables so a newly bound (or unbound) button action is
+ // re-rendered with the correct cell font -- text label vs SecondLife-game-control
+ // glyph.
+ if (action_grid_edited)
+ {
+ populateActionMappings();
+ }
+
+ // Refresh the axis-/button-channels output cells so the committed output's text
+ // label and SecondLife-game-control glyph are both re-rendered from the device map.
+ if (axis_channels_edited)
+ {
+ populateAxisChannelsCells();
+ }
+ if (button_channels_edited)
+ {
+ populateButtonChannelsCells();
+ }
+}
+
+// Returns true if a cell is currently selected and waiting for input channel assignment.
+// Used to determine whether to capture live controller input.
+bool LLPanelPreferenceGameControl::isWaitingForInputChannel()
+{
+ return sSelectedCell != nullptr;
+}
+
+// Static method called in the mainloop when an Action Mappings input selector is open.
+// Refreshes the canonical controller state, and if the user is pressing a button or
+// tilting an axis that matches the input_type of selector open (button vs. axis), assigns
+// it to the selected cell as if the user had picked it from the dropdown.
+void LLPanelPreferenceGameControl::applyGameControlInput()
+{
+ if (!sGameControlPanel || !sSelectedCombobox)
+ return;
+
+ bool wants_axis = (sSelectedGrid == sGameControlPanel->mActionMappingsAxes);
+ bool wants_button = (sSelectedGrid == sGameControlPanel->mActionMappingsButtons);
+ if (!wants_axis && !wants_button)
+ return;
+
+ // Recompute the canonical controller state from the live device input without
+ // triggering the normal "send to server" bookkeeping (see computeFinalStateAndCheckForChanges()),
+ // since input used to configure a mapping should not drive the avatar or the network.
+ LLGameControl::computeFinalState();
+
+ LLGameControl::InputChannel channel = LLGameControl::getActiveInputChannel();
+ if (wants_axis && !channel.isAxis())
+ return;
+ if (wants_button && !channel.isButton())
+ return;
+
+ std::string value = channel.getRemoteName();
+ if (!sSelectedCombobox->setSelectedByValue(value, true))
+ {
+ // The action-mapping axis selector has no entries for the individual
+ // trigger axes: it collapses them into one virtual "Triggers" item
+ // (see AXIS_TRIGGERS in panel_preferences_game_control.xml).
+ if (value != "AXIS_LEFT_TRIGGER" && value != "AXIS_RIGHT_TRIGGER")
+ return;
+ if (!sSelectedCombobox->setSelectedByValue(std::string("AXIS_TRIGGERS"), true))
+ return;
+ }
+
+ sGameControlPanel->onCommitInputChannel(sSelectedCombobox);
+}
+
+// Handles selection in the axis-channels table (invert, deadzone, offset, output).
+// Syncs the invert flag immediately; shows the numeric editor for deadzone/offset,
+// or the axis selector popup for the Output column.
+void LLPanelPreferenceGameControl::onAxisChannelsSelect()
+{
+ clearSelectionState();
+
+ // Deselect everything in the other scroll_list
+ mButtonChannels->deselectAllItems(true);
+
+ if (LLScrollListItem* row = mAxisChannels->getFirstSelected())
+ {
+ // Only the Output columns (icon + description) are editable; initCombobox
+ // ignores the fixed Input columns. Axis tuning (invert/offset/dead zone)
+ // now lives on the Device State tab.
+ initCombobox(row, mAxisChannels);
+ }
+}
+
+// Handles selection in the (now editable) axis-state table on the Device State
+// tab. Syncs the Invert checkbox immediately and shows the numeric editor for the
+// Offset/Dead Zone columns. Edits target the state tab's selected device.
+void LLPanelPreferenceGameControl::onAxisStateSelect()
+{
+ clearSelectionState();
+
+ // Deselect everything in the other scroll_list
+ mButtonState->deselectAllItems(true);
+
+ auto options_it = mDeviceOptions.find(mStateSelectedDeviceGUID);
+ if (options_it == mDeviceOptions.end())
+ {
+ return;
+ }
+ LLGameControl::Options& deviceOptions = options_it->second.options;
+
+ if (LLScrollListItem* row = mAxisState->getFirstSelected())
+ {
+ S32 row_index = mAxisState->getItemIndex(row);
+
+ {
+ // Always sync invert checkbox - clicking the checkbox selects the row
+ // but doesn't automatically update the underlying option.
+ S32 invert_checkbox_column = axisStateColumn("invert");
+ bool invert = row->getColumn(invert_checkbox_column)->getValue().asBoolean();
+ S32 multiplier = invert ? -1 : 1;
+ if (multiplier != deviceOptions.getAxisOptions()[row_index].mMultiplier)
+ {
+ deviceOptions.getAxisOptions()[row_index].mMultiplier = multiplier;
+
+ if (row_index == LLGameControl::AXIS_LEFT_TRIGGER
+ || row_index == LLGameControl::AXIS_RIGHT_TRIGGER)
+ {
+ // The two trigger axes act as one bidirectional axis under the hood,
+ // so their inversion must stay in sync -- update the sibling axis's
+ // option and reflect the new state in its checkbox cell.
+ S32 other_row_index = row_index == LLGameControl::AXIS_LEFT_TRIGGER
+ ? LLGameControl::AXIS_RIGHT_TRIGGER
+ : LLGameControl::AXIS_LEFT_TRIGGER;
+ deviceOptions.getAxisOptions()[other_row_index].mMultiplier = multiplier;
+
+ if (LLScrollListItem* other_row = mAxisState->getItemByIndex(other_row_index))
+ {
+ other_row->getColumn(invert_checkbox_column)->setValue(invert);
+ }
+ }
+
+ LLGameControl::setDeviceOptions(mStateSelectedDeviceGUID, deviceOptions);
+ }
+ }
+
+ S32 offset_col = axisStateColumn("offset");
+ S32 dead_zone_col = axisStateColumn("dead_zone");
+ S32 column_index = row->getSelectedCell();
+ if (column_index == offset_col || column_index == dead_zone_col)
+ {
+ fitInRect(mNumericValueEditor, mAxisState, row_index, column_index);
+ if (column_index == dead_zone_col) // Dead Zone
+ {
+ mNumericValueEditor->setMinValue(0);
+ mNumericValueEditor->setMaxValue(LLGameControl::MAX_AXIS_DEAD_ZONE);
+ mNumericValueEditor->setValue(deviceOptions.getAxisOptions()[row_index].mDeadZone);
+ }
+ else // Offset
+ {
+ mNumericValueEditor->setMinValue(-LLGameControl::MAX_AXIS_OFFSET);
+ mNumericValueEditor->setMaxValue(LLGameControl::MAX_AXIS_OFFSET);
+ mNumericValueEditor->setValue(deviceOptions.getAxisOptions()[row_index].mOffset);
+ }
+ mNumericValueEditor->setVisible(true);
+ }
+ }
+}
+
+// Handles selection in the button-channels table. Only the Output columns (icon +
+// description) use a popup selector; the Input columns are fixed (the physical button).
+void LLPanelPreferenceGameControl::onButtonChannelsSelect()
+{
+ clearSelectionState();
+
+ // Deselect everything in the other scroll_list
+ mAxisChannels->deselectAllItems(true);
+
+ if (LLScrollListItem* row = mButtonChannels->getFirstSelected())
+ {
+ initCombobox(row, mButtonChannels);
+ }
+}
+
+// Called when user commits a numeric value (offset or dead zone) in the spin
+// control over the Device State tab's axis table. Validates and clamps the value,
+// then updates both the UI and the state device's options.
+void LLPanelPreferenceGameControl::onCommitNumericValue()
+{
+ auto options_it = mDeviceOptions.find(mStateSelectedDeviceGUID);
+ if (options_it == mDeviceOptions.end())
+ {
+ return;
+ }
+ LLGameControl::Options& deviceOptions = options_it->second.options;
+
+ if (LLScrollListItem* row = mAxisState->getFirstSelected())
+ {
+ S32 value = mNumericValueEditor->getValue().asInteger();
+ S32 row_index = mAxisState->getItemIndex(row);
+ S32 offset_col = axisStateColumn("offset");
+ S32 dead_zone_col = axisStateColumn("dead_zone");
+ S32 column_index = row->getSelectedCell();
+ llassert(column_index == offset_col || column_index == dead_zone_col);
+ if (column_index != offset_col && column_index != dead_zone_col)
+ return;
+
+ if (column_index == dead_zone_col) // Dead Zone
+ {
+ value = std::clamp<S32>(value, 0, LLGameControl::MAX_AXIS_DEAD_ZONE);
+ deviceOptions.getAxisOptions()[row_index].mDeadZone = (U16)value;
+ }
+ else // Offset
+ {
+ value = std::clamp<S32>(value, -LLGameControl::MAX_AXIS_OFFSET, LLGameControl::MAX_AXIS_OFFSET);
+ deviceOptions.getAxisOptions()[row_index].mOffset = (S16)value;
+ }
+ setNumericLabel(row->getColumn(column_index), value);
+ LLGameControl::setDeviceOptions(mStateSelectedDeviceGUID, deviceOptions);
+ }
+}
+
+// Initializes all UI controls and sets up callbacks.
+// Called once when the panel is first built from XML.
+bool LLPanelPreferenceGameControl::postBuild()
+{
+ // Send-to-server checkbox (on the Server Data sub-tab)
+ mCheckGameControlToServer = getChild<LLCheckBoxCtrl>("game_control_to_server");
+ mCheckGameControlToServer->setCommitCallback([this](LLUICtrl*, const LLSD&)
+ {
+ LLGameControl::setSendToServer(mCheckGameControlToServer->getValue());
+ });
+
+ getChild<LLTabContainer>("game_control_tabs")->setCommitCallback([this](LLUICtrl*, const LLSD&) { clearSelectionState(); });
+
+ mTabActions = getChild<LLPanel>("tab_action_mappings");
+ mTabDevices = getChild<LLPanel>("tab_device_mappings");
+
+ // Actions tab (global, per-mode). The mode items (Avatar/FlyCam/Captive) are
+ // defined in the XML; only one mode is visible at a time, with a single
+ // Enabled checkbox that tracks whichever mode is currently selected.
+ mActionMode = getChild<LLComboBox>("action_mode");
+ mActionMode->setCommitCallback([this](LLUICtrl*, const LLSD&) { onActionModeChanged(); });
+
+ mCheckActionModeEnabled = getChild<LLCheckBoxCtrl>("action_mode_enabled");
+ mCheckActionModeEnabled->setCommitCallback([this](LLUICtrl*, const LLSD&)
+ { onModeEnabledToggled(mCheckActionModeEnabled->getValue()); });
+
+ mCheckFlycamAllowRoll = getChild<LLCheckBoxCtrl>("flycam_allow_roll");
+ mCheckFlycamAllowRoll->setCommitCallback([this](LLUICtrl*, const LLSD&)
+ {
+ clearSelectionState();
+ LLGameControl::setFlycamRollAllowed(mCheckFlycamAllowRoll->getValue());
+ populateActionMappings();
+ });
+
+ // Shared by FlyCam, Mouselook, and Avatar: applies to whichever mode is being edited.
+ mSliderSpeedFactor = getChild<LLSliderCtrl>("speed_factor");
+ mSliderSpeedFactor->setCommitCallback([this](LLUICtrl*, const LLSD&)
+ { LLGameControl::setSpeedFactor(currentEditMode(), (F32)mSliderSpeedFactor->getValue().asReal()); });
+ mSpeedSlowLabel = getChild<LLTextBox>("speed_slow_label");
+ mSpeedFastLabel = getChild<LLTextBox>("speed_fast_label");
+
+ mCheckFlycamCrosshair = getChild<LLCheckBoxCtrl>("flycam_crosshair");
+ mCheckFlycamCrosshair->setCommitCallback([this](LLUICtrl*, const LLSD&)
+ { LLGameControl::setFlycamCrosshairEnabled(mCheckFlycamCrosshair->getValue()); });
+
+ mCheckFlycamHideCursor = getChild<LLCheckBoxCtrl>("flycam_hide_cursor");
+ mCheckFlycamHideCursor->setCommitCallback([this](LLUICtrl*, const LLSD&)
+ { LLGameControl::setFlycamHideCursorEnabled(mCheckFlycamHideCursor->getValue()); });
+
+ mRestoreActionsDefaults = getChild<LLButton>("restore_actions_defaults");
+ mRestoreActionsDefaults->setCommitCallback([this](LLUICtrl*, const LLSD&) { onResetActionsToDefaults(); });
+
+ mCurrentModeIndicator = getChild<LLTextBox>("current_mode_indicator");
+
+ mActionMappingsAxes = getChild<LLScrollListCtrl>("action_mappings_axes");
+ mActionMappingsAxes->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onGridSelect(ctrl); });
+
+ mActionMappingsButtons = getChild<LLScrollListCtrl>("action_mappings_buttons");
+ mActionMappingsButtons->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onGridSelect(ctrl); });
+
+ // Inputs tab (per-device)
+ mNoDeviceMessage = getChild<LLTextBox>("nodevice_message");
+ mDevicePrompt = getChild<LLTextBox>("device_prompt");
+ mDeviceList = getChild<LLComboBox>("device_list");
+ mCheckShowAllDevices = getChild<LLCheckBoxCtrl>("show_all_known_devices");
+ mPanelDeviceSettings = getChild<LLPanel>("device_settings");
+
+ mCheckShowAllDevices->setCommitCallback([this](LLUICtrl*, const LLSD&) { populateDeviceTitle(); });
+ mDeviceList->setCommitCallback([this](LLUICtrl*, const LLSD& value) { populateDeviceSettings(value); });
+
+ mRestoreDeviceDefaults = getChild<LLButton>("restore_device_defaults");
+ mRestoreDeviceDefaults->setCommitCallback([this](LLUICtrl*, const LLSD&) { onResetDeviceToDefaults(); });
+
+ mAxisChannels = getChild<LLScrollListCtrl>("axis_channels");
+ mAxisChannels->setCommitCallback([this](LLUICtrl*, const LLSD&) { onAxisChannelsSelect(); });
+
+ mButtonChannels = getChild<LLScrollListCtrl>("button_channels");
+ mButtonChannels->setCommitCallback([this](LLUICtrl*, const LLSD&) { onButtonChannelsSelect(); });
+
+ // Outputs tab (per device)
+ mTabDeviceState = getChild<LLPanel>("tab_device_options");
+ mStateNoDeviceMessage = getChild<LLTextBox>("state_nodevice_message");
+ mStateDevicePrompt = getChild<LLTextBox>("state_device_prompt");
+ mStateRemapNote = getChild<LLTextBox>("state_remap_note");
+ mStateDeviceList = getChild<LLComboBox>("options_device_list");
+ mPanelDeviceState = getChild<LLPanel>("device_state_settings");
+ mStateDeviceList->setCommitCallback([this](LLUICtrl*, const LLSD& value)
+ {
+ mStateSelectedDeviceGUID = value.asString();
+ clearSelectionState();
+ mCalibrating = false; // switching devices invalidates any in-progress calibration
+ populateAxisStateOptionCells(); // refresh invert/offset/dead-zone for the new device
+ });
+
+ mRestoreDeviceOptionsDefaults = getChild<LLButton>("restore_device_options_defaults");
+ mRestoreDeviceOptionsDefaults->setCommitCallback([this](LLUICtrl*, const LLSD&) { onResetDeviceOptionsToDefaults(); });
+
+ mAutoCalibrate = getChild<LLButton>("auto_calibrate");
+ mAutoCalibrate->setCommitCallback([this](LLUICtrl*, const LLSD&) { onAutoCalibrate(); });
+
+ mAxisState = getChild<LLScrollListCtrl>("axis_state");
+ // The axis-state table is now editable: its Invert/Offset/Dead Zone columns
+ // tune the state device's axis options while its Raw/Adjusted columns update live.
+ mAxisState->setCommitCallback([this](LLUICtrl*, const LLSD&) { onAxisStateSelect(); });
+ mButtonState = getChild<LLScrollListCtrl>("button_state");
+
+ // Data Output tab (live, read-only view of the last outgoing GameControlInput)
+ mTabDataOutput = getChild<LLPanel>("tab_server_data");
+ mDataOutput = getChild<LLScrollListCtrl>("data_output");
+
+ // Spin control for editing deadzone/offset values inline
+ mNumericValueEditor = getChild<LLSpinCtrl>("numeric_value_editor");
+ mNumericValueEditor->setCommitCallback([this](LLUICtrl*, const LLSD&) { onCommitNumericValue(); });
+
+ // Action selectors: provide the "Action" column rows, chosen by edit mode.
+ mAnalogActionSelector = getChild<LLComboBox>("analog_action_selector");
+ mBinaryActionSelector = getChild<LLComboBox>("binary_action_selector");
+ mMouselookAnalogActionSelector = getChild<LLComboBox>("mouselook_analog_action_selector");
+ mMouselookBinaryActionSelector = getChild<LLComboBox>("mouselook_binary_action_selector");
+ mFlycamAnalogActionSelector = getChild<LLComboBox>("flycam_analog_action_selector");
+ mFlycamBinaryActionSelector = getChild<LLComboBox>("flycam_binary_action_selector");
+ mCaptiveBinaryActionSelector = getChild<LLComboBox>("sit_binary_action_selector");
+ mCursorAnalogActionSelector = getChild<LLComboBox>("cursor_analog_action_selector");
+ mCursorBinaryActionSelector = getChild<LLComboBox>("cursor_binary_action_selector");
+
+ // Canonical input selectors, shown inline when editing an Input/Output cell.
+ // The Actions tab binds an axis action to a canonical input (sticks or the
+ // "Triggers left/right" pair) via mAxisInputSelector; the Devices tab maps a
+ // physical axis to an individual canonical axis via mAxisOutputSelector.
+ mAxisInputSelector = getChild<LLComboBox>("axis_input_selector");
+ mAxisInputSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); });
+
+ mAxisOutputSelector = getChild<LLComboBox>("axis_output_selector");
+ mAxisOutputSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); });
+
+ // Glyph counterpart of mAxisOutputSelector, shown when editing the
+ // SecondLife-game-control "output" (icon) column of the axis-channels table.
+ // Same values, rendered as SecondLife-game-control glyphs, so build it from
+ // the text selector's values.
+ mAxisOutputGlyphSelector = getChild<LLComboBox>("axis_output_glyph_selector");
+ mAxisOutputGlyphSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); });
+ buildInputGlyphSelector(mAxisOutputSelector, mAxisOutputGlyphSelector);
+
+ mButtonInputSelector = getChild<LLComboBox>("button_input_selector");
+ mButtonInputSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); });
+
+ // Glyph selectors shown when editing the SecondLife-game-control
+ // "Axis"/"Button" column. Their items mirror the text selectors' values, so
+ // build them from those.
+ mAxisInputGlyphSelector = getChild<LLComboBox>("axis_input_glyph_selector");
+ mAxisInputGlyphSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); });
+ buildInputGlyphSelector(mAxisInputSelector, mAxisInputGlyphSelector);
+
+ mButtonInputGlyphSelector = getChild<LLComboBox>("button_input_glyph_selector");
+ mButtonInputGlyphSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); });
+ buildInputGlyphSelector(mButtonInputSelector, mButtonInputGlyphSelector);
+
+ // The device tables' rows are static (one per physical axis/button); their
+ // cells are filled per-device. The action table is mode-specific and built
+ // in populateActionMappings() on open / mode change.
+ populateAxisChannelsRows();
+ populateButtonChannelsRows();
+
+ // The Device State tab's rows are static (one per physical axis/button); their
+ // Value cells are refreshed every frame in draw() from the selected device.
+ populateAxisStateRows();
+ populateButtonStateRows();
+
+ // The Data Output tab's rows are static (AXIS_0..5, a blank separator, then
+ // BUTTON_0..31); their Value cells are refreshed whenever a fresh
+ // GameControlInput message is sent (see updateDataOutput()).
+ populateDataOutputRows();
+
+ // Workaround for the common bug:
+ // LLScrollListCtrl with draw_heading="true" initially has incorrect mTop (17 px higher).
+ // Each scroll list fills a dedicated wrapper panel, so the corrected top is its
+ // parent's height - 1.
+ auto fixHeadingTop = [](LLScrollListCtrl* grid)
+ {
+ LLRect rect = grid->getRect();
+ rect.mTop = grid->getParent()->getRect().getHeight() - 1;
+ grid->setRect(rect);
+ grid->updateLayout();
+ };
+ fixHeadingTop(mActionMappingsAxes);
+ fixHeadingTop(mActionMappingsButtons);
+ fixHeadingTop(mAxisChannels);
+ fixHeadingTop(mButtonChannels);
+ fixHeadingTop(mAxisState);
+ fixHeadingTop(mButtonState);
+ fixHeadingTop(mDataOutput);
+
+ return true;
+}
+
+// Called when the preferences floater is opened.
+// Loads current LLGameControl state into UI controls and refreshes all tables.
+void LLPanelPreferenceGameControl::onOpen(const LLSD& key)
+{
+ // Sync checkbox with current LLGameControl state
+ mCheckGameControlToServer->setValue(LLGameControl::sendToServer());
+
+ clearSelectionState();
+
+ // Default to editing whichever mode is currently active in-world, so the
+ // panel opens already showing the mappings the user is presently driving
+ // with; fall back to Avatar (the first action_mode item) when no mode is
+ // active (CONTROL_MODE_NONE, e.g. not yet logged in).
+ LLGameControl::AgentControlMode live_mode = LLGameControl::getAgentControlMode();
+ if (live_mode == LLGameControl::CONTROL_MODE_NONE || !mActionMode->selectByValue((S32)live_mode))
+ {
+ mActionMode->selectFirstItem();
+ }
+ populateActionMappings();
+
+ // Refresh device list and settings
+ updateDeviceListInternal();
+
+ mCheckGameControlToServer->setEnabled(true);
+ mActionMappingsAxes->setEnabled(true);
+ mActionMappingsButtons->setEnabled(true);
+ mAxisChannels->setEnabled(true);
+ mButtonChannels->setEnabled(true);
+ mDeviceList->setEnabled(true);
+ mStateDeviceList->setEnabled(true);
+
+ // Apply the current mode's enable flag (must run after the blanket enables
+ // above): syncs the checkbox and locks the tables if the mode is disabled.
+ updateActionModeEnabledUI();
+
+ // Clear original settings - will be populated on first saveSettings() call
+ mOrigSettings = LLSD::emptyMap();
+}
+
+ static LLRect computeCellScreenRect(LLScrollListCtrl* grid, LLView* relative_to, S32 row_index, S32 col_index)
+ {
+ LLRect rect(grid->getCellRect(row_index, col_index));
+ LLView* parent = grid->getParent();
+ while (parent && parent != relative_to)
+ {
+ rect.translate(parent->getRect().mLeft, parent->getRect().mBottom);
+ parent = parent->getParent();
+ }
+ return rect;
+ }
+
+// Per-frame refresh of the Device State tab. Only touches the tables while that
+// tab is actually the visible one, so it costs nothing on the other tabs.
+void LLPanelPreferenceGameControl::draw()
+{
+ updateCurrentModeIndicator();
+ if (mTabDeviceState && mTabDeviceState->getVisible())
+ {
+ populateDeviceStateValues();
+ if (mCalibrating)
+ {
+ updateAutoCalibration();
+ }
+ }
+ if (sSelectedCombobox && sSelectedGrid && sSelectedRow >= 0 && sSelectedCol >= 0)
+ {
+ LLRect current_rect = computeCellScreenRect(sSelectedGrid, sSelectedCombobox->getParent(), sSelectedRow, sSelectedCol);
+ if (current_rect != sSelectedOpenRect)
+ {
+ clearSelectionState();
+ }
+ }
+
+ LLPanelPreference::draw();
+}
+
+// Called when user clicks OK. Clears selections and prepares for onClose()
+void LLPanelPreferenceGameControl::apply()
+{
+ LLPanelPreference::apply();
+ clearSelectionState();
+
+ // Clear mOrigSettings to prevent cancel() from reverting changes.
+ // Note: cancel() is called in onClose() even after OK, so we must clear this.
+ mOrigSettings = LLSD::emptyMap();
+
+ // Note: any settings changes have already been written to global-settings
+ // via the LLControlVariables assigned to the UI elements. LLGameControl has
+ // already loaded from global-settings in saveSettings().
+}
+
+// Called when user clicks Cancel. Restores all settings to their original values.
+void LLPanelPreferenceGameControl::cancel(const std::vector<std::string> settings_to_skip)
+{
+ LLPanelPreference::cancel(settings_to_skip);
+ clearSelectionState();
+
+ // Skip restore if original settings were cleared in apply().
+ if (mOrigSettings.isEmpty())
+ {
+ return;
+ }
+
+ // Restore in-memory state from the snapshot, then push back to gSavedSettings
+ // via the bulk save path so persistence stays consistent.
+ LLGameControl::applySettingsFromLLSD(mOrigSettings);
+ LLGameControl::saveToSettings();
+}
+
+// Rebuilds the internal device options map from LLGameControl state.
+// Merges saved options with currently connected devices.
+void LLPanelPreferenceGameControl::updateDeviceListInternal()
+{
+ mDeviceOptions.clear();
+
+ // Load saved device options from settings. Each device's saved Config is
+ // parsed independently -- one entry with a corrupted/hand-edited Config
+ // (loadFromString() returns false) falls back to default Options rather
+ // than being dropped or affecting any other device's entry in this loop.
+ for (const auto& [guid, options] : LLGameControl::getDeviceOptions())
+ {
+ DeviceOptions deviceOptions = { LLStringUtil::null, options, LLGameControl::Options() };
+ if (!deviceOptions.options.loadFromString(deviceOptions.name, deviceOptions.settings))
+ {
+ LL_WARNS("SDL3") << "Discarding invalid saved device options for '" << guid
+ << "'; using defaults instead" << LL_ENDL;
+ }
+ if (deviceOptions.name.empty())
+ {
+ // Parsing failed before reaching the saved name, or the saved
+ // Config simply never recorded one -- fall back to the guid so
+ // the device list never shows a blank title.
+ deviceOptions.name = guid;
+ }
+ mDeviceOptions.emplace(guid, deviceOptions);
+ }
+
+ // Add currently connected devices that don't have saved settings yet
+ for (const auto& device : LLGameControl::getDevices())
+ {
+ if (mDeviceOptions.find(device.getGUID()) == mDeviceOptions.end())
+ {
+ mDeviceOptions[device.getGUID()] = { device.getName(), device.saveOptionsToString(true), device.getOptions() };
+ }
+ }
+
+ mCheckShowAllDevices->setValue(false);
+ populateDeviceTitle();
+
+ // The Device State tab tracks the live set of connected devices too.
+ updateDeviceStateList();
+}
+
+// Updates the device selection UI based on available devices.
+// Shows single device name, dropdown list, or "no device" message as appropriate.
+void LLPanelPreferenceGameControl::populateDeviceTitle()
+{
+ mSelectedDeviceGUID.clear();
+
+ // "Show all devices" includes saved settings for disconnected devices
+ bool showAllDevices = mCheckShowAllDevices->getValue().asBoolean();
+ std::size_t deviceCount = showAllDevices ? mDeviceOptions.size() : LLGameControl::getDevices().size();
+
+ mNoDeviceMessage->setVisible(!deviceCount);
+ mDevicePrompt->setVisible(deviceCount);
+ mDeviceList->setVisible(deviceCount); // always use the combo box, even for one device
+ mPanelDeviceSettings->setVisible(deviceCount);
+ mRestoreDeviceDefaults->setVisible(deviceCount);
+
+ if (!deviceCount)
+ {
+ return;
+ }
+
+ auto makeTitle = [](const std::string& guid, const std::string& name) -> std::string
+ {
+ return guid + ", " + name;
+ };
+
+ auto makeListItem = [](const std::string& guid, const std::string& title)
+ {
+ return LLSD().with("value", guid).with("columns", LLSD().with("label", title));
+ };
+
+ mDeviceList->clear();
+ mDeviceList->clearRows();
+
+ if (showAllDevices)
+ {
+ for (const auto& [guid, device] : mDeviceOptions)
+ {
+ mDeviceList->addElement(makeListItem(guid, makeTitle(guid, device.name)));
+ }
+ }
+ else
+ {
+ for (const LLGameControl::Device& device : LLGameControl::getDevices())
+ {
+ mDeviceList->addElement(makeListItem(device.getGUID(), makeTitle(device.getGUID(), device.getName())));
+ }
+ }
+
+ mDeviceList->selectNthItem(0);
+ populateDeviceSettings(mDeviceList->getValue());
+}
+
+// Loads settings for the specified device into the device-channel tables.
+void LLPanelPreferenceGameControl::populateDeviceSettings(const std::string& guid)
+{
+ mSelectedDeviceGUID = guid;
+ llassert_always(mDeviceOptions.find(guid) != mDeviceOptions.end());
+
+ // Device tables are per-device (mode-independent).
+ populateAxisChannelsCells();
+ populateButtonChannelsCells();
+}
+
+// The mode string ("When moving Avatar"/"When moving FlyCam"/"When sitting"/
+// "When in mouselook") currently selected for editing.
+std::string LLPanelPreferenceGameControl::currentEditMode()
+{
+ S32 ordinal = mActionMode->getValue().asInteger();
+ return LLGameControl::getModeName((LLGameControl::AgentControlMode)ordinal);
+}
+
+// True for the FlyCam Roll actions, and for Unroll (which only undoes roll),
+// while "Allow Roll" is unchecked.
+bool LLPanelPreferenceGameControl::isFlycamRollDisallowed(const std::string& mode, const std::string& action)
+{
+ return mode == "FlyCam" && !LLGameControl::isFlycamRollAllowed()
+ && (action == "Roll CCW/CW" || action == "Roll CW" || action == "Roll CCW" || action == "Unroll");
+}
+
+// Picks the action selector supplying the "Action" rows for a block + mode.
+LLComboBox* LLPanelPreferenceGameControl::actionSelectorForMode(bool axis, const std::string& mode) const
+{
+ bool flycam = (mode == "FlyCam");
+ bool mouselook = (mode == "Mouselook");
+ bool cursor = (mode == "Cursor");
+ // Avatar and Captive share the same axis actions (see llgamecontrol.cpp);
+ // Mouselook and Cursor each have their own axis-action selector too, since
+ // Cursor swaps in "Mouse left/right"/"Mouse up/down" for Strafe/Advance.
+ // Each mode has its own button-action selector so their button sets can
+ // diverge (e.g. Captive swaps in "Stand" for "Jump", Cursor adds "Mouse
+ // click left/right").
+ if (axis)
+ return flycam ? mFlycamAnalogActionSelector
+ : mouselook ? mMouselookAnalogActionSelector
+ : cursor ? mCursorAnalogActionSelector
+ : mAnalogActionSelector;
+ if (mouselook)
+ return mMouselookBinaryActionSelector;
+ if (flycam)
+ return mFlycamBinaryActionSelector;
+ if (cursor)
+ return mCursorBinaryActionSelector;
+ return (mode == "Captive") ? mCaptiveBinaryActionSelector : mBinaryActionSelector;
+}
+
+// Rebuilds the two Actions tables for the current mode: axis actions in the top
+// table, button actions in the bottom table. Each row stores {input_type, action} as its
+// value and shows the action label + its currently-mapped input.
+void LLPanelPreferenceGameControl::populateActionMappings()
+{
+ mActionMappingsAxes->clearRows();
+ mActionMappingsButtons->clearRows();
+
+ std::string mode = currentEditMode();
+
+ auto addBlock = [&](LLScrollListCtrl* grid, const std::string& input_type,
+ const LLComboBox* action_selector, const LLComboBox* input_selector)
+ {
+ LLSD mapping = LLGameControl::getModeMapping(mode, input_type);
+ // Axes-only Invert column: -1 for the Buttons block (no such column there).
+ // The selector's last item is the "None" value (e.g. AXIS_NONE), used below
+ // to tell an unmapped row from a mapped one.
+ S32 invert_col = (input_type == MODE_INPUT_TYPE_AXES) ? grid->getColumn("invert")->mIndex : -1;
+ std::string none_value = input_selector->getAllData().back()->getValue().asString();
+
+ for (LLScrollListItem* item : action_selector->getAllData())
+ {
+ std::string action = item->getValue().asString();
+ if (action == NONE_LABEL) // skip the "None" sentinel; not an action row
+ continue;
+
+ // Current input bound to this action, and the SecondLife-game-control
+ // glyph to show instead of the text label, if this input has one.
+ std::string input_value = mapping.has(action) ? mapping[action].asString() : LLStringUtil::null;
+ std::string glyph = promptFontGlyph(input_value);
+
+ // Roll and Unroll stay mapped (and shown) while disallowed, but greyed
+ // out to match their lack of effect on flycam behavior until re-enabled.
+ // The row itself stays enabled/clickable so an existing mapping can
+ // still be cleared to None; onCommitInputChannel() refuses to set
+ // anything else while disallowed.
+ bool roll_disabled = isFlycamRollDisallowed(mode, action);
+
+ LLScrollListItem::Params row_params;
+ for (S32 c = 0; c < grid->getNumColumns(); ++c)
+ {
+ LLScrollListCell::Params cell_params;
+ const std::string& col_name = grid->getColumn(c)->mName;
+ cell_params.column = col_name;
+ // The icon column (1) renders the controller glyph in
+ // SecondLife-game-control font when this input has one; the action
+ // (0) and description (2) columns match the "Controls" preferences
+ // panel font.
+ cell_params.font = (c == 1 && !glyph.empty())
+ ? promptFontForCell()
+ : LLFontGL::getFontSansSerif();
+ if (c == invert_col)
+ {
+ cell_params.type = "checkbox";
+ cell_params.font_halign = "left"; // left-align the checkbox within the cell
+ }
+ row_params.columns.add(cell_params);
+ }
+
+ // Row value carries the block input_type and action key (used on commit/lookup).
+ LLSD row_value;
+ row_value["input_type"] = input_type;
+ row_value["action"] = action;
+ row_params.value = row_value;
+
+ LLScrollListItem* row = grid->addRow(row_params);
+ row->getColumn(0)->setValue(item->getColumn(0)->getValue()); // action label
+ // Columns 1 (icon) and 2 (description) both derive from input_value, so
+ // they always refer to the same controller input.
+ row->getColumn(1)->setValue(glyph.empty() ? LLSD() : LLSD(glyph));
+ row->getColumn(2)->setValue(blankIfNone(inputLabel(input_selector, input_value)));
+
+ if (invert_col >= 0)
+ {
+ // Disabled (and left at its last value) whenever no axis is mapped,
+ // since there is nothing to invert.
+ bool mapped = !input_value.empty() && input_value != none_value;
+ row->getColumn(invert_col)->setValue(LLGameControl::getAxisInvert(mode, action));
+ row->getColumn(invert_col)->setEnabled(mapped && !roll_disabled);
+ }
+
+ if (roll_disabled)
+ {
+ // Grey the text to signal "unavailable" without disabling the row,
+ // which would also block clicking an existing mapping to clear it.
+ LLColor4 disabled_color = LLUIColorTable::instance().getColor("LabelDisabledColor");
+ row->getColumn(0)->setColor(disabled_color);
+ row->getColumn(1)->setColor(disabled_color);
+ row->getColumn(2)->setColor(disabled_color);
+ }
+ }
+ };
+
+ addBlock(mActionMappingsAxes, MODE_INPUT_TYPE_AXES, actionSelectorForMode(true, mode), mAxisInputSelector);
+ addBlock(mActionMappingsButtons, MODE_INPUT_TYPE_BUTTONS, actionSelectorForMode(false, mode), mButtonInputSelector);
+}
+
+// Handles a change in the edit-mode selector: rebuild the action table.
+void LLPanelPreferenceGameControl::onActionModeChanged()
+{
+ clearSelectionState();
+ populateActionMappings();
+ updateActionModeEnabledUI();
+}
+
+// Toggle whether game-control input is converted to the currently-selected
+// mode's actions.
+void LLPanelPreferenceGameControl::onModeEnabledToggled(bool enabled)
+{
+ clearSelectionState();
+ LLGameControl::setModeEnabled(currentEditMode(), enabled);
+ updateActionModeEnabledUI();
+}
+
+// Sync the Enabled checkbox with the selected mode's stored flag (keeps it
+// correct after apply/cancel/reset and after switching modes) and lock/unlock
+// the action tables (and Restore Defaults) so a disabled mode's mappings can't change.
+void LLPanelPreferenceGameControl::updateActionModeEnabledUI()
+{
+ std::string mode = currentEditMode();
+ bool enabled = LLGameControl::isModeEnabled(mode);
+ mCheckActionModeEnabled->set(enabled);
+ // A disabled mode's tables grey out; onGridSelect() also refuses edits on a
+ // disabled table, so this both signals and enforces the lock.
+ mActionMappingsAxes->setEnabled(enabled);
+ mActionMappingsButtons->setEnabled(enabled);
+ mRestoreActionsDefaults->setEnabled(enabled);
+
+ // Roll, the crosshair, and cursor hiding are only meaningful for FlyCam, and the speed
+ // slider for FlyCam, Mouselook, and Avatar: hide them for every other mode.
+ bool is_flycam = (mode == "FlyCam");
+ bool has_speed_factor = is_flycam || (mode == "Mouselook") || (mode == "Avatar");
+ mCheckFlycamAllowRoll->setVisible(is_flycam);
+ mCheckFlycamCrosshair->setVisible(is_flycam);
+ mCheckFlycamHideCursor->setVisible(is_flycam);
+ mSliderSpeedFactor->setVisible(has_speed_factor);
+ mSpeedSlowLabel->setVisible(has_speed_factor);
+ mSpeedFastLabel->setVisible(has_speed_factor);
+ if (is_flycam)
+ {
+ mCheckFlycamAllowRoll->set(LLGameControl::isFlycamRollAllowed());
+ mCheckFlycamAllowRoll->setEnabled(enabled);
+ mCheckFlycamCrosshair->set(LLGameControl::isFlycamCrosshairEnabled());
+ mCheckFlycamCrosshair->setEnabled(enabled);
+ mCheckFlycamHideCursor->set(LLGameControl::isFlycamHideCursorEnabled());
+ mCheckFlycamHideCursor->setEnabled(enabled);
+ }
+ if (has_speed_factor)
+ {
+ mSliderSpeedFactor->setValue(LLGameControl::getSpeedFactor(mode));
+ mSliderSpeedFactor->setEnabled(enabled);
+ }
+}
+
+// Shows the live AgentControlMode independent of the mode being edited (mActionMode)
+void LLPanelPreferenceGameControl::updateCurrentModeIndicator()
+{
+ LLGameControl::AgentControlMode mode = LLGameControl::getAgentControlMode();
+ if (mode == mLastDrawnControlMode)
+ {
+ return; // no change, skip the string work
+ }
+ mLastDrawnControlMode = mode;
+
+ if (mCurrentModeIndicator)
+ {
+ static const std::map<LLGameControl::AgentControlMode, std::string> sDisplayNames = {
+ { LLGameControl::CONTROL_MODE_AVATAR, "Moving Avatar" },
+ { LLGameControl::CONTROL_MODE_MOUSELOOK, "Mouselook" },
+ { LLGameControl::CONTROL_MODE_FLYCAM, "FlyCam" },
+ { LLGameControl::CONTROL_MODE_CAPTIVE, "Sitting" },
+ { LLGameControl::CONTROL_MODE_CURSOR, "Mouse Cursor" },
+ };
+ auto it = sDisplayNames.find(mode);
+ std::string name = (it != sDisplayNames.end()) ? it->second : "None";
+ mCurrentModeIndicator->setText(std::string("Active mode: ") + name);
+ }
+}
+
+// Enforces that an input drives at most one action within a mode's block. When a
+// new (non-None) input is assigned to an action, any *other* action in the same
+// mode+input_type mapping that currently uses that same input is reset to "None"
+// (its Input cell blanked and its mapping set to the selector's None value).
+void LLPanelPreferenceGameControl::removeDuplicateActionInput(const std::string& mode,
+ const std::string& input_type, const std::string& keep_action, const std::string& input_value,
+ const LLComboBox* input_selector)
+{
+ // The selector's last item is the "None" value (e.g. AXIS_NONE / BUTTON_NONE).
+ std::string none_value = input_selector->getAllData().back()->getValue().asString();
+ LLSD mapping = LLGameControl::getModeMapping(mode, input_type);
+
+ LLScrollListCtrl* grid = (input_type == MODE_INPUT_TYPE_AXES) ? mActionMappingsAxes : mActionMappingsButtons;
+ for (LLScrollListItem* row : grid->getAllData())
+ {
+ LLSD row_value = row->getValue();
+ if (!row_value.isMap())
+ continue;
+
+ std::string action = row_value["action"].asString();
+ if (action == keep_action)
+ continue;
+
+ if (mapping.has(action) && mapping[action].asString() == input_value)
+ {
+ LLGameControl::updateModeMapping(mode, input_type, action, none_value);
+ row->getColumn(1)->setValue(LLSD()); // blank the Input cell
+ }
+ }
+}
+
+// Creates one row per physical axis in the axis-channels table. Columns:
+// input(glyph) | input_description | output_description | output(glyph). The two
+// Input columns are the fixed physical axis (icon + text); the two Output columns
+// are the canonical axis it maps to (icon + text), edited via popup selectors.
+// Axis tuning (invert/offset/dead zone) lives on the Device State tab.
+void LLPanelPreferenceGameControl::populateAxisChannelsRows()
+{
+ mAxisChannels->clearRows();
+
+ // The physical controller axes are the output selector's first NUM_AXES items,
+ // in order (item N == canonical axis N).
+ std::vector<LLScrollListItem*> items = mAxisOutputSelector->getAllData();
+
+ S32 input_glyph_col = mAxisChannels->getColumn("input")->mIndex;
+ S32 input_desc_col = mAxisChannels->getColumn("input_description")->mIndex;
+
+ LLScrollListItem::Params row_params;
+ LLScrollListCell::Params cell_params;
+ for (S32 i = 0; i < (S32)(mAxisChannels->getNumColumns()); ++i)
+ {
+ const std::string& name = mAxisChannels->getColumn(i)->mName;
+ // The icon columns ("input"/"output") render the controller glyph in
+ // SecondLife-game-control; the description columns match the "Controls"
+ // panel font.
+ cell_params.font = (name == "input" || name == "output")
+ ? promptFontForCell()
+ : LLFontGL::getFontSansSerif();
+ cell_params.column = name;
+ row_params.columns.add(cell_params);
+ }
+
+ for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i)
+ {
+ LLScrollListItem* row = mAxisChannels->addRow(row_params);
+ // The physical axis is fixed: fill both its text label and its glyph.
+ std::string glyph = promptFontGlyph(items[i]->getValue().asString());
+ row->getColumn(input_desc_col)->setValue(items[i]->getColumn(0)->getValue());
+ row->getColumn(input_glyph_col)->setValue(glyph.empty() ? LLSD() : LLSD(glyph));
+ }
+}
+
+// Fills the axis-channel Output cells (text description + SecondLife-game-control
+// glyph) from the current device's axis map.
+void LLPanelPreferenceGameControl::populateAxisChannelsCells()
+{
+ std::vector<LLScrollListItem*> rows = mAxisChannels->getAllData();
+ const LLGameControl::Options& options = getSelectedDeviceOptions();
+ const auto& axis_map = options.getAxisMap();
+
+ S32 output_desc_col = mAxisChannels->getColumn("output_description")->mIndex;
+ S32 output_glyph_col = mAxisChannels->getColumn("output")->mIndex;
+
+ for (size_t i = 0; i < rows.size() && i < axis_map.size(); ++i)
+ {
+ std::string output_name = LLGameControl::axisOutputName(axis_map[i]);
+ std::string glyph = promptFontGlyph(output_name);
+ rows[i]->getColumn(output_desc_col)->setValue(inputLabel(mAxisOutputSelector, output_name));
+ rows[i]->getColumn(output_glyph_col)->setValue(glyph.empty() ? LLSD() : LLSD(glyph));
+ }
+}
+
+// Creates one row per physical button in the button-channels table. Columns:
+// input(glyph) | input_description | output_description | output(glyph). The two
+// Input columns are the fixed physical button (icon + text); the two Output columns
+// are the canonical button it maps to (icon + text), edited via popup selectors.
+void LLPanelPreferenceGameControl::populateButtonChannelsRows()
+{
+ mButtonChannels->clearRows();
+
+ std::vector<LLScrollListItem*> items = mButtonInputSelector->getAllData();
+
+ S32 input_glyph_col = mButtonChannels->getColumn("input")->mIndex;
+ S32 input_desc_col = mButtonChannels->getColumn("input_description")->mIndex;
+
+ LLScrollListItem::Params row_params;
+ LLScrollListCell::Params cell_params;
+ for (S32 i = 0; i < (S32)(mButtonChannels->getNumColumns()); ++i)
+ {
+ const std::string& name = mButtonChannels->getColumn(i)->mName;
+ // The icon columns ("input"/"output") render the controller glyph in
+ // SecondLife-game-control; the description columns match the
+ // "Controls" panel font.
+ cell_params.font = (name == "input" || name == "output")
+ ? promptFontForCell()
+ : LLFontGL::getFontSansSerif();
+ cell_params.column = name;
+ row_params.columns.add(cell_params);
+ }
+
+ for (size_t i = 0; i < LLGameControl::NUM_BUTTONS; ++i)
+ {
+ LLScrollListItem* row = mButtonChannels->addRow(row_params);
+ // The physical button is fixed: fill both its text label and its glyph
+ // (buttons without a glyph, e.g. spares, keep an empty icon cell).
+ std::string glyph = promptFontGlyph(items[i]->getValue().asString());
+ row->getColumn(input_desc_col)->setValue(items[i]->getColumn(0)->getValue());
+ row->getColumn(input_glyph_col)->setValue(glyph.empty() ? LLSD() : LLSD(glyph));
+ }
+}
+
+// Fills the button-channel Output cells (text description +
+// SecondLife-game-control glyph) from the current device's button map.
+void LLPanelPreferenceGameControl::populateButtonChannelsCells()
+{
+ std::vector<LLScrollListItem*> rows = mButtonChannels->getAllData();
+ const auto& button_map = getSelectedDeviceOptions().getButtonMap();
+ std::vector<LLScrollListItem*> items = mButtonInputSelector->getAllData();
+ llassert(rows.size() == button_map.size());
+
+ S32 output_desc_col = mButtonChannels->getColumn("output_description")->mIndex;
+ S32 output_glyph_col = mButtonChannels->getColumn("output")->mIndex;
+
+ for (size_t i = 0; i < rows.size(); ++i)
+ {
+ U8 output = button_map[i];
+ rows[i]->getColumn(output_desc_col)->setValue(selectorLabelAt(mButtonInputSelector, output));
+ std::string value = (output < items.size()) ? items[output]->getValue().asString() : LLStringUtil::null;
+ std::string glyph = promptFontGlyph(value);
+ rows[i]->getColumn(output_glyph_col)->setValue(glyph.empty() ? LLSD() : LLSD(glyph));
+ }
+}
+
+// Rebuilds the Device State selector from the currently connected devices.
+// Only connected devices are listed here, since the tab shows live input and a
+// disconnected device has no live state. Shows the "No device" message and hides
+// the tables when nothing is connected.
+void LLPanelPreferenceGameControl::updateDeviceStateList()
+{
+ mStateDeviceList->clear();
+ mStateDeviceList->clearRows();
+
+ const std::list<LLGameControl::Device>& devices = LLGameControl::getDevices();
+ bool hasDevice = !devices.empty();
+
+ mStateNoDeviceMessage->setVisible(!hasDevice);
+ mStateDevicePrompt->setVisible(hasDevice);
+ mStateRemapNote->setVisible(hasDevice);
+ mStateDeviceList->setVisible(hasDevice);
+ mRestoreDeviceOptionsDefaults->setVisible(hasDevice);
+ mPanelDeviceState->setVisible(hasDevice);
+
+ if (!hasDevice)
+ {
+ mStateSelectedDeviceGUID.clear();
+ return;
+ }
+
+ for (const LLGameControl::Device& device : devices)
+ {
+ std::string title = device.getGUID() + ", " + device.getName();
+ mStateDeviceList->addElement(LLSD().with("value", device.getGUID())
+ .with("columns", LLSD().with("label", title)));
+ }
+
+ // Keep the current selection if that device is still connected; otherwise
+ // fall back to the first device.
+ if (mStateSelectedDeviceGUID.empty() || !mStateDeviceList->setSelectedByValue(mStateSelectedDeviceGUID, true))
+ {
+ mStateDeviceList->selectNthItem(0);
+ }
+ mStateSelectedDeviceGUID = mStateDeviceList->getValue().asString();
+
+ // Refresh the editable axis option cells for the (re)selected state device.
+ populateAxisStateOptionCells();
+}
+
+// Creates one row per physical axis in the axis-state table. Columns:
+// Axis-state table columns (input, raw_value, invert, offset, dead_zone,
+// fixed_value); their display order is defined entirely by the XML. Raw/Adjusted
+// are filled live in draw(); Invert/Offset/Dead Zone are editable axis options.
+// All cells are addressed by column name (see axisStateColumn), so reordering the
+// columns in the XML requires no change here.
+void LLPanelPreferenceGameControl::populateAxisStateRows()
+{
+ mAxisState->clearRows();
+
+ // One row per physical axis, labelled from the output selector's canonical-axis items.
+ std::vector<LLScrollListItem*> items = mAxisOutputSelector->getAllData();
+
+ LLScrollListItem::Params row_params;
+ LLScrollListCell::Params cell_params;
+ for (S32 i = 0; i < (S32)(mAxisState->getNumColumns()); ++i)
+ {
+ const std::string& name = mAxisState->getColumn(i)->mName;
+ // The icon column ("input_glyph") renders the controller glyph in
+ // SecondLife-game-control font; every other column uses the default text font.
+ cell_params.font = (name == "input_glyph")
+ ? promptFontForCell()
+ : LLFontGL::getFontSansSerif();
+ cell_params.column = name;
+ row_params.columns.add(cell_params);
+ }
+ // Configure each cell by column name so the XML column order stays the single
+ // source of truth (reordering columns in the XML needs no change here).
+ row_params.columns(axisStateColumn("raw_value")).font_halign = "right";
+ row_params.columns(axisStateColumn("invert")).type = "checkbox";
+ row_params.columns(axisStateColumn("invert")).font_halign = "right"; // right-align the checkbox within the cell
+ row_params.columns(axisStateColumn("offset")).font_halign = "right";
+ row_params.columns(axisStateColumn("dead_zone")).font_halign = "right";
+ row_params.columns(axisStateColumn("fixed_value")).font_halign = "right";
+
+ S32 input_glyph_col = axisStateColumn("input_glyph");
+ S32 input_col = axisStateColumn("input");
+ for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i)
+ {
+ LLScrollListItem* row = mAxisState->addRow(row_params);
+ // The physical axis is fixed: fill both its SecondLife-game-control glyph
+ // and its text label.
+ std::string glyph = promptFontGlyph(items[i]->getValue().asString());
+ row->getColumn(input_glyph_col)->setValue(glyph.empty() ? LLSD() : LLSD(glyph));
+ row->getColumn(input_col)->setValue(items[i]->getColumn(0)->getValue()); // physical axis label
+ }
+
+ // Fill the editable option columns for the currently selected state device.
+ populateAxisStateOptionCells();
+}
+
+// Fills the Device State axis table's editable option cells (Invert / Offset /
+// Dead Zone) from the state tab's selected device. Called when rows are built and
+// whenever the selected state device changes; the per-frame draw() only refreshes
+// the Raw/Adjusted columns, so it never clobbers these while the user edits.
+void LLPanelPreferenceGameControl::populateAxisStateOptionCells()
+{
+ auto options_it = mDeviceOptions.find(mStateSelectedDeviceGUID);
+ if (options_it == mDeviceOptions.end())
+ {
+ return;
+ }
+ const auto& all_axis_options = options_it->second.options.getAxisOptions();
+ std::vector<LLScrollListItem*> rows = mAxisState->getAllData();
+ S32 invert_col = axisStateColumn("invert");
+ S32 offset_col = axisStateColumn("offset");
+ S32 dead_zone_col = axisStateColumn("dead_zone");
+ for (size_t i = 0; i < rows.size() && i < all_axis_options.size(); ++i)
+ {
+ const LLGameControl::Options::AxisOptions& axis_options = all_axis_options[i];
+ rows[i]->getColumn(invert_col)->setValue(axis_options.mMultiplier == -1); // Invert checkbox
+ setNumericLabel(rows[i]->getColumn(offset_col), axis_options.mOffset); // Offset
+ setNumericLabel(rows[i]->getColumn(dead_zone_col), axis_options.mDeadZone); // Dead Zone
+ }
+}
+
+// Creates one row per physical button in the button-state table.
+// Columns: Button (physical button label) | Value (filled live in draw()).
+void LLPanelPreferenceGameControl::populateButtonStateRows()
+{
+ mButtonState->clearRows();
+
+ std::vector<LLScrollListItem*> items = mButtonInputSelector->getAllData();
+
+ S32 input_glyph_col = mButtonState->getColumn("input_glyph")->mIndex;
+ S32 input_col = mButtonState->getColumn("input")->mIndex;
+
+ LLScrollListItem::Params row_params;
+ LLScrollListCell::Params cell_params;
+ for (S32 i = 0; i < (S32)(mButtonState->getNumColumns()); ++i)
+ {
+ const std::string& name = mButtonState->getColumn(i)->mName;
+ // The icon column ("input_glyph") renders the controller glyph in
+ // SecondLife-game-control; every other column uses the default text font.
+ cell_params.font = (name == "input_glyph")
+ ? promptFontForCell()
+ : LLFontGL::getFontSansSerif();
+ cell_params.column = name;
+ row_params.columns.add(cell_params);
+ }
+ row_params.columns(mButtonState->getColumn("value")->mIndex).font_halign = "right"; // Value
+
+ for (size_t i = 0; i < LLGameControl::NUM_BUTTONS; ++i)
+ {
+ LLScrollListItem* row = mButtonState->addRow(row_params);
+ // The physical button is fixed: fill both its SecondLife-game-control
+ // glyph and its text label.
+ std::string glyph = promptFontGlyph(items[i]->getValue().asString());
+ row->getColumn(input_glyph_col)->setValue(glyph.empty() ? LLSD() : LLSD(glyph));
+ row->getColumn(input_col)->setValue(items[i]->getColumn(0)->getValue()); // physical button label
+ }
+}
+
+// Fills the Value columns of both state tables from the selected device's live
+// input state. Axis values are the raw [0, 32767] readings; button values are
+// 1 (pressed) or 0 (released). Called each frame while the tab is visible.
+void LLPanelPreferenceGameControl::populateDeviceStateValues()
+{
+ if (mStateSelectedDeviceGUID.empty())
+ {
+ return;
+ }
+
+ // Locate the live state for the selected device by GUID.
+ const LLGameControl::State* state = nullptr;
+ for (const LLGameControl::Device& device : LLGameControl::getDevices())
+ {
+ if (device.getGUID() == mStateSelectedDeviceGUID)
+ {
+ state = &device.getState();
+ break;
+ }
+ }
+ if (!state)
+ {
+ return;
+ }
+
+ // Each row is a physical axis, and its Invert/Offset/Dead-Zone options are keyed by
+ // physical axis, so Raw/Adjusted must be too. State::mAxes/mRawAxes are keyed by
+ // canonical output axis (post-mapping), which would land on the wrong row; instead
+ // read mPhysicalRawAxes (pre-fix) / mPhysicalFixedAxes (post-fix), the pre-map values
+ // onAxis() preserves by physical index specifically for this table.
+ std::vector<LLScrollListItem*> axisRows = mAxisState->getAllData();
+ S32 raw_col = axisStateColumn("raw_value");
+ S32 fixed_col = axisStateColumn("fixed_value");
+ for (size_t i = 0; i < axisRows.size(); ++i)
+ {
+ if (i >= state->mPhysicalRawAxes.size())
+ {
+ break;
+ }
+ S32 raw = (S32)state->mPhysicalRawAxes[i]; // Raw Value (pre-fix)
+ S32 fixed = (S32)state->mPhysicalFixedAxes[i]; // Adjusted Value (post-fix)
+ axisRows[i]->getColumn(raw_col)->setValue(llformat("%d ", raw));
+ axisRows[i]->getColumn(fixed_col)->setValue(llformat("%d ", fixed));
+ }
+
+ // Each row is a physical button, so read the pre-map mPhysicalButtons; mButtons is
+ // keyed by canonical button (post-mapping) and would show state on the wrong row.
+ std::vector<LLScrollListItem*> buttonRows = mButtonState->getAllData();
+ S32 button_value_col = mButtonState->getColumn("value")->mIndex;
+ for (size_t i = 0; i < buttonRows.size(); ++i)
+ {
+ S32 value = (state->mPhysicalButtons >> i) & 0x1;
+ buttonRows[i]->getColumn(button_value_col)->setValue(llformat("%d ", value));
+ }
+}
+
+// Static hook, called from the send path each time a fresh GameControlInput
+// message goes out. Refreshes the Data Output tab's Value column from the
+// values just packed into that message (the current server state).
+// sGameControlPanel exists for the lifetime of the panel instance, not just while
+// it's on-screen (e.g. Preferences closed, or another tab selected), and this is
+// called unconditionally on every outgoing message -- so skip the refresh (and the
+// mode-change/row-rebuild check inside populateDataOutputValues()) unless the tab is
+// actually visible; it will simply pick up the current values on the next send after
+// the user switches back to it.
+void LLPanelPreferenceGameControl::updateDataOutput()
+{
+ if (sGameControlPanel && sGameControlPanel->mTabDataOutput->isInVisibleChain())
+ {
+ sGameControlPanel->populateDataOutputValues();
+ }
+}
+
+// Creates the Data Output rows: one per canonical axis (AXIS_0..AXIS_5), a single
+// empty separator row, then one per canonical button (BUTTON_0..BUTTON_31), then
+// the semantic (mode-dependent) block built by populateDataOutputSemanticRows().
+// The Value column is filled later in populateDataOutputValues().
+void LLPanelPreferenceGameControl::populateDataOutputRows()
+{
+ mDataOutput->clearRows();
+ mDataOutputSemanticMode = -1; // force the semantic block below to build fresh
+
+ LLScrollListItem::Params row_params;
+ LLScrollListCell::Params cell_params;
+ cell_params.font = LLFontGL::getFontSansSerif();
+ for (S32 i = 0; i < (S32)(mDataOutput->getNumColumns()); ++i)
+ {
+ cell_params.column = mDataOutput->getColumn(i)->mName;
+ row_params.columns.add(cell_params);
+ }
+ row_params.columns(2).font_halign = "right"; // Value
+
+ // Column 0 is a per-block 0-based index; it restarts at 0 for the button
+ // block below. Column 1 is the canonical output name, column 2 the Value.
+ for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i)
+ {
+ LLScrollListItem* row = mDataOutput->addRow(row_params);
+ row->getColumn(0)->setValue(llformat("%d", (S32)i));
+ row->getColumn(1)->setValue(LLGameControl::axisOutputName((U8)i));
+ }
+
+ // One empty row separates the axis block from the button block.
+ mDataOutput->addRow(row_params);
+
+ for (size_t i = 0; i < LLGameControl::NUM_BUTTONS; ++i)
+ {
+ LLScrollListItem* row = mDataOutput->addRow(row_params);
+ row->getColumn(0)->setValue(llformat("%d", (S32)i));
+ // getRemoteName() gives the Button enum's symbolic name for the named
+ // buttons (0..BUTTON_TOUCHPAD) but blanks the unnamed tail; fall back to
+ // the indexed BUTTON_N form there, which is exactly the enum name for those.
+ std::string name = LLGameControl::InputChannel(LLGameControl::InputChannel::TYPE_BUTTON, (U8)i).getRemoteName();
+ LLStringUtil::trim(name);
+ if (name.empty())
+ {
+ name = llformat("BUTTON_%d", (S32)i);
+ }
+ row->getColumn(1)->setValue(name);
+ }
+
+ populateDataOutputSemanticRows((LLGameControl::AgentControlMode)LLGameControl::getServerState().mActionMode);
+}
+
+// Rebuilds the semantic (mode-dependent) block of Data Output rows -- a blank
+// separator, one row per semantic axis slot for 'mode' (LLGameControl::
+// numSemanticAxesForMode()/semanticAxisName()), another blank separator, then one
+// row per semantic button slot (numSemanticButtonsForMode()/semanticButtonName()).
+// Called whenever populateDataOutputValues() finds the live ServerState::mActionMode
+// no longer matches mDataOutputSemanticMode: unlike the canonical block above, both
+// the semantic block's row count and its labels depend on the mode, so simply
+// truncating/re-adding rows here (rather than reusing stale ones) is what keeps a
+// mode switch from leaving behind a stale label or a Value from a slot that no
+// longer exists for the new mode.
+void LLPanelPreferenceGameControl::populateDataOutputSemanticRows(LLGameControl::AgentControlMode mode)
+{
+ static const S32 CANONICAL_ROW_COUNT = (S32)LLGameControl::NUM_AXES + 1 + (S32)LLGameControl::NUM_BUTTONS;
+ while (mDataOutput->getItemCount() > CANONICAL_ROW_COUNT)
+ {
+ mDataOutput->deleteSingleItem(mDataOutput->getItemCount() - 1);
+ }
+
+ LLScrollListItem::Params row_params;
+ LLScrollListCell::Params cell_params;
+ cell_params.font = LLFontGL::getFontSansSerif();
+ for (S32 i = 0; i < (S32)(mDataOutput->getNumColumns()); ++i)
+ {
+ cell_params.column = mDataOutput->getColumn(i)->mName;
+ row_params.columns.add(cell_params);
+ }
+ row_params.columns(2).font_halign = "right"; // Value
+
+ // One empty row separates the canonical button block from the semantic axes.
+ mDataOutput->addRow(row_params);
+
+ U8 num_semantic_axes = LLGameControl::numSemanticAxesForMode(mode);
+ for (U8 i = 0; i < num_semantic_axes; ++i)
+ {
+ LLScrollListItem* row = mDataOutput->addRow(row_params);
+ row->getColumn(0)->setValue(llformat("%d", (S32)i));
+ row->getColumn(1)->setValue(LLGameControl::semanticAxisName(mode, i));
+ }
+
+ // One empty row separates the semantic axes from the semantic buttons.
+ mDataOutput->addRow(row_params);
+
+ U8 num_semantic_buttons = LLGameControl::numSemanticButtonsForMode(mode);
+ for (U8 i = 0; i < num_semantic_buttons; ++i)
+ {
+ LLScrollListItem* row = mDataOutput->addRow(row_params);
+ row->getColumn(0)->setValue(llformat("%d", (S32)i));
+ row->getColumn(1)->setValue(LLGameControl::semanticButtonName(mode, i));
+ }
+
+ mDataOutputSemanticMode = (S32)mode;
+}
+
+// Fills the Data Output Value column from the last outgoing server state: each
+// axis shows its signed [-32768, 32767] value; each button shows 1 (pressed) or
+// 0 (released). The row layout matches populateDataOutputRows()/
+// populateDataOutputSemanticRows(): canonical axes, a blank separator, canonical
+// buttons, a blank separator, semantic axes, a blank separator, semantic buttons.
+void LLPanelPreferenceGameControl::populateDataOutputValues()
+{
+ const LLGameControl::ServerState& state = LLGameControl::getServerState();
+ LLGameControl::AgentControlMode mode = (LLGameControl::AgentControlMode)state.mActionMode;
+ if ((S32)mode != mDataOutputSemanticMode)
+ {
+ populateDataOutputSemanticRows(mode);
+ }
+
+ std::vector<LLScrollListItem*> rows = mDataOutput->getAllData();
+ size_t row = 0;
+
+ for (size_t i = 0; i < LLGameControl::NUM_AXES && i < state.mAxes.size() && row < rows.size(); ++i, ++row)
+ {
+ rows[row]->getColumn(2)->setValue(llformat("%d ", (S32)state.mAxes[i]));
+ }
+
+ ++row; // skip the empty separator row
+
+ for (size_t i = 0; i < LLGameControl::NUM_BUTTONS && row < rows.size(); ++i, ++row)
+ {
+ S32 value = (state.mButtons >> i) & 0x1;
+ rows[row]->getColumn(2)->setValue(llformat("%d ", value));
+ }
+
+ ++row; // skip the empty separator row between canonical buttons and semantic axes
+
+ U8 num_semantic_axes = LLGameControl::numSemanticAxesForMode(mode);
+ for (size_t i = 0; i < num_semantic_axes && i < state.mSemanticAxes.size() && row < rows.size(); ++i, ++row)
+ {
+ rows[row]->getColumn(2)->setValue(llformat("%d ", (S32)state.mSemanticAxes[i]));
+ }
+
+ ++row; // skip the empty separator row between semantic axes and semantic buttons
+
+ U8 num_semantic_buttons = LLGameControl::numSemanticButtonsForMode(mode);
+ for (size_t i = 0; i < num_semantic_buttons && row < rows.size(); ++i, ++row)
+ {
+ S32 value = (state.mSemanticButtons >> i) & 0x1;
+ rows[row]->getColumn(2)->setValue(llformat("%d ", value));
+ }
+}
+
+// Returns the display label of the input selector item with the given value,
+// or empty if there is no such item.
+std::string LLPanelPreferenceGameControl::inputLabel(const LLComboBox* input_selector, const std::string& input_value)
+{
+ for (const LLScrollListItem* item : input_selector->getAllData())
+ {
+ if (item->getValue().asString() == input_value)
+ {
+ return item->getColumn(0)->getValue().asString();
+ }
+ }
+ return LLStringUtil::null;
+}
+
+// Returns the display label of the selector item at the given index (the item
+// position matches the canonical axis/button index), or empty if out of range.
+std::string LLPanelPreferenceGameControl::selectorLabelAt(const LLComboBox* selector, S32 index)
+{
+ std::vector<LLScrollListItem*> items = selector->getAllData();
+ if (index < 0 || index >= (S32)items.size())
+ {
+ return LLStringUtil::null;
+ }
+ return items[index]->getColumn(0)->getValue().asString();
+}
+
+// Populates glyph_selector with one item per value in text_selector. Each item
+// keeps the canonical value but is displayed as its SecondLife-game-control
+// glyph, so the dropdown shown over the icon column matches the icons in the
+// table. Inputs with no glyph (e.g. "None", spare buttons) keep their text
+// label in the normal font so they remain readable and selectable.
+void LLPanelPreferenceGameControl::buildInputGlyphSelector(const LLComboBox* text_selector, LLComboBox* glyph_selector)
+{
+ glyph_selector->clearRows();
+ for (const LLScrollListItem* item : text_selector->getAllData())
+ {
+ std::string value = item->getValue().asString();
+ std::string glyph = promptFontGlyph(value);
+
+ LLSD element;
+ element["value"] = value;
+ LLSD& column = element["columns"][0];
+ column["column"] = "input";
+ if (glyph.empty())
+ {
+ column["value"] = item->getColumn(0)->getValue().asString(); // text label
+ column["font"]["name"] = "SansSerif";
+ column["font"]["size"] = "Small";
+ }
+ else
+ {
+ column["value"] = glyph;
+ column["font"]["name"] = "SecondLife-game-control";
+ column["font"]["size"] = "Huge";
+ }
+ glyph_selector->addElement(element);
+ }
+}
+
+// Returns the options struct for the currently selected device.
+LLGameControl::Options& LLPanelPreferenceGameControl::getSelectedDeviceOptions()
+{
+ auto options_it = mDeviceOptions.find(mSelectedDeviceGUID);
+ llassert_always(options_it != mDeviceOptions.end());
+ return options_it->second.options;
+}
+
+// Formats a numeric value for display in a table cell.
+// Always shows the value, including the zero (default) case.
+S32 LLPanelPreferenceGameControl::axisStateColumn(const std::string& name) const
+{
+ LLScrollListColumn* column = mAxisState->getColumn(name);
+ return column ? column->mIndex : -1;
+}
+
+void LLPanelPreferenceGameControl::setNumericLabel(LLScrollListCell* cell, S32 value)
+{
+ cell->setValue(llformat("%d ", value));
+}
+
+// Positions a UI control (combobox or spin control) to overlay a specific table cell.
+// Used to show editors inline within the scroll list tables.
+void LLPanelPreferenceGameControl::fitInRect(LLUICtrl* ctrl, LLScrollListCtrl* grid, S32 row_index, S32 col_index)
+{
+ LLRect rect(grid->getCellRect(row_index, col_index));
+ LLView* parent = grid->getParent();
+ while (parent && parent != ctrl->getParent())
+ {
+ rect.translate(parent->getRect().mLeft, parent->getRect().mBottom);
+ parent = parent->getParent();
+ }
+
+ ctrl->setRect(rect);
+ rect.translate(-rect.mLeft, -rect.mBottom);
+ for (LLView* child : *ctrl->getChildList())
+ {
+ LLRect childRect(child->getRect());
+ childRect.intersectWith(rect);
+ if (childRect.mRight < rect.mRight &&
+ childRect.mRight > (rect.mLeft + rect.mRight) / 2)
+ {
+ childRect.mRight = rect.mRight;
+ }
+ child->setRect(childRect);
+ }
+}
+
+// Clears the current cell selection state and hides all popup editors.
+void LLPanelPreferenceGameControl::clearSelectionState()
+{
+ // Restore the text we blanked when the selector opened (initCombobox).
+ // On commit this is the freshly committed value; otherwise it's the
+ // original, so a dismissed selector leaves the cell unchanged.
+ if (sSelectedCell)
+ {
+ sSelectedCell->setValue(sSelectedCellValue);
+ }
+ sSelectedCellValue = LLSD();
+
+ if (sSelectedGrid)
+ {
+ sSelectedGrid->deselectAllItems(true);
+ }
+
+ sSelectedGrid = nullptr;
+ sSelectedItem = nullptr;
+ sSelectedCell = nullptr;
+ sSelectedCombobox = nullptr;
+ sSelectedRow = -1;
+ sSelectedCol = -1;
+ mNumericValueEditor->setVisible(false);
+ mAxisInputSelector->setVisible(false);
+ mAxisOutputSelector->setVisible(false);
+ mButtonInputSelector->setVisible(false);
+ mAxisInputGlyphSelector->setVisible(false);
+ mButtonInputGlyphSelector->setVisible(false);
+ mAxisOutputGlyphSelector->setVisible(false);
+}
+
+// Resets the current mode's axis + button action mappings to the built-in defaults.
+void LLPanelPreferenceGameControl::onResetActionsToDefaults()
+{
+ clearSelectionState();
+
+ std::string mode = currentEditMode();
+ LLSD defaults = LLGameControl::getDefaultModeMappings();
+ LLGameControl::setModeMapping(mode, MODE_INPUT_TYPE_AXES, defaults[mode][MODE_INPUT_TYPE_AXES]);
+ LLGameControl::setModeMapping(mode, MODE_INPUT_TYPE_BUTTONS, defaults[mode][MODE_INPUT_TYPE_BUTTONS]);
+ LLGameControl::setModeMapping(mode, MODE_INPUT_TYPE_AXES_INVERT, defaults[mode][MODE_INPUT_TYPE_AXES_INVERT]);
+ // AllowRoll, SpeedFactor, ShowCrosshair, and HideCursor live outside the
+ // Axes/Buttons/AxesInvert mapping this function otherwise restores, so
+ // they need to be reset explicitly.
+ if (mode == "FlyCam")
+ {
+ LLGameControl::setFlycamRollAllowed(false);
+ LLGameControl::setFlycamCrosshairEnabled(false);
+ LLGameControl::setFlycamHideCursorEnabled(true);
+ }
+ if (mode == "FlyCam" || mode == "Mouselook" || mode == "Avatar")
+ {
+ LLGameControl::setSpeedFactor(mode, 1.0f);
+ }
+ populateActionMappings();
+ updateActionModeEnabledUI(); // syncs mCheckFlycamAllowRoll with the reset value above
+
+ // Push the pending UI state into LLGameControl's runtime so the effect is
+ // immediate. gSavedSettings is updated later via saveSettings() on OK.
+ LLGameControl::applySettingsFromLLSD(getSettingsAsLLSD());
+}
+
+// Resets the selected device's options (axis/button remap, invert, deadzone, offset)
+// to defaults.
+void LLPanelPreferenceGameControl::onResetDeviceToDefaults()
+{
+ clearSelectionState();
+ if (mSelectedDeviceGUID.empty())
+ {
+ return;
+ }
+
+ LLGameControl::Options& options = getSelectedDeviceOptions();
+ options.resetToDefaults();
+ LLGameControl::setDeviceOptions(mSelectedDeviceGUID, options);
+
+ populateAxisChannelsCells();
+ populateButtonChannelsCells();
+ // Invert/offset/dead-zone now live on the Device State tab; refresh them too
+ // (a no-op unless the reset device is the one shown there).
+ populateAxisStateOptionCells();
+
+ LLGameControl::applySettingsFromLLSD(getSettingsAsLLSD());
+}
+
+// Resets the state-tab device's per-axis tuning (Invert / Offset / Dead Zone) to
+// defaults for every axis, leaving the axis/button remaps untouched. This backs
+// the Device Options tab's "Restore Defaults" button.
+void LLPanelPreferenceGameControl::onResetDeviceOptionsToDefaults()
+{
+ clearSelectionState();
+ auto options_it = mDeviceOptions.find(mStateSelectedDeviceGUID);
+ if (options_it == mDeviceOptions.end())
+ {
+ return;
+ }
+
+ LLGameControl::Options& options = options_it->second.options;
+ for (LLGameControl::Options::AxisOptions& axis_options : options.getAxisOptions())
+ {
+ axis_options.resetToDefaults();
+ }
+ LLGameControl::setDeviceOptions(mStateSelectedDeviceGUID, options);
+
+ populateAxisStateOptionCells();
+
+ LLGameControl::applySettingsFromLLSD(getSettingsAsLLSD());
+}
+
+// Starts a new auto-calibration pass for the state tab's selected device: clears any
+// previously-collected samples and lets updateAutoCalibration() (called from draw())
+// gather CALIBRATION_SAMPLE_COUNT raw-axis readings, one per frame while the Device
+// Options tab is visible.
+void LLPanelPreferenceGameControl::onAutoCalibrate()
+{
+ clearSelectionState();
+ if (mStateSelectedDeviceGUID.empty())
+ {
+ return;
+ }
+
+ mCalibrationSamples.assign(LLGameControl::NUM_AXES, {});
+ mCalibrationSamplesCollected = 0;
+ mCalibrating = true;
+}
+
+// Advances an in-progress auto-calibration pass by one frame: records the state
+// device's current raw axis readings, and once CALIBRATION_SAMPLE_COUNT frames have
+// been sampled, derives Offset/Dead Zone for every axis whose readings never changed
+// across all samples (i.e. the axis wasn't being manipulated, so its readings are its
+// natural "zero input" state). Axes that changed are left untouched.
+void LLPanelPreferenceGameControl::updateAutoCalibration()
+{
+ // Locate the live state for the selected device by GUID (same lookup as
+ // populateDeviceStateValues()).
+ const LLGameControl::State* state = nullptr;
+ for (const LLGameControl::Device& device : LLGameControl::getDevices())
+ {
+ if (device.getGUID() == mStateSelectedDeviceGUID)
+ {
+ state = &device.getState();
+ break;
+ }
+ }
+ if (!state)
+ {
+ mCalibrating = false;
+ return;
+ }
+
+ for (size_t i = 0; i < mCalibrationSamples.size() && i < state->mPhysicalRawAxes.size(); ++i)
+ {
+ mCalibrationSamples[i].push_back(state->mPhysicalRawAxes[i]);
+ }
+ ++mCalibrationSamplesCollected;
+ if (mCalibrationSamplesCollected < CALIBRATION_SAMPLE_COUNT)
+ {
+ return;
+ }
+
+ mCalibrating = false;
+
+ auto options_it = mDeviceOptions.find(mStateSelectedDeviceGUID);
+ if (options_it != mDeviceOptions.end())
+ {
+ std::vector<LLGameControl::Options::AxisOptions>& all_axis_options = options_it->second.options.getAxisOptions();
+ for (size_t i = 0; i < mCalibrationSamples.size() && i < all_axis_options.size(); ++i)
+ {
+ const std::vector<S16>& samples = mCalibrationSamples[i];
+ bool steady = !samples.empty();
+ for (size_t s = 1; s < samples.size() && steady; ++s)
+ {
+ steady = (samples[s] == samples[0]);
+ }
+ if (!steady)
+ {
+ // Axis moved during the measurement window: the user is manipulating
+ // it, so leave its Offset/Dead Zone untouched.
+ continue;
+ }
+
+ S32 offset = std::clamp<S32>(-(S32)samples[0], -(S32)(LLGameControl::MAX_AXIS_OFFSET), (S32)(LLGameControl::MAX_AXIS_OFFSET));
+ S32 dead_zone = std::clamp(2 * std::abs(offset), (S32)(LLGameControl::DEFAULT_AXIS_DEAD_ZONE), (S32)(LLGameControl::MAX_AXIS_DEAD_ZONE));
+
+ LLGameControl::Options::AxisOptions& axis_options = all_axis_options[i];
+ axis_options.mOffset = (S16)offset;
+ axis_options.mDeadZone = (U16)dead_zone;
+ }
+ LLGameControl::setDeviceOptions(mStateSelectedDeviceGUID, options_it->second.options);
+
+ populateAxisStateOptionCells();
+
+ LLGameControl::applySettingsFromLLSD(getSettingsAsLLSD());
+ }
+
+ mCalibrationSamples.clear();
+ mCalibrationSamplesCollected = 0;
+}
+
+// Captures current settings values into mOrigSettings for later restoration upon cancel().
+void LLPanelPreferenceGameControl::rememberOriginalSettings()
+{
+ mOrigSettings = LLGameControl::getSettingsAsLLSD();
+}
diff --git a/indra/newview/llpanelpreferencegamecontrol.h b/indra/newview/llpanelpreferencegamecontrol.h
new file mode 100644
index 0000000000..60749710f9
--- /dev/null
+++ b/indra/newview/llpanelpreferencegamecontrol.h
@@ -0,0 +1,277 @@
+/**
+ * @file llpanelpreferencegamecontrol.h
+ * @brief LLPanelPreferenceGameControl class definition
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llfloaterpreference.h"
+#include "llgamecontrol.h"
+#include "llscrolllistcell.h"
+#include "llscrolllistctrl.h"
+
+class LLButton;
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLPanel;
+class LLSliderCtrl;
+class LLSpinCtrl;
+class LLTextBox;
+
+//------------------------LLPanelPreferenceGameControl--------------------------------
+//
+// Preference panel for configuring game controller (gamepad) input.
+//
+// Two visible sub-tabs:
+// - Actions (global, per mode Avatar/Mouselook/FlyCam/Captive/Cursor): one table binding
+// each mode's axis and button actions to a canonical input. Independent of device.
+// - Devices (per device): normalizes physical hardware to canonical inputs --
+// an axis-channels table and a button-channels table, each mapping the physical
+// input (icon + text) to the canonical output (icon + text). Axis tuning
+// (invert/offset/dead zone) lives on the Device State tab.
+//
+// All settings are stored under a single "GameControl" key:
+// GameControl/ModeMappings/<Mode>/{Axes,Buttons} - GLOBAL action -> input
+// GameControl/Devices/<guid>/Config - serialized per-device options
+//
+class LLPanelPreferenceGameControl : public LLPanelPreference
+{
+ LOG_CLASS(LLPanelPreferenceGameControl);
+public:
+
+ // Called when a device is connected/disconnected
+ static void updateDeviceList();
+
+ LLPanelPreferenceGameControl();
+ ~LLPanelPreferenceGameControl();
+
+ void onOpen(const LLSD& key) override;
+ void draw() override;
+
+ void apply() override;
+ void cancel(const std::vector<std::string> settings_to_skip = {}) override;
+ void saveSettings() override;
+
+ // Snapshots the panel's UI state as the single "GameControl" setting map.
+ // The result can be fed to LLGameControl::applySettingsFromLLSD()
+ // to push pending changes into the runtime without touching gSavedSettings.
+ LLSD getSettingsAsLLSD();
+
+ void updateDeviceListInternal(); // Refresh device list and settings
+
+ // UI event handlers
+ void onGridSelect(LLUICtrl* ctrl); // Handle table row selection
+ void onCommitInputChannel(LLUICtrl* ctrl); // Handle input/output combobox selection
+ void onCommitNumericValue(); // Handle deadzone/offset value changes
+
+ // Live input capture support
+ static bool isWaitingForInputChannel(); // True if a cell is waiting for input
+ static void applyGameControlInput(); // Assign detected input to selected cell
+
+ // Data Output tab: refresh the Value column with the channel values packed into
+ // the most recent outgoing GameControlInput message. Called from the send path.
+ static void updateDataOutput();
+
+protected:
+ bool postBuild() override;
+
+ // Actions tab (global, per-mode) population.
+ void populateActionMappings(); // Rebuild the action table for the current mode
+ LLGameControl::Options& getSelectedDeviceOptions(); // Get options for selected device
+
+ // Devices tab (per-device) population.
+ void populateDeviceTitle(); // Update device selector UI
+ void populateDeviceSettings(const std::string& guid); // Load settings for device
+ void populateAxisChannelsRows(); // Create axis-channel rows (one per physical axis)
+ void populateAxisChannelsCells(); // Fill axis-channel invert/deadzone/offset/output
+ void populateButtonChannelsRows(); // Create button-channel rows (one per physical button)
+ void populateButtonChannelsCells(); // Fill button-channel output column
+
+ // Device State tab (per-device, live read-only) population.
+ void updateDeviceStateList(); // Rebuild the state device selector from connected devices
+ void populateAxisStateRows(); // Create axis-state rows (one per physical axis)
+ void populateAxisStateOptionCells();// Fill the state-tab axis option cells (invert/offset/dead zone) from the state device
+ void populateButtonStateRows(); // Create button-state rows (one per physical button)
+ void populateDeviceStateValues(); // Fill the Value columns from the selected device's live state
+
+ // Data Output tab (live, read-only view of the last outgoing GameControlInput).
+ void populateDataOutputRows(); // Create the AXIS_/BUTTON_ label rows (with a blank separator)
+ void populateDataOutputSemanticRows(LLGameControl::AgentControlMode mode); // Rebuild the mode-dependent semantic block
+ void populateDataOutputValues(); // Fill the Value column from the last outgoing server state
+
+ // Utility methods
+ // Column index of a named axis-state column. Lets the code address the
+ // Device State axis table by column name, so the XML column order is the
+ // single source of truth: columns can be reordered in the XML with no code
+ // change here. Returns -1 if no such column exists.
+ S32 axisStateColumn(const std::string& name) const;
+ static void setNumericLabel(LLScrollListCell* cell, S32 value); // Format numeric cell
+ static void fitInRect(LLUICtrl* ctrl, LLScrollListCtrl* grid, S32 row_index, S32 col_index); // Position editor over cell
+
+private:
+ // Inline editing support
+ bool initCombobox(LLScrollListItem* item, LLScrollListCtrl* grid); // Show combobox over cell
+ void clearSelectionState(); // Hide editors and clear selection tracking
+
+ // Actions-tab helpers
+ std::string currentEditMode(); // mode string ("Avatar"/"Mouselook"/"FlyCam"/"Captive"/"Cursor") from mActionMode
+ void onActionModeChanged(); // rebuild the action table when the edit-mode selector changes
+ void onModeEnabledToggled(bool enabled); // toggle conversion for the currently-selected mode
+ void updateActionModeEnabledUI(); // sync the Enabled checkbox and lock/unlock the tables
+ void updateCurrentModeIndicator(); //sync mode indicator
+ LLComboBox* actionSelectorForMode(bool axis, const std::string& mode) const; // default vs flycam selector
+ void removeDuplicateActionInput(const std::string& mode, const std::string& kind,
+ const std::string& keep_action, const std::string& input_value, const LLComboBox* input_selector);
+ // True for the FlyCam Roll actions and Unroll while "Allow Roll" is unchecked: new
+ // mappings to them are refused (existing ones stay mapped, but greyed out and clearable).
+ static bool isFlycamRollDisallowed(const std::string& mode, const std::string& action);
+ static std::string inputLabel(const LLComboBox* input_selector, const std::string& input_value); // value -> label
+ static std::string selectorLabelAt(const LLComboBox* selector, S32 index); // label of item at index
+ // Fill glyph_selector with one item per value in text_selector, each labelled
+ // with that input's PromptFont glyph (or its text label where no glyph exists).
+ static void buildInputGlyphSelector(const LLComboBox* text_selector, LLComboBox* glyph_selector);
+
+ // Handlers for individual table selections/commits
+ void onAxisChannelsSelect(); // output popup (Device Options tab)
+ void onButtonChannelsSelect(); // output popup
+ void onAxisStateSelect(); // invert checkbox / offset-deadzone editor (Device State tab)
+
+ // Reset to defaults handlers
+ void onResetActionsToDefaults(); // Reset current mode's action mappings
+ void onResetDeviceToDefaults(); // Reset selected device's options (remap/invert/deadzone/offset)
+ void onResetDeviceOptionsToDefaults(); // Reset state device's per-axis tuning (invert/offset/dead zone)
+
+ // Auto-calibration: samples the state device's raw axes over several frames and
+ // derives Offset/Dead Zone for axes that don't move. See updateAutoCalibration().
+ void onAutoCalibrate(); // Kick off a new calibration pass
+ void updateAutoCalibration(); // Advance the in-progress pass; called once per frame from draw()
+
+ void rememberOriginalSettings(); // Capture settings for cancel restoration
+
+ // Sends game_control data to server
+ LLCheckBoxCtrl* mCheckGameControlToServer { nullptr };
+
+ // Sub-tab panels
+ LLPanel* mTabActions { nullptr };
+ LLPanel* mTabDevices { nullptr };
+
+ // Actions tab
+ LLComboBox* mActionMode { nullptr }; // selects which mode's mappings are edited
+ LLCheckBoxCtrl* mCheckActionModeEnabled { nullptr }; // enables/disables the selected mode
+ LLCheckBoxCtrl* mCheckFlycamAllowRoll { nullptr }; // FlyCam-only: allows Roll input; hidden for other modes
+ LLSliderCtrl* mSliderSpeedFactor { nullptr }; // FlyCam/Mouselook/Avatar-only: "Slow".."Fast" speed multiplier; hidden for other modes
+ LLTextBox* mSpeedSlowLabel { nullptr }; // "Slow"/"Fast" labels shown/hidden with mSliderSpeedFactor
+ LLTextBox* mSpeedFastLabel { nullptr };
+ LLCheckBoxCtrl* mCheckFlycamCrosshair { nullptr }; // FlyCam-only: draws a centered crosshair while flying; hidden for other modes
+ LLCheckBoxCtrl* mCheckFlycamHideCursor { nullptr }; // FlyCam-only: hides the mouse cursor while flying (until the mouse moves); hidden for other modes
+ LLButton* mRestoreActionsDefaults { nullptr };
+ LLTextBox* mCurrentModeIndicator { nullptr }; //mode indicator
+ LLGameControl::AgentControlMode mLastDrawnControlMode { LLGameControl::CONTROL_MODE_NONE };
+ LLScrollListCtrl* mActionMappingsAxes { nullptr }; // Action | Axis Input (axis action block)
+ LLScrollListCtrl* mActionMappingsButtons { nullptr }; // Action | Buttons Input (button action block)
+
+ // Devices tab
+ LLTextBox* mNoDeviceMessage { nullptr }; // Shown when no devices connected
+ LLTextBox* mDevicePrompt { nullptr }; // "Device:" label
+ LLComboBox* mDeviceList { nullptr }; // Dropdown listing available devices
+ LLCheckBoxCtrl* mCheckShowAllDevices { nullptr }; // Include disconnected devices
+ LLPanel* mPanelDeviceSettings { nullptr };
+ LLButton* mRestoreDeviceDefaults { nullptr };
+ LLScrollListCtrl* mAxisChannels { nullptr }; // input(glyph) | input_description | output_description | output(glyph)
+ LLScrollListCtrl* mButtonChannels { nullptr }; // input(glyph) | input_description | output_description | output(glyph)
+
+ // Device State tab (per-device, live read-only)
+ LLPanel* mTabDeviceState { nullptr };
+ LLTextBox* mStateNoDeviceMessage { nullptr }; // Shown when no devices connected
+ LLTextBox* mStateDevicePrompt { nullptr }; // "Device:" label
+ LLTextBox* mStateRemapNote { nullptr }; // Note that values are post-remap
+ LLComboBox* mStateDeviceList { nullptr }; // Dropdown listing connected devices
+ LLButton* mRestoreDeviceOptionsDefaults { nullptr }; // Restore per-axis tuning to defaults
+ LLButton* mAutoCalibrate { nullptr }; // Kicks off automatic offset/dead-zone calibration
+ LLPanel* mPanelDeviceState { nullptr }; // Wrapper holding the two state tables
+ LLScrollListCtrl* mAxisState { nullptr }; // Input(glyph) | Axis | Raw/Adjusted values | invert/offset/dead-zone
+ LLScrollListCtrl* mButtonState { nullptr }; // Input(glyph) | Button | Value (live pressed state)
+ std::string mStateSelectedDeviceGUID; // GUID of the device shown in the state tab
+
+ // Auto-calibration: in-progress sample capture kicked off by mAutoCalibrate.
+ // updateAutoCalibration() (called from draw()) appends one raw-axis sample per
+ // physical axis each frame; once CALIBRATION_SAMPLE_COUNT samples are collected,
+ // any axis whose samples were all equal is treated as being at rest, and its
+ // Offset/Dead Zone are derived from that reading.
+ static constexpr S32 CALIBRATION_SAMPLE_COUNT = 5;
+ bool mCalibrating { false };
+ S32 mCalibrationSamplesCollected { 0 };
+ std::vector<std::vector<S16>> mCalibrationSamples; // per physical axis, up to CALIBRATION_SAMPLE_COUNT raw samples
+
+ // Data Output tab (live, read-only view of the last outgoing GameControlInput)
+ LLPanel* mTabDataOutput { nullptr };
+ LLScrollListCtrl* mDataOutput { nullptr }; // Output | Value (last sent axis/button values)
+
+ // AgentControlMode (as an S32; -1 == none yet) the semantic block of mDataOutput
+ // was last built for. populateDataOutputValues() rebuilds that block via
+ // populateDataOutputSemanticRows() whenever the live ServerState::mActionMode no
+ // longer matches, since both row count and labels are mode-dependent.
+ S32 mDataOutputSemanticMode { -1 };
+
+ // Inline editors - positioned over table cells when editing
+ LLSpinCtrl* mNumericValueEditor { nullptr }; // For deadzone/offset values
+ LLComboBox* mAxisInputSelector { nullptr }; // Axis-action Input popup (sticks + "Triggers left/right" pair)
+ LLComboBox* mAxisOutputSelector { nullptr }; // Device axis Output popup (individual canonical axes, index-based)
+ LLComboBox* mButtonInputSelector { nullptr }; // Canonical buttons (action Input + button Output popups)
+
+ // Glyph counterparts of the two action-Input selectors above, shown when the
+ // user edits the PromptFont icon ("Axis"/"Button") column instead of the text
+ // "input_description" column. Same values, but each item is rendered as its
+ // PromptFont glyph. Built in postBuild() from the text selectors' values.
+ LLComboBox* mAxisInputGlyphSelector { nullptr };
+ LLComboBox* mButtonInputGlyphSelector { nullptr };
+
+ // Glyph counterpart of mAxisOutputSelector, shown when the user edits the
+ // PromptFont icon ("output") column of the Devices-tab axis-channels table
+ // instead of the text "output_description" column. Built in postBuild().
+ LLComboBox* mAxisOutputGlyphSelector { nullptr };
+
+ // Action selectors: source of the "Action" column rows, chosen by edit mode.
+ LLComboBox* mAnalogActionSelector { nullptr }; // Avatar axis actions
+ LLComboBox* mBinaryActionSelector { nullptr }; // Avatar button actions
+ LLComboBox* mMouselookAnalogActionSelector { nullptr }; // Mouselook axis actions
+ LLComboBox* mMouselookBinaryActionSelector { nullptr }; // Mouselook button actions
+ LLComboBox* mFlycamAnalogActionSelector { nullptr }; // FlyCam axis actions
+ LLComboBox* mFlycamBinaryActionSelector { nullptr }; // FlyCam button actions
+ LLComboBox* mCaptiveBinaryActionSelector { nullptr }; // Captive (sitting) button actions
+ LLComboBox* mCursorAnalogActionSelector { nullptr }; // Cursor-mode axis actions
+ LLComboBox* mCursorBinaryActionSelector { nullptr }; // Cursor-mode button actions
+
+ // Per-device options storage
+ struct DeviceOptions
+ {
+ std::string name; // Device display name
+ std::string settings; // Serialized settings string
+ LLGameControl::Options options; // Parsed options (axis settings, mappings)
+ };
+ std::map<std::string, DeviceOptions> mDeviceOptions; // Keyed by device GUID
+ std::string mSelectedDeviceGUID; // Currently selected device
+
+ LLSD mOrigSettings; // Captured settings for cancel restoration
+};
diff --git a/indra/newview/llscriptruntimeperms.h b/indra/newview/llscriptruntimeperms.h
index 6350b61d08..af443849ff 100644
--- a/indra/newview/llscriptruntimeperms.h
+++ b/indra/newview/llscriptruntimeperms.h
@@ -34,7 +34,7 @@ typedef struct _script_perm {
question(q), permbit(b), caution(c) {}
} script_perm_t;
-const U32 NUM_SCRIPT_PERMISSIONS = 19;
+const U32 NUM_SCRIPT_PERMISSIONS = 20;
const S32 SCRIPT_PERMISSION_DEBIT = 0;
const S32 SCRIPT_PERMISSION_TRIGGER_ANIMATION = 3;
const S32 SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS = 14;
@@ -58,6 +58,7 @@ static const std::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSION
_script_perm("ScriptReturnObjects", (0x1 << 16), false),
_script_perm("ForceSitAvatar", (0x1 << 17), false),
_script_perm("ChangeEnvSettings", (0x1 << 18), false),
- _script_perm("PrivilegedLandAccess",(0x1 << 19), true)
+ _script_perm("PrivilegedLandAccess",(0x1 << 19), true),
+ _script_perm("UseGameControlInputs",(0x1 << 20), false)
} };
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index c595fc42ca..49c5bf27cd 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -193,7 +193,7 @@ bool LLTool::handleKey(KEY key, MASK mask)
LLTool* LLTool::getOverrideTool(MASK mask)
{
// NOTE: if in flycam mode, ALT-ZOOM camera should be disabled
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ if (gAgent.isCameraExternallyDriven())
{
return NULL;
}
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index b8878b1e6f..a93f37e09a 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -62,6 +62,8 @@ bool gCameraBtnPan = false;
const S32 SLOP_RANGE = 4;
+extern bool agent_push_forward(const LLKeyPressState& s);
+
//
// Camera - shared functionality
//
@@ -80,8 +82,10 @@ LLToolCamera::LLToolCamera()
mMouseSteering(false),
mMouseUpX(0),
mMouseUpY(0),
- mMouseUpMask(MASK_NONE)
-{ }
+ mMouseUpMask(MASK_NONE),
+ mKeyState(LLKeyPressState(false,false,false,1.0))
+{
+}
LLToolCamera::~LLToolCamera()
@@ -337,6 +341,12 @@ bool LLToolCamera::handleMouseUp(S32 x, S32 y, MASK mask)
bool LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
{
+ if (gViewerWindow->getRightMouseDown())
+ {
+ mKeyState.mState = KEYSTATE_LEVEL;
+ agent_push_forward(mKeyState);
+ }
+
S32 dx = gViewerWindow->getCurrentMouseDX();
S32 dy = gViewerWindow->getCurrentMouseDY();
@@ -471,8 +481,36 @@ bool LLToolCamera::handleHover(S32 x, S32 y, MASK mask)
return true;
}
+bool LLToolCamera::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(mMouseSteering)
+ {
+ mKeyState.mState = KEYSTATE_DOWN;
+ agent_push_forward(mKeyState);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool LLToolCamera::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+ if (mMouseSteering)
+ {
+ mKeyState.mState = KEYSTATE_UP;
+ agent_push_forward(mKeyState);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
void LLToolCamera::onMouseCaptureLost()
{
releaseMouse();
+ handleRightMouseUp(0, 0, 0);
}
diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h
index c2460e7aa4..56a7501f50 100644
--- a/indra/newview/lltoolfocus.h
+++ b/indra/newview/lltoolfocus.h
@@ -27,20 +27,23 @@
#ifndef LL_LLTOOLFOCUS_H
#define LL_LLTOOLFOCUS_H
+#include "llkeyboard.h"
#include "lltool.h"
class LLPickInfo;
class LLToolCamera
-: public LLTool, public LLSingleton<LLToolCamera>
+: public LLTool, public LLSimpleton<LLToolCamera>
{
- LLSINGLETON(LLToolCamera);
- virtual ~LLToolCamera();
public:
+ LLToolCamera();
+ virtual ~LLToolCamera();
virtual bool handleMouseDown(S32 x, S32 y, MASK mask) override;
virtual bool handleMouseUp(S32 x, S32 y, MASK mask) override;
virtual bool handleHover(S32 x, S32 y, MASK mask) override;
+ virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+ virtual bool handleRightMouseUp(S32 x, S32 y, MASK mask) override;
virtual void onMouseCaptureLost() override;
@@ -72,6 +75,7 @@ protected:
S32 mMouseUpX; // needed for releaseMouse()
S32 mMouseUpY;
MASK mMouseUpMask;
+ LLKeyPressState mKeyState;
};
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index ddcabd9cda..2559f1065f 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -35,6 +35,7 @@
#include "llagentcamera.h"
#include "llfloaterimnearbychat.h"
#include "llfocusmgr.h"
+#include "llgamecontrol.h"
#include "llkeybind.h" // LLKeyData
#include "llmorphview.h"
#include "llmoveview.h"
@@ -47,6 +48,7 @@
#include "llfloatercamera.h"
#include "llinitparam.h"
#include "llselectmgr.h"
+#include "llviewercamera.h"
//
// Constants
@@ -61,15 +63,18 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true);
+static U64 g_lastUpdateTime { 0 };
+static F32 g_deltaTime { 0.0f };
+
struct LLKeybindFunctionData
{
- LLKeybindFunctionData(std::function<bool(EKeystate keystate)> function, bool global)
+ LLKeybindFunctionData(LLKeyFunc function, bool global)
:
mFunction(function),
mIsGlobal(global)
{
}
- std::function<bool(EKeystate keystate)> mFunction;
+ LLKeyFunc mFunction;
// todo: might be good idea to make this into enum, like: global/inworld/menu
bool mIsGlobal;
};
@@ -82,16 +87,16 @@ struct LLKeyboardActionRegistry
LLViewerInput gViewerInput;
-bool agent_jump( EKeystate s )
+bool agent_jump( const LLKeyPressState& s )
{
static bool first_fly_attempt(true);
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
first_fly_attempt = true;
return true;
}
- F32 time = gKeyboard->getCurKeyElapsedTime();
- S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+ F32 time = s.mElapsedTime;
+ S32 frame_count = s.mElapsedFrames;
if( time < FLY_TIME
|| frame_count <= FLY_FRAMES
@@ -109,9 +114,22 @@ bool agent_jump( EKeystate s )
return true;
}
-bool agent_push_down( EKeystate s )
+bool agent_push_down( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
+ gAgent.moveUp(-1);
+ return true;
+}
+
+bool agent_toggle_down( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
+
+ if (KEYSTATE_DOWN == s.mState
+ && !gAgent.getFlying())
+ {
+ gAgent.toggleCrouch();
+ }
gAgent.moveUp(-1);
return true;
}
@@ -128,16 +146,16 @@ static void agent_check_temporary_run(LLAgent::EDoubleTapRunMode mode)
}
}
-static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode mode)
+static void agent_handle_doubletap_run(const LLKeyPressState& s, LLAgent::EDoubleTapRunMode mode)
{
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
// Note: in case shift is already released, slide left/right run
// will be released in agent_turn_left()/agent_turn_right()
agent_check_temporary_run(mode);
}
else if (gSavedSettings.getBOOL("AllowTapTapHoldRun") &&
- KEYSTATE_DOWN == s &&
+ KEYSTATE_DOWN == s.mState &&
!gAgent.getRunning())
{
if (gAgent.mDoubleTapRunMode == mode &&
@@ -155,13 +173,13 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m
}
}
-static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
+static void agent_push_forwardbackward( const LLKeyPressState& s, S32 direction, LLAgent::EDoubleTapRunMode mode )
{
agent_handle_doubletap_run(s, mode);
- if (KEYSTATE_UP == s) return;
+ if (KEYSTATE_UP == s.mState) return;
- F32 time = gKeyboard->getCurKeyElapsedTime();
- S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+ F32 time = s.mElapsedTime;
+ S32 frame_count = s.mElapsedFrames;
if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
{
@@ -173,9 +191,9 @@ static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDo
}
}
-bool camera_move_forward( EKeystate s );
+bool camera_move_forward( const LLKeyPressState& s );
-bool agent_push_forward( EKeystate s )
+bool agent_push_forward( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
@@ -191,9 +209,9 @@ bool agent_push_forward( EKeystate s )
return true;
}
-bool camera_move_backward( EKeystate s );
+bool camera_move_backward( const LLKeyPressState& s );
-bool agent_push_backward( EKeystate s )
+bool agent_push_backward( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
@@ -213,12 +231,12 @@ bool agent_push_backward( EKeystate s )
return true;
}
-static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode )
+static void agent_slide_leftright( const LLKeyPressState& s, S32 direction, LLAgent::EDoubleTapRunMode mode )
{
agent_handle_doubletap_run(s, mode);
- if( KEYSTATE_UP == s ) return;
- F32 time = gKeyboard->getCurKeyElapsedTime();
- S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
+ if( KEYSTATE_UP == s.mState ) return;
+ F32 time = s.mElapsedTime;
+ S32 frame_count = s.mElapsedFrames;
if( time < NUDGE_TIME || frame_count <= NUDGE_FRAMES)
{
@@ -231,7 +249,7 @@ static void agent_slide_leftright( EKeystate s, S32 direction, LLAgent::EDoubleT
}
-bool agent_slide_left( EKeystate s )
+bool agent_slide_left( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
agent_slide_leftright(s, 1, LLAgent::DOUBLETAP_SLIDELEFT);
@@ -239,16 +257,16 @@ bool agent_slide_left( EKeystate s )
}
-bool agent_slide_right( EKeystate s )
+bool agent_slide_right( const LLKeyPressState& s )
{
if(gAgent.isMovementLocked()) return true;
agent_slide_leftright(s, -1, LLAgent::DOUBLETAP_SLIDERIGHT);
return true;
}
-bool camera_spin_around_cw( EKeystate s );
+bool camera_spin_around_cw( const LLKeyPressState& s );
-bool agent_turn_left(EKeystate s)
+bool agent_turn_left(const LLKeyPressState& s)
{
//in free camera control mode we need to intercept keyboard events for avatar movements
if (LLFloaterCamera::inFreeCameraMode())
@@ -265,21 +283,21 @@ bool agent_turn_left(EKeystate s)
}
else
{
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
// Check temporary running. In case user released 'left' key with shift already released.
agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDELEFT);
return true;
}
- F32 time = gKeyboard->getCurKeyElapsedTime();
- gAgent.moveYaw( LLFloaterMove::getYawRate( time ) );
+ F32 time = s.mElapsedTime;
+ gAgent.moveYaw( LLFloaterMove::getYawRate( time ) * s.mValue );
}
return true;
}
-bool camera_spin_around_ccw( EKeystate s );
+bool camera_spin_around_ccw( const LLKeyPressState& s );
-bool agent_turn_right( EKeystate s )
+bool agent_turn_right( const LLKeyPressState& s )
{
//in free camera control mode we need to intercept keyboard events for avatar movements
if (LLFloaterCamera::inFreeCameraMode())
@@ -296,48 +314,58 @@ bool agent_turn_right( EKeystate s )
}
else
{
- if (KEYSTATE_UP == s)
+ if (KEYSTATE_UP == s.mState)
{
// Check temporary running. In case user released 'right' key with shift already released.
agent_check_temporary_run(LLAgent::DOUBLETAP_SLIDERIGHT);
return true;
}
- F32 time = gKeyboard->getCurKeyElapsedTime();
- gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) );
+ F32 time = s.mElapsedTime;
+ gAgent.moveYaw( -LLFloaterMove::getYawRate( time ) * s.mValue );
}
return true;
}
-bool agent_look_up( EKeystate s )
+bool agent_look_up( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgent.movePitch(-1);
//gAgent.rotate(-2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
return true;
}
-bool agent_look_down( EKeystate s )
+bool agent_look_down( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgent.movePitch(1);
//gAgent.rotate(2.f * DEG_TO_RAD, gAgent.getFrame().getLeftAxis() );
return true;
}
-bool agent_toggle_fly( EKeystate s )
+bool agent_toggle_fly( const LLKeyPressState& s )
{
// Only catch the edge
- if (KEYSTATE_DOWN == s )
+ if (KEYSTATE_DOWN == s.mState )
{
LLAgent::toggleFlying();
}
return true;
}
-F32 get_orbit_rate()
+bool agent_toggle_flycam( const LLKeyPressState& s )
+{
+ // Only catch the edge
+ if (KEYSTATE_DOWN == s.mState )
+ {
+ gAgent.toggleFlycam();
+ }
+ return true;
+}
+
+F32 get_orbit_rate( const LLKeyPressState& s )
{
- F32 time = gKeyboard->getCurKeyElapsedTime();
+ F32 time = s.mElapsedTime;
if( time < NUDGE_TIME )
{
F32 rate = ORBIT_NUDGE_RATE + time * (1 - ORBIT_NUDGE_RATE)/ NUDGE_TIME;
@@ -350,26 +378,46 @@ F32 get_orbit_rate()
}
}
-bool camera_spin_around_ccw( EKeystate s )
+// Keyboard-driven flycam translate/rotate: sets a per-channel rate that
+// LLAgent::updateFlycam() blends in and clears every frame (same
+// "set while held, cleared once consumed" idiom as mOrbitInKey/mPanUpKey).
+template <U8 CHANNEL, S32 SIGN>
+bool flycam_axis_key(const LLKeyPressState& s)
+{
+ if (KEYSTATE_UP == s.mState) return true;
+ gAgent.setFlycamKeyInput(CHANNEL, SIGN * get_orbit_rate(s));
+ return true;
+}
+
+bool flycam_unroll_key(const LLKeyPressState& s)
{
- if( KEYSTATE_UP == s ) return true;
+ if (KEYSTATE_DOWN == s.mState)
+ {
+ gAgent.setFlycamKeyUnroll(true);
+ }
+ return true;
+}
+
+bool camera_spin_around_ccw( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
+ gAgentCamera.setOrbitLeftKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_around_cw( EKeystate s )
+bool camera_spin_around_cw( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitRightKey( get_orbit_rate() );
+ gAgentCamera.setOrbitRightKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_around_ccw_sitting( EKeystate s )
+bool camera_spin_around_ccw_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT ) return true;
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT ) return true;
if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
{
//send keystrokes, but do not change camera
@@ -379,15 +427,15 @@ bool camera_spin_around_ccw_sitting( EKeystate s )
{
//change camera but do not send keystrokes
gAgentCamera.unlockView();
- gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
+ gAgentCamera.setOrbitLeftKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_spin_around_cw_sitting( EKeystate s )
+bool camera_spin_around_cw_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT ) return true;
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT ) return true;
if (gAgent.rotateGrabbed() || gAgentCamera.sitCameraEnabled() || gAgent.getRunning())
{
//send keystrokes, but do not change camera
@@ -397,32 +445,32 @@ bool camera_spin_around_cw_sitting( EKeystate s )
{
//change camera but do not send keystrokes
gAgentCamera.unlockView();
- gAgentCamera.setOrbitRightKey( get_orbit_rate() );
+ gAgentCamera.setOrbitRightKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_spin_over( EKeystate s )
+bool camera_spin_over( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitUpKey( get_orbit_rate() );
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_under( EKeystate s )
+bool camera_spin_under( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitDownKey( get_orbit_rate() );
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
return true;
}
-bool camera_spin_over_sitting( EKeystate s )
+bool camera_spin_over_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
if (gAgent.upGrabbed() || gAgentCamera.sitCameraEnabled())
{
//send keystrokes, but do not change camera
@@ -431,15 +479,15 @@ bool camera_spin_over_sitting( EKeystate s )
else
{
//change camera but do not send keystrokes
- gAgentCamera.setOrbitUpKey( get_orbit_rate() );
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_spin_under_sitting( EKeystate s )
+bool camera_spin_under_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
if (gAgent.downGrabbed() || gAgentCamera.sitCameraEnabled())
{
//send keystrokes, but do not change camera
@@ -448,45 +496,68 @@ bool camera_spin_under_sitting( EKeystate s )
else
{
//change camera but do not send keystrokes
- gAgentCamera.setOrbitDownKey( get_orbit_rate() );
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_move_forward( EKeystate s )
+bool camera_roll_left(const LLKeyPressState& s)
+{
+ if (KEYSTATE_UP == s.mState) return true;
+ gAgentCamera.unlockView();
+ gAgentCamera.setRollLeftKey(get_orbit_rate(s));
+ return true;
+}
+
+bool camera_roll_right(const LLKeyPressState& s)
{
- if( KEYSTATE_UP == s ) return true;
+ if (KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitInKey( get_orbit_rate() );
+ gAgentCamera.setRollRightKey(get_orbit_rate(s));
return true;
}
+bool camera_roll_reset(const LLKeyPressState& s)
+{
+ if (KEYSTATE_UP == s.mState ) return true;
+ gAgentCamera.resetCameraRoll();
+ return true;
+}
-bool camera_move_backward( EKeystate s )
+bool camera_move_forward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+ gAgentCamera.setOrbitInKey( get_orbit_rate(s) );
return true;
}
-bool camera_move_forward_sitting( EKeystate s )
+
+bool camera_move_backward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
+ gAgentCamera.unlockView();
+ gAgentCamera.setOrbitOutKey( get_orbit_rate(s) );
+ return true;
+}
+
+bool camera_move_forward_sitting( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD ) return true;
if (gAgent.forwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
{
agent_push_forward(s);
}
else
{
- gAgentCamera.setOrbitInKey( get_orbit_rate() );
+ gAgentCamera.setOrbitInKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_move_backward_sitting( EKeystate s )
+bool camera_move_backward_sitting( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD ) return true;
+ if( KEYSTATE_UP == s.mState && gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD ) return true;
if (gAgent.backwardGrabbed() || gAgentCamera.sitCameraEnabled() || (gAgent.getRunning() && !gAgent.getAlwaysRun()))
{
@@ -494,137 +565,137 @@ bool camera_move_backward_sitting( EKeystate s )
}
else
{
- gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+ gAgentCamera.setOrbitOutKey( get_orbit_rate(s) );
}
return true;
}
-bool camera_pan_up( EKeystate s )
+bool camera_pan_up( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanUpKey( get_orbit_rate() );
+ gAgentCamera.setPanUpKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_down( EKeystate s )
+bool camera_pan_down( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanDownKey( get_orbit_rate() );
+ gAgentCamera.setPanDownKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_left( EKeystate s )
+bool camera_pan_left( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanLeftKey( get_orbit_rate() );
+ gAgentCamera.setPanLeftKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_right( EKeystate s )
+bool camera_pan_right( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanRightKey( get_orbit_rate() );
+ gAgentCamera.setPanRightKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_in( EKeystate s )
+bool camera_pan_in( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanInKey( get_orbit_rate() );
+ gAgentCamera.setPanInKey( get_orbit_rate(s) );
return true;
}
-bool camera_pan_out( EKeystate s )
+bool camera_pan_out( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
- gAgentCamera.setPanOutKey( get_orbit_rate() );
+ gAgentCamera.setPanOutKey( get_orbit_rate(s) );
return true;
}
-bool camera_move_forward_fast( EKeystate s )
+bool camera_move_forward_fast( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
gAgentCamera.setOrbitInKey(2.5f);
return true;
}
-bool camera_move_backward_fast( EKeystate s )
+bool camera_move_backward_fast( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gAgentCamera.unlockView();
gAgentCamera.setOrbitOutKey(2.5f);
return true;
}
-bool edit_avatar_spin_ccw( EKeystate s )
+bool edit_avatar_spin_ccw( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitLeftKey( get_orbit_rate() );
- //gMorphView->orbitLeft( get_orbit_rate() );
+ gAgentCamera.setOrbitLeftKey( get_orbit_rate(s) );
+ //gMorphView->orbitLeft( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_spin_cw( EKeystate s )
+bool edit_avatar_spin_cw( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitRightKey( get_orbit_rate() );
- //gMorphView->orbitRight( get_orbit_rate() );
+ gAgentCamera.setOrbitRightKey( get_orbit_rate(s) );
+ //gMorphView->orbitRight( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_spin_over( EKeystate s )
+bool edit_avatar_spin_over( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitUpKey( get_orbit_rate() );
- //gMorphView->orbitUp( get_orbit_rate() );
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
+ //gMorphView->orbitUp( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_spin_under( EKeystate s )
+bool edit_avatar_spin_under( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitDownKey( get_orbit_rate() );
- //gMorphView->orbitDown( get_orbit_rate() );
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
+ //gMorphView->orbitDown( get_orbit_rate(s) );
return true;
}
-bool edit_avatar_move_forward( EKeystate s )
+bool edit_avatar_move_forward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitInKey( get_orbit_rate() );
+ gAgentCamera.setOrbitInKey( get_orbit_rate(s) );
//gMorphView->orbitIn();
return true;
}
-bool edit_avatar_move_backward( EKeystate s )
+bool edit_avatar_move_backward( const LLKeyPressState& s )
{
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
gMorphView->setCameraDrivenByKeys( true );
- gAgentCamera.setOrbitOutKey( get_orbit_rate() );
+ gAgentCamera.setOrbitOutKey( get_orbit_rate(s) );
//gMorphView->orbitOut();
return true;
}
-bool stop_moving( EKeystate s )
+bool stop_moving( const LLKeyPressState& s )
{
//it's supposed that 'stop moving' key will be held down for some time
- if( KEYSTATE_UP == s ) return true;
+ if( KEYSTATE_UP == s.mState ) return true;
// stop agent
gAgent.setControlFlags(AGENT_CONTROL_STOP);
@@ -633,23 +704,23 @@ bool stop_moving( EKeystate s )
return true;
}
-bool start_chat( EKeystate s )
+bool start_chat( const LLKeyPressState& s )
{
if (LLAppViewer::instance()->quitRequested())
{
return true; // can't talk, gotta go, kthxbye!
}
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
// start chat
LLFloaterIMNearbyChat::startChat(NULL);
return true;
}
-bool start_gesture( EKeystate s )
+bool start_gesture( const LLKeyPressState& s )
{
LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
- if (KEYSTATE_UP == s &&
+ if (KEYSTATE_UP == s.mState &&
! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
{
if ((LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->getCurrentChat().empty())
@@ -666,9 +737,9 @@ bool start_gesture( EKeystate s )
return true;
}
-bool run_forward(EKeystate s)
+bool run_forward(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_FORWARD)
{
@@ -680,7 +751,7 @@ bool run_forward(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if(KEYSTATE_UP == s)
+ else if(KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_FORWARD)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -691,9 +762,9 @@ bool run_forward(EKeystate s)
return true;
}
-bool run_backward(EKeystate s)
+bool run_backward(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_BACKWARD)
{
@@ -705,7 +776,7 @@ bool run_backward(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if (KEYSTATE_UP == s)
+ else if (KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_BACKWARD)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -716,9 +787,9 @@ bool run_backward(EKeystate s)
return true;
}
-bool run_left(EKeystate s)
+bool run_left(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDELEFT)
{
@@ -730,7 +801,7 @@ bool run_left(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if (KEYSTATE_UP == s)
+ else if (KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_SLIDELEFT)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -741,9 +812,9 @@ bool run_left(EKeystate s)
return true;
}
-bool run_right(EKeystate s)
+bool run_right(const LLKeyPressState& s)
{
- if (KEYSTATE_UP != s)
+ if (KEYSTATE_UP != s.mState)
{
if (gAgent.mDoubleTapRunMode != LLAgent::DOUBLETAP_SLIDERIGHT)
{
@@ -755,7 +826,7 @@ bool run_right(EKeystate s)
gAgent.sendWalkRun(true);
}
}
- else if (KEYSTATE_UP == s)
+ else if (KEYSTATE_UP == s.mState)
{
if (gAgent.mDoubleTapRunMode == LLAgent::DOUBLETAP_SLIDERIGHT)
gAgent.mDoubleTapRunMode = LLAgent::DOUBLETAP_NONE;
@@ -766,9 +837,9 @@ bool run_right(EKeystate s)
return true;
}
-bool toggle_run(EKeystate s)
+bool toggle_run(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
bool run = gAgent.getAlwaysRun();
if (run)
{
@@ -784,9 +855,9 @@ bool toggle_run(EKeystate s)
return true;
}
-bool toggle_sit(EKeystate s)
+bool toggle_sit(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
if (gAgent.isSitting())
{
gAgent.standUp();
@@ -798,25 +869,25 @@ bool toggle_sit(EKeystate s)
return true;
}
-bool toggle_pause_media(EKeystate s) // analogue of play/pause button in top bar
+bool toggle_pause_media(const LLKeyPressState& s) // analogue of play/pause button in top bar
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
bool pause = LLViewerMedia::getInstance()->isAnyMediaPlaying();
LLViewerMedia::getInstance()->setAllMediaPaused(pause);
return true;
}
-bool toggle_enable_media(EKeystate s)
+bool toggle_enable_media(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
bool pause = LLViewerMedia::getInstance()->isAnyMediaPlaying() || LLViewerMedia::getInstance()->isAnyMediaShowing();
LLViewerMedia::getInstance()->setAllMediaEnabled(!pause);
return true;
}
-bool walk_to(EKeystate s)
+bool walk_to(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s)
+ if (KEYSTATE_DOWN != s.mState)
{
// teleport/walk is usually on mouseclick, mouseclick needs
// to let AGENT_CONTROL_LBUTTON_UP happen if teleport didn't,
@@ -827,29 +898,29 @@ bool walk_to(EKeystate s)
return LLToolPie::getInstance()->walkToClickedLocation();
}
-bool teleport_to(EKeystate s)
+bool teleport_to(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return false;
+ if (KEYSTATE_DOWN != s.mState) return false;
return LLToolPie::getInstance()->teleportToClickedLocation();
}
-bool toggle_voice(EKeystate s)
+bool toggle_voice(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s.mState) return true;
if (!LLAgent::isActionAllowed("speak")) return false;
LLVoiceClient::getInstance()->toggleUserPTTState();
return true;
}
-bool voice_follow_key(EKeystate s)
+bool voice_follow_key(const LLKeyPressState& s)
{
- if (KEYSTATE_DOWN == s)
+ if (KEYSTATE_DOWN == s.mState)
{
if (!LLAgent::isActionAllowed("speak")) return false;
LLVoiceClient::getInstance()->setUserPTTState(true);
return true;
}
- else if (KEYSTATE_UP == s && LLVoiceClient::getInstance()->getUserPTTState())
+ else if (KEYSTATE_UP == s.mState && LLVoiceClient::getInstance()->getUserPTTState())
{
LLVoiceClient::getInstance()->setUserPTTState(false);
return true;
@@ -857,7 +928,7 @@ bool voice_follow_key(EKeystate s)
return false;
}
-bool script_trigger_lbutton(EKeystate s)
+bool script_trigger_lbutton(const LLKeyPressState& s)
{
// Check for script overriding/expecting left mouse button.
// Note that this does not pass event further and depends onto mouselook.
@@ -866,7 +937,7 @@ bool script_trigger_lbutton(EKeystate s)
if (gAgent.leftButtonGrabbed())
{
bool mouselook = gAgentCamera.cameraMouselook();
- switch (s)
+ switch (s.mState)
{
case KEYSTATE_DOWN:
if (mouselook)
@@ -895,11 +966,56 @@ bool script_trigger_lbutton(EKeystate s)
return false;
}
+bool agent_pitch(const LLKeyPressState& s, F32 direction)
+{
+ if(!gAgentCamera.cameraMouselook() || KEYSTATE_UP == s.mState)
+ {
+ return false;
+ }
+ // const F32 NOMINAL_MOUSE_SENSITIVITY = 0.0025f;
+
+ // static LLCachedControl<F32> mouse_sensitivity_setting(gSavedSettings, "MouseSensitivity");
+ // F32 mouse_sensitivity = clamp_rescale(mouse_sensitivity_setting, 0.f, 15.f, 0.5f, 2.75f) * NOMINAL_MOUSE_SENSITIVITY;
+
+ const F32 fov = LLViewerCamera::getInstance()->getView() / DEFAULT_FIELD_OF_VIEW;
+ // pitch (vertical)
+ gAgent.pitch(s.mValue * fov * direction * g_deltaTime); // or -dy if InvertMouse
+ return true;
+}
+
+bool agent_pitch_forward(const LLKeyPressState& s)
+{
+ return agent_pitch(s,1);
+}
+
+bool agent_pitch_backward(const LLKeyPressState& s)
+{
+ return agent_pitch(s,-1);
+}
+
+bool agent_spin_over( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
+ //change camera but do not send keystrokes
+ gAgentCamera.setOrbitUpKey( get_orbit_rate(s) );
+ return true;
+}
+
+
+bool agent_spin_under( const LLKeyPressState& s )
+{
+ if( KEYSTATE_UP == s.mState ) return true;
+ //change camera but do not send keystrokes
+ gAgentCamera.setOrbitDownKey( get_orbit_rate(s) );
+ return true;
+}
+
+
// Used by scripts, for overriding/handling left mouse button
// see mControlsTakenCount
-bool agent_control_lbutton_handle(EKeystate s)
+bool agent_control_lbutton_handle(const LLKeyPressState& s)
{
- switch (s)
+ switch (s.mState)
{
case KEYSTATE_DOWN:
gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
@@ -913,6 +1029,20 @@ bool agent_control_lbutton_handle(EKeystate s)
return true;
}
+template <U8 N>
+bool game_control_button(const LLKeyPressState& s)
+{
+ if ( KEYSTATE_DOWN == s.mState )
+ {
+ gAgent.pressGameControlButton(N);
+ }
+ else if ( KEYSTATE_UP == s.mState )
+ {
+ gAgent.releaseGameControlButton(N);
+ }
+ return true;
+}
+
// In-world keybindings, like walking or camera
#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, LLKeybindFunctionData(ACTION, false));
// Global keybindings that should work even with floaters focused, like voice
@@ -936,6 +1066,10 @@ REGISTER_KEYBOARD_ACTION("spin_over", camera_spin_over);
REGISTER_KEYBOARD_ACTION("spin_under", camera_spin_under);
REGISTER_KEYBOARD_ACTION("spin_over_sitting", camera_spin_over_sitting);
REGISTER_KEYBOARD_ACTION("spin_under_sitting", camera_spin_under_sitting);
+REGISTER_KEYBOARD_ACTION("pitch_forward", agent_pitch_forward);
+REGISTER_KEYBOARD_ACTION("pitch_backward", agent_pitch_backward);
+REGISTER_KEYBOARD_ACTION("spin_over_agent", agent_spin_over);
+REGISTER_KEYBOARD_ACTION("spin_under_agent", agent_spin_under);
REGISTER_KEYBOARD_ACTION("move_forward", camera_move_forward);
REGISTER_KEYBOARD_ACTION("move_backward", camera_move_backward);
REGISTER_KEYBOARD_ACTION("move_forward_sitting", camera_move_forward_sitting);
@@ -962,6 +1096,7 @@ REGISTER_KEYBOARD_ACTION("run_backward", run_backward);
REGISTER_KEYBOARD_ACTION("run_left", run_left);
REGISTER_KEYBOARD_ACTION("run_right", run_right);
REGISTER_KEYBOARD_ACTION("toggle_run", toggle_run);
+REGISTER_KEYBOARD_ACTION("toggle_down", agent_toggle_down);
REGISTER_KEYBOARD_ACTION("toggle_sit", toggle_sit);
REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media);
REGISTER_KEYBOARD_ACTION("toggle_enable_media", toggle_enable_media);
@@ -970,6 +1105,55 @@ REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice);
REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key);
REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton);
+REGISTER_KEYBOARD_ACTION("roll_left", camera_roll_left);
+REGISTER_KEYBOARD_ACTION("roll_right", camera_roll_right);
+REGISTER_KEYBOARD_ACTION("roll_reset", camera_roll_reset);
+REGISTER_KEYBOARD_ACTION("toggle_flycam", agent_toggle_flycam);
+REGISTER_KEYBOARD_ACTION("flycam_move_forward", (flycam_axis_key<LLGameControl::FLYCAM_DOLLY, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_move_backward", (flycam_axis_key<LLGameControl::FLYCAM_DOLLY, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_truck_left", (flycam_axis_key<LLGameControl::FLYCAM_TRUCK, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_truck_right", (flycam_axis_key<LLGameControl::FLYCAM_TRUCK, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_move_up", (flycam_axis_key<LLGameControl::FLYCAM_BOOM, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_move_down", (flycam_axis_key<LLGameControl::FLYCAM_BOOM, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_yaw_left", (flycam_axis_key<LLGameControl::FLYCAM_PAN, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_yaw_right", (flycam_axis_key<LLGameControl::FLYCAM_PAN, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_pitch_up", (flycam_axis_key<LLGameControl::FLYCAM_TILT, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_pitch_down", (flycam_axis_key<LLGameControl::FLYCAM_TILT, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_roll_left", (flycam_axis_key<LLGameControl::FLYCAM_ROLL, -1>));
+REGISTER_KEYBOARD_ACTION("flycam_roll_right", (flycam_axis_key<LLGameControl::FLYCAM_ROLL, 1>));
+REGISTER_KEYBOARD_ACTION("flycam_unroll", flycam_unroll_key);
+REGISTER_KEYBOARD_ACTION("game_control_button_0", game_control_button<0>);
+REGISTER_KEYBOARD_ACTION("game_control_button_1", game_control_button<1>);
+REGISTER_KEYBOARD_ACTION("game_control_button_2", game_control_button<2>);
+REGISTER_KEYBOARD_ACTION("game_control_button_3", game_control_button<3>);
+REGISTER_KEYBOARD_ACTION("game_control_button_4", game_control_button<4>);
+REGISTER_KEYBOARD_ACTION("game_control_button_5", game_control_button<5>);
+REGISTER_KEYBOARD_ACTION("game_control_button_6", game_control_button<6>);
+REGISTER_KEYBOARD_ACTION("game_control_button_7", game_control_button<7>);
+REGISTER_KEYBOARD_ACTION("game_control_button_8", game_control_button<8>);
+REGISTER_KEYBOARD_ACTION("game_control_button_9", game_control_button<9>);
+REGISTER_KEYBOARD_ACTION("game_control_button_10", game_control_button<10>);
+REGISTER_KEYBOARD_ACTION("game_control_button_11", game_control_button<11>);
+REGISTER_KEYBOARD_ACTION("game_control_button_12", game_control_button<12>);
+REGISTER_KEYBOARD_ACTION("game_control_button_13", game_control_button<13>);
+REGISTER_KEYBOARD_ACTION("game_control_button_14", game_control_button<14>);
+REGISTER_KEYBOARD_ACTION("game_control_button_15", game_control_button<15>);
+REGISTER_KEYBOARD_ACTION("game_control_button_16", game_control_button<16>);
+REGISTER_KEYBOARD_ACTION("game_control_button_17", game_control_button<17>);
+REGISTER_KEYBOARD_ACTION("game_control_button_18", game_control_button<18>);
+REGISTER_KEYBOARD_ACTION("game_control_button_19", game_control_button<19>);
+REGISTER_KEYBOARD_ACTION("game_control_button_20", game_control_button<20>);
+REGISTER_KEYBOARD_ACTION("game_control_button_21", game_control_button<21>);
+REGISTER_KEYBOARD_ACTION("game_control_button_22", game_control_button<22>);
+REGISTER_KEYBOARD_ACTION("game_control_button_23", game_control_button<23>);
+REGISTER_KEYBOARD_ACTION("game_control_button_24", game_control_button<24>);
+REGISTER_KEYBOARD_ACTION("game_control_button_25", game_control_button<25>);
+REGISTER_KEYBOARD_ACTION("game_control_button_26", game_control_button<26>);
+REGISTER_KEYBOARD_ACTION("game_control_button_27", game_control_button<27>);
+REGISTER_KEYBOARD_ACTION("game_control_button_28", game_control_button<28>);
+REGISTER_KEYBOARD_ACTION("game_control_button_29", game_control_button<29>);
+REGISTER_KEYBOARD_ACTION("game_control_button_30", game_control_button<30>);
+REGISTER_KEYBOARD_ACTION("game_control_button_31", game_control_button<31>);
#undef REGISTER_KEYBOARD_ACTION
LLViewerInput::LLViewerInput()
@@ -1026,6 +1210,11 @@ bool LLViewerInput::modeFromString(const std::string& string, S32 *mode)
*mode = MODE_SITTING;
return true;
}
+ else if (cmp_string == "flycam")
+ {
+ *mode = MODE_FLYCAM;
+ return true;
+ }
S32 val = atoi(string.c_str());
if (val >= 0 && val < MODE_COUNT)
@@ -1175,8 +1364,7 @@ bool LLViewerInput::handleGlobalBindsMouse(EMouseClickType clicktype, MASK mask,
bool LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
{
size_t index;
- typedef std::function<bool(EKeystate)> function_t;
- function_t function = nullptr;
+ LLKeyFunc function = nullptr;
std::string name;
// Allow remapping of F2-F12
@@ -1265,8 +1453,7 @@ bool LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons
bool LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name)
{
size_t index;
- typedef std::function<bool(EKeystate)> function_t;
- function_t function = nullptr;
+ LLKeyFunc function = nullptr;
if (mouse == CLICK_LEFT
&& mask == MASK_NONE
@@ -1344,11 +1531,79 @@ bool LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
return true;
}
+bool LLViewerInput::bindController(const S32 mode, const LLGameControl::ActionType actionType, U8 action, const std::string& function_name)
+{
+ size_t index;
+ LLKeyFunc function = nullptr;
+
+ LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
+ if (result)
+ {
+ function = result->mFunction;
+ }
+
+ if (!function)
+ {
+ LL_WARNS_ONCE() << "Can't bind mouse key to function " << function_name << ", no function with this name found" << LL_ENDL;
+ return false;
+ }
+
+ if (mode >= MODE_COUNT)
+ {
+ LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
+ return false;
+ }
+
+ // check for duplicate first and overwrite
+ if (result->mIsGlobal)
+ {
+ auto size = mGlobalControllerBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (actionType == mGlobalControllerBindings[mode][index].mActionType && action == mGlobalControllerBindings[mode][index].mAction)
+ {
+ mGlobalControllerBindings[mode][index].mFunction = function;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ auto size = mControllerBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (actionType == mControllerBindings[mode][index].mActionType && action == mControllerBindings[mode][index].mAction)
+ {
+ mControllerBindings[mode][index].mFunction = function;
+ return true;
+ }
+ }
+ }
+
+ LLControllerBinding bind;
+ bind.mActionType = actionType;
+ bind.mAction = action;
+ bind.mFunction = function;
+ bind.mFunctionName = function_name;
+
+ if (result->mIsGlobal)
+ {
+ mGlobalControllerBindings[mode].push_back(bind);
+ }
+ else
+ {
+ mControllerBindings[mode].push_back(bind);
+ }
+
+ return true;
+}
+
LLViewerInput::KeyBinding::KeyBinding()
: key("key"),
mouse("mouse"),
mask("mask"),
- command("command")
+ command("command"),
+ controller("controller")
{}
LLViewerInput::KeyMode::KeyMode()
@@ -1360,6 +1615,7 @@ LLViewerInput::Keys::Keys()
third_person("third_person"),
sitting("sitting"),
edit_avatar("edit_avatar"),
+ flycam("flycam"),
xml_version("xml_version", 0)
{}
@@ -1369,8 +1625,10 @@ void LLViewerInput::resetBindings()
{
mGlobalKeyBindings[i].clear();
mGlobalMouseBindings[i].clear();
+ mGlobalControllerBindings[i].clear();
mKeyBindings[i].clear();
mMouseBindings[i].clear();
+ mControllerBindings[i].clear();
mLMouseDefaultHandling[i] = false;
}
}
@@ -1390,8 +1648,11 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename)
binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON);
binding_count += loadBindingMode(keys.sitting, MODE_SITTING);
binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR);
+ binding_count += loadBindingMode(keys.flycam, MODE_FLYCAM);
// verify version
+ bool needs_rewrite = false;
+
if (keys.xml_version < 1)
{
// updating from a version that was not aware of LMouse bindings
@@ -1427,6 +1688,35 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename)
keys.edit_avatar.bindings.add(mouse_binding);
}
+ needs_rewrite = true;
+ }
+
+ if (keys.xml_version < 2 && !keys.flycam.isProvided())
+ {
+ // Updating from a version that predates the flycam mode: an old
+ // customized key_bindings.xml has no <flycam> block at all, so
+ // without this fixup the user would get zero flycam keybindings
+ // (no LLKeyConflictHandler-style fallback exists in this runtime
+ // loader). Pull the authoritative default flycam bindings from
+ // the shipped app_settings file and merge them in.
+ std::string default_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
+ if (default_filename != filename)
+ {
+ Keys default_keys;
+ LLSimpleXUIParser default_parser;
+ if (default_parser.readXUI(default_filename, default_keys)
+ && default_keys.validateBlock()
+ && default_keys.flycam.isProvided())
+ {
+ keys.flycam.set(default_keys.flycam.getValue(), true);
+ binding_count += loadBindingMode(keys.flycam, MODE_FLYCAM);
+ needs_rewrite = true;
+ }
+ }
+ }
+
+ if (needs_rewrite)
+ {
// fix version
keys.xml_version.set(keybindings_xml_version, true);
@@ -1481,6 +1771,16 @@ bool compare_mouse_by_mask(LLMouseBinding i1, LLMouseBinding i2)
return (count_masks(i1.mMask) > count_masks(i2.mMask));
}
+void LLViewerInput::storeDeltaTime()
+{
+ // measure delta time and frame
+ // Note: it is possible for the deltas to be very large
+ // and it is the duty of the code that uses them to clamp as necessary
+ U64 now = LLFrameTimer::getTotalTime();
+ g_deltaTime = F32(now - g_lastUpdateTime) / (F32)(USEC_PER_SEC);
+ g_lastUpdateTime = now;
+}
+
S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode)
{
S32 binding_count = 0;
@@ -1523,6 +1823,20 @@ S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mo
LL_WARNS_ONCE() << "There might be issues in keybindings' file" << LL_ENDL;
}
}
+ if(!processed && it->controller.isProvided() && !it->controller.getValue().empty())
+ {
+ LLGameControl::ActionType actionType;
+ U8 action;
+ if(LLGameControl::actionFromString(it->controller.getValue(), actionType, action))
+ {
+ bindController(mode, actionType, action, it->command);
+ processed = true;
+ }
+ else
+ {
+ LL_WARNS_ONCE() << "There might be issues in keybindings' file" << LL_ENDL;
+ }
+ }
if (processed)
{
// total
@@ -1539,7 +1853,11 @@ S32 LLViewerInput::loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mo
EKeyboardMode LLViewerInput::getMode() const
{
- if ( gAgentCamera.cameraMouselook() )
+ if ( gAgent.isUsingFlycam() )
+ {
+ return MODE_FLYCAM;
+ }
+ else if ( gAgentCamera.cameraMouselook() )
{
return MODE_FIRST_PERSON;
}
@@ -1566,29 +1884,38 @@ bool LLViewerInput::scanKey(const std::vector<LLKeyboardBinding> &binding,
bool key_level,
bool repeat) const
{
+ // TODO implement time
+ LLKeyPressState state = LLKeyPressState(key_up, key_down, key_level, 1.0);
+ state.mRepeat = repeat;
+
for (S32 i = 0; i < binding_count; i++)
{
if (binding[i].mKey == key)
{
if ((binding[i].mMask & mask) == binding[i].mMask)
{
+ state.mElapsedTime = gKeyboard->getCurKeyElapsedTime();
+ state.mElapsedFrames = gKeyboard->getCurKeyElapsedFrameCount();
bool res = false;
if (key_down && !repeat)
{
// ...key went down this frame, call function
- res = binding[i].mFunction( KEYSTATE_DOWN );
+ state.mState = KEYSTATE_DOWN;
+ res = binding[i].mFunction( state );
return true;
}
else if (key_up)
{
// ...key went down this frame, call function
- res = binding[i].mFunction( KEYSTATE_UP );
+ state.mState = KEYSTATE_UP;
+ res = binding[i].mFunction( state );
}
else if (key_level)
{
// ...key held down from previous frame
// Not windows, just call the function.
- res = binding[i].mFunction( KEYSTATE_LEVEL );
+ state.mState = KEYSTATE_LEVEL;
+ res = binding[i].mFunction( state );
}//if
// Key+Mask combinations are supposed to be unique, so we won't find anything else
return res;
@@ -1623,6 +1950,82 @@ bool LLViewerInput::scanKey(KEY key, bool key_down, bool key_up, bool key_level)
return res;
}
+bool LLViewerInput::scanControllerInput(const LLGameControl::ActionType actionType, const U8 action, const LLKeyPressState& state) const
+{
+ S32 mode = getMode();
+
+ for(auto binding : mControllerBindings[mode])
+ {
+ if (binding.mActionType != actionType || binding.mAction != action)
+ {
+ continue;
+ }
+
+ LL_WARNS() << "Controller Val " << LLGameControl::stringFromAction(actionType, action) << state.mValue << LL_ENDL;
+
+ bool res = binding.mFunction(state);
+ if (state.mDown)
+ {
+ return true;
+ }
+ return res;
+ }
+ return false;
+}
+
+void LLViewerInput::scanController()
+{
+ LLGameControl::computeFinalState();
+ const LLGameControl::State& state = LLGameControl::getState();
+ // HACK: GameControl: supply hard-coded threshold for ON/OFF zones
+ constexpr U16 AXIS_THRESHOLD = 32768 / 8;
+
+ // TODO: GameControl: This is kind of inificient, it would be more efficient to
+ // loop the bindings and check if the keys/axes they want are active
+ // rather than looping all keys/axes then all bindings for each one
+ // But copying scanMouse pattern for now.
+
+ LLKeyPressState keyState = LLKeyPressState(true, false, false, 0.0);
+ keyState.mAnalog = true;
+
+ for(U8 i = 0;i < state.mAxes.size();i++)
+ {
+ U16 current = state.mAxes[i];
+ U16 prev = state.mPrevAxes[i];
+ keyState.mDown = prev < AXIS_THRESHOLD && current >= AXIS_THRESHOLD;
+ keyState.mLevel = prev >= AXIS_THRESHOLD && current >= AXIS_THRESHOLD;
+ keyState.mUp = prev >= AXIS_THRESHOLD && current < AXIS_THRESHOLD;
+
+ if(keyState.mDown || keyState.mLevel || keyState.mUp)
+ {
+ keyState.mElapsedTime = LLGameControl::getControllerHeldTime(LLGameControl::ActionType::DOF, i);
+ keyState.mElapsedFrames = LLGameControl::getControllerHeldFrames(LLGameControl::ActionType::DOF, i);
+ keyState.mValue = std::clamp(((F32)current) / 32767.0f, 0.0f, 1.0f);
+ keyState.mState = keyState.mDown ? KEYSTATE_DOWN : (keyState.mLevel ? KEYSTATE_LEVEL : KEYSTATE_UP);
+ scanControllerInput(LLGameControl::ActionType::DOF, i, keyState);
+ }
+ }
+
+ keyState.mAnalog = false;
+ for(U8 i = 0; i < LLGameControl::Button::NUM_BUTTONS; i++)
+ {
+ U32 flag = 1 << i;
+ bool current = (state.mButtons & flag) == flag;
+ bool prev = (state.mPrevButtons & flag) == flag;
+ if(current || prev)
+ {
+ keyState.mDown = current && !prev;
+ keyState.mLevel = current && prev;
+ keyState.mUp = !current && prev;
+ keyState.mElapsedTime = LLGameControl::getControllerHeldTime(LLGameControl::ActionType::BUTTON, i);
+ keyState.mElapsedFrames = LLGameControl::getControllerHeldFrames(LLGameControl::ActionType::BUTTON, i);
+ keyState.mValue = current ? 1.0f : 0.0f;
+ keyState.mState = keyState.mDown ? KEYSTATE_DOWN : (keyState.mLevel ? KEYSTATE_LEVEL : KEYSTATE_UP);
+ scanControllerInput(LLGameControl::ActionType::BUTTON, i, keyState);
+ }
+ }
+}
+
bool LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, bool down)
{
bool is_toolmgr_action = false;
@@ -1742,6 +2145,7 @@ bool LLViewerInput::scanMouse(
bool ignore_additional_masks
) const
{
+ LLKeyPressState keyState = LLKeyPressState(false,false,false,1.0);
for (S32 i = 0; i < binding_count; i++)
{
if (binding[i].mMouse == mouse && (ignore_additional_masks ? (binding[i].mMask & mask) == binding[i].mMask : binding[i].mMask == mask))
@@ -1750,20 +2154,31 @@ bool LLViewerInput::scanMouse(
switch (state)
{
case MOUSE_STATE_DOWN:
- res = binding[i].mFunction(KEYSTATE_DOWN);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ res = binding[i].mFunction(keyState);
break;
case MOUSE_STATE_CLICK:
// Button went down and up in scope of single frame
// might not work best with some functions,
// but some function need specific states specifically
- res = binding[i].mFunction(KEYSTATE_DOWN);
- res |= binding[i].mFunction(KEYSTATE_UP);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ res = binding[i].mFunction(keyState);
+ keyState.mDown = false;
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ res |= binding[i].mFunction(keyState);
break;
case MOUSE_STATE_LEVEL:
- res = binding[i].mFunction(KEYSTATE_LEVEL);
+ keyState.mLevel = true;
+ keyState.mState = KEYSTATE_LEVEL;
+ res = binding[i].mFunction(keyState);
break;
case MOUSE_STATE_UP:
- res = binding[i].mFunction(KEYSTATE_UP);
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ res = binding[i].mFunction(keyState);
break;
default:
break;
@@ -1775,7 +2190,7 @@ bool LLViewerInput::scanMouse(
return false;
}
-// todo: this recods key, scanMouse() triggers functions with EKeystate
+// todo: this recods key, scanMouse() triggers functions with LLKeyPressState
bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
{
bool res = false;
@@ -1790,6 +2205,8 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
// and sends AGENT_CONTROL_ML_LBUTTON_DOWN, but it only applies if ML controls
// are leftButtonGrabbed(), send a normal click otherwise.
+ LLKeyPressState keyState = LLKeyPressState(false,false,false,1.0);
+
if (!res
&& mLMouseDefaultHandling[mode]
&& (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed())
@@ -1799,18 +2216,27 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
switch (state)
{
case MOUSE_STATE_DOWN:
- agent_control_lbutton_handle(KEYSTATE_DOWN);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ agent_control_lbutton_handle(keyState);
res = true;
break;
case MOUSE_STATE_CLICK:
// might not work best with some functions,
// but some function need specific states too specifically
- agent_control_lbutton_handle(KEYSTATE_DOWN);
- agent_control_lbutton_handle(KEYSTATE_UP);
+ keyState.mDown = true;
+ keyState.mState = KEYSTATE_DOWN;
+ agent_control_lbutton_handle(keyState);
+ keyState.mDown = false;
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ agent_control_lbutton_handle(keyState);
res = true;
break;
case MOUSE_STATE_UP:
- agent_control_lbutton_handle(KEYSTATE_UP);
+ keyState.mUp = true;
+ keyState.mState = KEYSTATE_UP;
+ agent_control_lbutton_handle(keyState);
res = true;
break;
default:
diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h
index 80ba99e201..2f2860a1b5 100644
--- a/indra/newview/llviewerinput.h
+++ b/indra/newview/llviewerinput.h
@@ -28,9 +28,10 @@
#define LL_LLVIEWERINPUT_H
#include "llkeyboard.h" // For EKeystate
+#include "llgamecontrol.h" // For LLGameControl::ActionType
const S32 MAX_KEY_BINDINGS = 128; // was 60
-const S32 keybindings_xml_version = 1;
+const S32 keybindings_xml_version = 2;
const std::string script_mouse_handler_name = "script_trigger_lbutton";
class LLWindow;
@@ -65,6 +66,15 @@ public:
std::string mFunctionName;
};
+class LLControllerBinding
+{
+ public:
+ LLGameControl::ActionType mActionType;
+ U8 mAction;
+ LLKeyFunc mFunction;
+ std::string mFunctionName;
+};
+
typedef enum e_keyboard_mode
{
@@ -72,6 +82,7 @@ typedef enum e_keyboard_mode
MODE_THIRD_PERSON,
MODE_EDIT_AVATAR,
MODE_SITTING,
+ MODE_FLYCAM,
MODE_COUNT
} EKeyboardMode;
@@ -84,6 +95,7 @@ public:
mask,
command;
Optional<std::string> mouse; // Note, not mandatory for the sake of backward campatibility with keys.xml
+ Optional<std::string> controller;
KeyBinding();
};
@@ -100,7 +112,8 @@ public:
Optional<KeyMode> first_person,
third_person,
sitting,
- edit_avatar;
+ edit_avatar,
+ flycam;
Optional<S32> xml_version; // 'xml', because 'version' appears to be reserved
Keys();
};
@@ -108,6 +121,8 @@ public:
LLViewerInput();
virtual ~LLViewerInput();
+ void storeDeltaTime();
+
bool handleKey(KEY key, MASK mask, bool repeated);
bool handleKeyUp(KEY key, MASK mask);
@@ -132,6 +147,7 @@ public:
// handleMouse() records state, scanMouse() goes through states, scanMouse(click) processes individual saved states after UI is done with them
bool handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, bool down);
void scanMouse();
+ void scanController();
bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const;
bool isLMouseHandlingDefault(const S32 mode) const { return mLMouseDefaultHandling[mode]; }
@@ -165,9 +181,12 @@ private:
EMouseState state,
bool ignore_additional_masks) const;
+ bool scanControllerInput(const LLGameControl::ActionType actionType, const U8 action, const LLKeyPressState& state) const;
+
S32 loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode);
bool bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
bool bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name);
+ bool bindController(const S32 mode, const LLGameControl::ActionType actionType, U8 action, const std::string& function_name);
void resetBindings();
// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
@@ -175,13 +194,15 @@ private:
// TODO: at some point it is better to remake this, especially keyaboard part
// would be much better to send to functions actual state of the button than
// to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
- std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
- std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
- bool mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority
+ std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
+ std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
+ std::vector<LLControllerBinding> mControllerBindings[MODE_COUNT];
+ bool mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority
// keybindings that do not consume event and are handled earlier, before floaters
- std::vector<LLKeyboardBinding> mGlobalKeyBindings[MODE_COUNT];
- std::vector<LLMouseBinding> mGlobalMouseBindings[MODE_COUNT];
+ std::vector<LLKeyboardBinding> mGlobalKeyBindings[MODE_COUNT];
+ std::vector<LLMouseBinding> mGlobalMouseBindings[MODE_COUNT];
+ std::vector<LLControllerBinding> mGlobalControllerBindings[MODE_COUNT];
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp
index c4d87d7e16..899a2c2a84 100644
--- a/indra/newview/llviewerjoystick.cpp
+++ b/indra/newview/llviewerjoystick.cpp
@@ -40,6 +40,7 @@
#include "llagent.h"
#include "llagentcamera.h"
#include "llfocusmgr.h"
+#include "llgamecontrol.h"
#if LL_WINDOWS && !LL_MESA_HEADLESS
// Require DirectInput version 8
@@ -72,6 +73,8 @@ F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0};
#if LIB_NDOF
+static bool sNdofLibInitialized = false;
+
std::ostream& operator<<(std::ostream& out, NDOF_Device* ptr)
{
if (! ptr)
@@ -145,6 +148,15 @@ BOOL CALLBACK di8_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVO
{
std::string product_name = ll_convert<std::string>(std::wstring(device_instance_ptr->tszProductName));
+ // Only 3Dconnexion devices are handled by ndof: generic game controllers
+ // belong to LLGameControl (SDL), and opening them here too would feed the
+ // same physical input into the flycam twice.
+ if (!LLViewerJoystick::is3DConnexionDevice(product_name))
+ {
+ LL_DEBUGS("Joystick") << "Skipping non-3Dconnexion device: " << product_name << LL_ENDL;
+ return DIENUM_CONTINUE;
+ }
+
LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID();
bool init_device = false;
@@ -255,42 +267,43 @@ void LLViewerJoystick::updateEnabled(bool autoenable)
}
if (!gSavedSettings.getBOOL("JoystickEnabled"))
{
- mOverrideCamera = false;
+ if (gAgentCamera.isUsingFlycam())
+ {
+ gAgentCamera.toggleFlycam();
+ }
}
}
-void LLViewerJoystick::setOverrideCamera(bool val)
+bool LLViewerJoystick::getOverrideCamera()
{
- if (!gSavedSettings.getBOOL("JoystickEnabled"))
- {
- mOverrideCamera = false;
- }
- else
- {
- mOverrideCamera = val;
- }
-
- if (mOverrideCamera)
- {
- gAgentCamera.changeCameraToDefault();
- }
+ return gAgentCamera.isUsingFlycam();
}
// -----------------------------------------------------------------------------
#if LIB_NDOF
NDOF_HotPlugResult LLViewerJoystick::HotPlugAddCallback(NDOF_Device *dev)
{
+ // Note: macOS only: hotplug callbacks never fire on Windows or Linux
NDOF_HotPlugResult res = NDOF_DISCARD_HOTPLUGGED;
- LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
- if (joystick->mDriverState == JDS_UNINITIALIZED)
+ if (dev)
{
- LL_INFOS("Joystick") << "HotPlugAddCallback: will use device:" << LL_ENDL;
- ndof_dump(stderr, dev);
- joystick->mNdofDev = dev;
- joystick->mDriverState = JDS_INITIALIZED;
- res = NDOF_KEEP_HOTPLUGGED;
+ LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
+ if (joystick->mDriverState == JDS_UNINITIALIZED && is3DConnexionDevice(dev->product))
+ {
+ LL_INFOS("Joystick") << "HotPlugAddCallback: will use device: " << (void*)(dev) << LL_ENDL;
+ ndof_dump(stderr, dev);
+
+ // POTENTIAL LEAK: libndofdev has no per-device free and we belive its memory is
+ // only released by ndof_libcleanup(). We don't want to free it ourselves for
+ // worry it might still be used later, so we drop it.
+ joystick->mNdofDev = dev;
+
+ joystick->mDriverState = JDS_INITIALIZED;
+ joystick->mDeviceIs3DConnexion = true;
+ res = NDOF_KEEP_HOTPLUGGED;
+ }
+ joystick->updateEnabled(true);
}
- joystick->updateEnabled(true);
return res;
}
#endif
@@ -299,6 +312,7 @@ NDOF_HotPlugResult LLViewerJoystick::HotPlugAddCallback(NDOF_Device *dev)
#if LIB_NDOF
void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev)
{
+ // Note: macOS only: hotplug callbacks never fire on Windows or Linux
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
if (joystick->mNdofDev == dev)
{
@@ -306,6 +320,13 @@ void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev)
<< joystick->mNdofDev << "; removed device:" << LL_ENDL;
ndof_dump(stderr, dev);
joystick->mDriverState = JDS_UNINITIALIZED;
+ joystick->mDeviceIs3DConnexion = false;
+
+ // POTENTIAL LEAK: ndofdev_external.h doesn't say what becomes of 'dev' after this
+ // callback, so we don't free it or keep using it. init() allocates a new struct if
+ // it needs one (and a replug hands us a new 'dev' via HotPlugAddCallback()).
+ // If libndofdev doesn't free 'dev' itself, its memory is lost until ndof_libcleanup().
+ joystick->mNdofDev = nullptr;
}
joystick->updateEnabled(true);
}
@@ -313,18 +334,11 @@ void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev)
// -----------------------------------------------------------------------------
LLViewerJoystick::LLViewerJoystick()
-: mDriverState(JDS_UNINITIALIZED),
- mNdofDev(NULL),
- mResetFlag(false),
- mCameraUpdated(true),
- mOverrideCamera(false),
- mJoystickRun(0)
{
for (int i = 0; i < 6; i++)
{
mAxes[i] = sDelta[i] = sLastDelta[i] = 0.0f;
}
-
memset(mBtn, 0, sizeof(mBtn));
// factor in bandwidth? bandwidth = gViewerStats->mKBitStat
@@ -346,12 +360,11 @@ LLViewerJoystick::~LLViewerJoystick()
void LLViewerJoystick::init(bool autoenable)
{
#if LIB_NDOF
- static bool libinit = false;
mDriverState = JDS_INITIALIZING;
loadDeviceIdFromSettings();
- if (!libinit)
+ if (!sNdofLibInitialized)
{
// Note: The HotPlug callbacks are not actually getting called on Windows
if (ndof_libinit(HotPlugAddCallback,
@@ -363,14 +376,18 @@ void LLViewerJoystick::init(bool autoenable)
else
{
// NB: ndof_libinit succeeds when there's no device
- libinit = true;
-
- // allocate memory once for an eventual device
- mNdofDev = ndof_create();
+ sNdofLibInitialized = true;
}
}
- if (libinit)
+ if (sNdofLibInitialized && !mNdofDev)
+ {
+ // allocate memory for an eventual device; also after a hot-unplug
+ // (see HotPlugRemovalCallback()) or a failed ndof_create()
+ mNdofDev = ndof_create();
+ }
+
+ if (sNdofLibInitialized)
{
if (mNdofDev)
{
@@ -402,7 +419,7 @@ void LLViewerJoystick::init(bool autoenable)
}
else
{
- mDriverState = JDS_INITIALIZED;
+ acceptInitializedDevice();
}
}
#endif
@@ -462,7 +479,7 @@ void LLViewerJoystick::init(bool autoenable)
}
LL_INFOS("Joystick") << "ndof: mDriverState=" << mDriverState << "; mNdofDev="
- << mNdofDev << "; libinit=" << libinit << LL_ENDL;
+ << (void*)(mNdofDev) << "; libinit=" << sNdofLibInitialized << LL_ENDL;
#endif
}
@@ -475,6 +492,10 @@ void LLViewerJoystick::initDevice(LLSD &guid)
std::function<bool(std::string&, LLSD&, void*)> osx_callback;
mDriverState = JDS_INITIALIZING;
+ if (!mNdofDev)
+ {
+ return;
+ }
#if LL_WINDOWS && !LL_MESA_HEADLESS
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
device_type = DI8DEVCLASS_GAMECTRL;
@@ -498,7 +519,7 @@ void LLViewerJoystick::initDevice(LLSD &guid)
}
else
{
- mDriverState = JDS_INITIALIZED;
+ acceptInitializedDevice();
}
}
#endif
@@ -509,10 +530,10 @@ void LLViewerJoystick::initDevice(LLSD &guid)
{
LL_INFOS("Joystick") << "Failed to gather input devices. Falling back to ndof's init" << LL_ENDL;
// Failed to gather devices from window, init first suitable one
- void *preffered_device = NULL;
- mLastDeviceUUID = LLSD();
- initDevice(preffered_device);
- }
+ void *preffered_device = NULL;
+ mLastDeviceUUID = LLSD();
+ initDevice(preffered_device);
+ }
}
if (mDriverState == JDS_INITIALIZING)
@@ -528,6 +549,11 @@ bool LLViewerJoystick::initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8
#if LIB_NDOF
mLastDeviceUUID = guid;
+ if (!mNdofDev)
+ {
+ return false;
+ }
+
#if LL_DARWIN
if (guid.isMap())
{
@@ -556,6 +582,12 @@ bool LLViewerJoystick::initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8
bool LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE8* */)
{
#if LIB_NDOF
+ if (!mNdofDev)
+ {
+ mDriverState = JDS_UNINITIALIZED;
+ return false;
+ }
+
// Different joysticks will return different ranges of raw values.
// Since we want to handle every device in the same uniform way,
// we initialize the mNdofDev struct and we set the range
@@ -582,9 +614,30 @@ bool LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE
}
else
{
+ return acceptInitializedDevice();
+ }
+#endif
+ return false;
+}
+
+bool LLViewerJoystick::acceptInitializedDevice()
+{
+#if LIB_NDOF
+ // ndof_init_first() will open any joystick-like device (e.g. an Xbox
+ // controller via DirectInput), but ndof is only meant to drive 3Dconnexion
+ // devices: everything else is handled by LLGameControl (SDL). Accepting a
+ // generic controller here would have both paths drive the flycam from the
+ // same physical input.
+ mDeviceIs3DConnexion = is3DConnexionDevice(mNdofDev->product);
+ if (mDeviceIs3DConnexion)
+ {
mDriverState = JDS_INITIALIZED;
+ mSessionDevices.try_emplace(ll_safe_string(mNdofDev->product), false);
return true;
}
+ LL_INFOS("Joystick") << "Ignoring non-3Dconnexion device: " << ll_safe_string(mNdofDev->product) << LL_ENDL;
+ // Leave the state as INITIALIZING so callers still report "no matching device"
+ mDriverState = JDS_INITIALIZING;
#endif
return false;
}
@@ -593,11 +646,13 @@ bool LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE
void LLViewerJoystick::terminate()
{
#if LIB_NDOF
- if (mNdofDev != NULL)
+ if (sNdofLibInitialized)
{
ndof_libcleanup(); // frees alocated memory in mNdofDev
+ sNdofLibInitialized = false;
mDriverState = JDS_UNINITIALIZED;
mNdofDev = NULL;
+ mDeviceIs3DConnexion = false;
LL_INFOS("Joystick") << "Terminated connection with NDOF device." << LL_ENDL;
}
#endif
@@ -607,19 +662,34 @@ void LLViewerJoystick::terminate()
void LLViewerJoystick::updateStatus()
{
#if LIB_NDOF
-
- ndof_update(mNdofDev);
-
- for (int i=0; i<6; i++)
+ if (mNdofDev != NULL && mDriverState == JDS_INITIALIZED)
{
- mAxes[i] = (F32) mNdofDev->axes[i] / mNdofDev->axes_max;
- }
+ ndof_update(mNdofDev);
+ for (int i=0; i<6; i++)
+ {
+ mAxes[i] = (F32) mNdofDev->axes[i] / mNdofDev->axes_max;
+ }
+ for (int i=0; i<16; i++)
+ {
+ mBtn[i] = mNdofDev->buttons[i];
+ }
- for (int i=0; i<16; i++)
- {
- mBtn[i] = mNdofDev->buttons[i];
+ // Remember that this device produced real input, for the viewer stats.
+ // The threshold ignores small resting drift on the axes.
+ constexpr F32 USED_AXIS_THRESHOLD = 0.1f;
+ bool used = std::any_of(std::begin(mAxes), std::end(mAxes),
+ [](F32 axis) { return fabsf(axis) > USED_AXIS_THRESHOLD; })
+ || std::any_of(std::begin(mBtn), std::end(mBtn),
+ [](long btn) { return btn != 0; });
+ if (used)
+ {
+ auto it = mSessionDevices.find(ll_safe_string(mNdofDev->product));
+ if (it != mSessionDevices.end())
+ {
+ it->second = true;
+ }
+ }
}
-
#endif
}
@@ -1012,7 +1082,7 @@ void LLViewerJoystick::moveAvatar(bool reset)
F32 val, dom_mov = 0.f;
U32 dom_axis = Z_I;
#if LIB_NDOF
- bool absolute = (gSavedSettings.getBOOL("Cursor3D") && mNdofDev->absolute);
+ bool absolute = mNdofDev != NULL && (gSavedSettings.getBOOL("Cursor3D") && mNdofDev->absolute);
#else
bool absolute = false;
#endif
@@ -1159,10 +1229,6 @@ void LLViewerJoystick::moveAvatar(bool reset)
// -----------------------------------------------------------------------------
void LLViewerJoystick::moveFlycam(bool reset)
{
- static LLQuaternion sFlycamRotation;
- static LLVector3d sFlycamPosition;
- static F32 sFlycamZoom;
-
if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED
|| !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled"))
{
@@ -1183,11 +1249,15 @@ void LLViewerJoystick::moveFlycam(bool reset)
bool in_build_mode = LLToolMgr::getInstance()->inBuildMode();
if (reset || mResetFlag)
{
- sFlycamPosition = gAgentCamera.getCameraPositionGlobal();
- sFlycamRotation = LLViewerCamera::getInstance()->getQuaternion();
- sFlycamZoom = LLViewerCamera::getInstance()->getView();
+ gAgentCamera.resetFlycamToCurrentView();
- resetDeltas(axis);
+ for (U32 i = 0; i < 6; i++)
+ {
+ mJoystickFlycamLastDelta[i] = -getJoystickAxis(axis[i]);
+ mJoystickFlycamDelta[i] = 0.f;
+ }
+ mJoystickFlycamLastDelta[6] = mJoystickFlycamDelta[6] = 0.f;
+ mResetFlag = false;
return;
}
@@ -1235,9 +1305,9 @@ void LLViewerJoystick::moveFlycam(bool reset)
F32 tmp = cur_delta[i];
if (absolute)
{
- cur_delta[i] = cur_delta[i] - sLastDelta[i];
+ cur_delta[i] = cur_delta[i] - mJoystickFlycamLastDelta[i];
}
- sLastDelta[i] = tmp;
+ mJoystickFlycamLastDelta[i] = tmp;
if (cur_delta[i] > 0)
{
@@ -1267,7 +1337,7 @@ void LLViewerJoystick::moveFlycam(bool reset)
cur_delta[i] *= time;
}
- sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather;
+ mJoystickFlycamDelta[i] = mJoystickFlycamDelta[i] + (cur_delta[i]-mJoystickFlycamDelta[i])*time*feather;
is_zero = is_zero && (cur_delta[i] == 0.f);
@@ -1286,46 +1356,12 @@ void LLViewerJoystick::moveFlycam(bool reset)
}
}
- sFlycamPosition += LLVector3d(sDelta[VX], sDelta[VY], sDelta[VZ]) * sFlycamRotation;
-
- LLMatrix3 rot_mat(sDelta[3], sDelta[4], sDelta[5]);
- sFlycamRotation = LLQuaternion(rot_mat)*sFlycamRotation;
-
- if (gSavedSettings.getBOOL("AutoLeveling"))
- {
- LLMatrix3 level(sFlycamRotation);
-
- LLVector3 x = LLVector3(level.mMatrix[0]);
- LLVector3 y = LLVector3(level.mMatrix[1]);
- LLVector3 z = LLVector3(level.mMatrix[2]);
-
- y.mV[2] = 0.f;
- y.normVec();
+ bool auto_level = gSavedSettings.getBOOL("AutoLeveling");
+ F32 auto_level_fraction = llmin(feather*time, 1.f);
+ bool zoom_direct = gSavedSettings.getBOOL("ZoomDirect");
+ F32 direct_view_value = mJoystickFlycamLastDelta[6]*axis_scale[6]+dead_zone[6];
- level.setRows(x,y,z);
- level.orthogonalize();
-
- LLQuaternion quat(level);
- sFlycamRotation = nlerp(llmin(feather*time,1.f), sFlycamRotation, quat);
- }
-
- if (gSavedSettings.getBOOL("ZoomDirect"))
- {
- sFlycamZoom = sLastDelta[6]*axis_scale[6]+dead_zone[6];
- }
- else
- {
- sFlycamZoom += sDelta[6];
- }
-
- LLMatrix3 mat(sFlycamRotation);
-
- LLViewerCamera::getInstance()->setView(sFlycamZoom);
- LLVector3 new_camera_pos = gAgent.getPosAgentFromGlobal(sFlycamPosition);
- LLViewerCamera::getInstance()->setOrigin(new_camera_pos);
- LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
- LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
- LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
+ gAgentCamera.applyNdofFlycamFrameDelta(mJoystickFlycamDelta, auto_level, auto_level_fraction, zoom_direct, direct_view_value);
}
// -----------------------------------------------------------------------------
@@ -1333,11 +1369,14 @@ bool LLViewerJoystick::toggleFlycam()
{
if (!gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled"))
{
- mOverrideCamera = false;
+ if (gAgentCamera.isUsingFlycam())
+ {
+ gAgentCamera.toggleFlycam();
+ }
return false;
}
- if (!mOverrideCamera)
+ if (!gAgentCamera.isUsingFlycam())
{
gAgentCamera.changeCameraToDefault();
}
@@ -1351,8 +1390,8 @@ bool LLViewerJoystick::toggleFlycam()
gAwayTriggerTimer.reset();
}
- mOverrideCamera = !mOverrideCamera;
- if (mOverrideCamera)
+ gAgentCamera.toggleFlycam();
+ if (gAgentCamera.isUsingFlycam())
{
moveFlycam(true);
@@ -1369,7 +1408,9 @@ bool LLViewerJoystick::toggleFlycam()
void LLViewerJoystick::scanJoystick()
{
- if (mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled"))
+ if (mDriverState != JDS_INITIALIZED
+ || !gSavedSettings.getBOOL("JoystickEnabled")
+ || !mDeviceIs3DConnexion)
{
return;
}
@@ -1377,7 +1418,7 @@ void LLViewerJoystick::scanJoystick()
#if LL_WINDOWS
// On windows, the flycam is updated syncronously with a timer, so there is
// no need to update the status of the joystick here.
- if (!mOverrideCamera)
+ if (!getOverrideCamera())
#endif
updateStatus();
@@ -1402,7 +1443,7 @@ void LLViewerJoystick::scanJoystick()
toggle_flycam = 0;
}
- if (!mOverrideCamera && !(LLToolMgr::getInstance()->inBuildMode() && gSavedSettings.getBOOL("JoystickBuildEnabled")))
+ if (!getOverrideCamera() && !(LLToolMgr::getInstance()->inBuildMode() && gSavedSettings.getBOOL("JoystickBuildEnabled")))
{
moveAvatar();
}
@@ -1532,14 +1573,53 @@ std::string LLViewerJoystick::getDescription()
return res;
}
+// static
+bool LLViewerJoystick::is3DConnexionDevice(const std::string& full_name)
+{
+ // Linux (evdev) prefixes the product with the vendor, e.g. "3Dconnexion SpaceNavigator"
+ const std::string VENDOR_PREFIX("3Dconnexion ");
+ std::string device_name = full_name.compare(0, VENDOR_PREFIX.size(), VENDOR_PREFIX) == 0
+ ? full_name.substr(VENDOR_PREFIX.size())
+ : full_name;
+ bool answer = device_name.find("Space") == 0
+ && ( (device_name.find("SpaceNavigator") == 0)
+ || (device_name.find("SpaceExplorer") == 0)
+ || (device_name.find("SpaceTraveler") == 0)
+ || (device_name.find("SpacePilot") == 0)
+ || (device_name.find("SpaceMouse") == 0));
+ return answer;
+}
+
+LLSD LLViewerJoystick::getSessionStatsAsLLSD() const
+{
+ std::string current_device;
+#if LIB_NDOF
+ if (mNdofDev != nullptr && mDriverState == JDS_INITIALIZED)
+ {
+ current_device = ll_safe_string(mNdofDev->product);
+ }
+#endif
+
+ LLSD result;
+ result["enabled"] = gSavedSettings.getBOOL("JoystickEnabled");
+ LLSD& devices = result["devices"] = LLSD::emptyArray();
+ for (const auto& [name, used] : mSessionDevices)
+ {
+ LLSD entry;
+ entry["name"] = name;
+ entry["used"] = used;
+ entry["connected"] = (name == current_device);
+ devices.append(entry);
+ }
+ return result;
+}
+
bool LLViewerJoystick::isLikeSpaceNavigator() const
{
#if LIB_NDOF
- return (isJoystickInitialized()
- && (strncmp(mNdofDev->product, "SpaceNavigator", 14) == 0
- || strncmp(mNdofDev->product, "SpaceExplorer", 13) == 0
- || strncmp(mNdofDev->product, "SpaceTraveler", 13) == 0
- || strncmp(mNdofDev->product, "SpacePilot", 10) == 0));
+ return (mNdofDev != NULL
+ && isJoystickInitialized()
+ && is3DConnexionDevice(mNdofDev->product));
#else
return false;
#endif
diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h
index c989615653..d061fb77d4 100644
--- a/indra/newview/llviewerjoystick.h
+++ b/indra/newview/llviewerjoystick.h
@@ -29,6 +29,8 @@
#include "stdtypes.h"
+#include <map>
+
#if LIB_NDOF
#if LL_DARWIN
#define TARGET_OS_MAC 1
@@ -71,8 +73,9 @@ public:
void setNeedsReset(bool reset = true) { mResetFlag = reset; }
void setCameraNeedsUpdate(bool b) { mCameraUpdated = b; }
bool getCameraNeedsUpdate() const { return mCameraUpdated; }
- bool getOverrideCamera() { return mOverrideCamera; }
- void setOverrideCamera(bool val);
+ // Flycam's state now lives on LLAgentCamera (shared with the game-control
+ // flycam); this just forwards.
+ bool getOverrideCamera();
bool toggleFlycam();
void setSNDefaults();
bool isDeviceUUIDSet();
@@ -81,6 +84,13 @@ public:
std::string getDescription();
void saveDeviceIdToSettings();
+ static bool is3DConnexionDevice(const std::string& device_name);
+
+ // Summary of 3Dconnexion usage this session, for the viewer stats:
+ // { enabled, devices: [ { name, used, connected }, ... ] }
+ // 'devices' lists every 3Dconnexion device accepted at some point this session.
+ LLSD getSessionStatsAsLLSD() const;
+
protected:
void updateEnabled(bool autoenable);
void handleRun(F32 inc);
@@ -92,29 +102,44 @@ protected:
void agentJump();
void resetDeltas(S32 axis[]);
void loadDeviceIdFromSettings();
+ // Call after a successful ndof_init_first(): marks the driver initialized
+ // only if the device is a 3Dconnexion one. Returns true if accepted.
+ bool acceptInitializedDevice();
#if LIB_NDOF
static NDOF_HotPlugResult HotPlugAddCallback(NDOF_Device *dev);
static void HotPlugRemovalCallback(NDOF_Device *dev);
#endif
private:
+ // 3Dconnexion devices accepted this session (product name -> used), for viewer stats.
+ std::map<std::string, bool> mSessionDevices;
+
F32 mAxes[6];
long mBtn[16];
- EJoystickDriverState mDriverState;
- NDOF_Device *mNdofDev;
- bool mResetFlag;
- F32 mPerfScale;
- bool mCameraUpdated;
- bool mOverrideCamera;
- U32 mJoystickRun;
+ EJoystickDriverState mDriverState { JDS_UNINITIALIZED };
+ NDOF_Device *mNdofDev { nullptr };
// Windows: _GUID as U8 binary map
// MacOS: long as an U8 binary map
// Else: integer 1 for no device/ndof's default device
LLSD mLastDeviceUUID;
+ F32 mPerfScale;
+ U32 mJoystickRun { 0 };
+ bool mResetFlag { false };
+ bool mCameraUpdated { true };
+ bool mDeviceIs3DConnexion { false };
+
static F32 sLastDelta[7];
static F32 sDelta[7];
+
+ // This device's own feathered-delta state feeding
+ // LLAgentCamera::applyNdofFlycamFrameDelta() (which owns the shared flycam
+ // transform/engine, also used by the game-control flycam), kept separate
+ // from sDelta/sLastDelta above (which moveAvatar()/moveObjects() still
+ // use for non-flycam axis handling).
+ F32 mJoystickFlycamDelta[7] { 0,0,0,0,0,0,0 };
+ F32 mJoystickFlycamLastDelta[7] { 0,0,0,0,0,0,0 };
};
#endif
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index ce4c32e34e..eda867fb08 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -33,6 +33,7 @@
#include "llviewermenu.h"
// linden library includes
+#include "indra_constants.h"
#include "llavatarnamecache.h" // IDEVO (I Are Not Men!)
#include "llcombobox.h"
#include "llcoros.h"
@@ -56,6 +57,7 @@
// [SL:KB] - Patch: Appearance-PhantomAttach | Checked: Catznip-5.0
#include "llattachmentsmgr.h"
// [/SL:KB]
+#include "llavataractions.h"
#include "llcompilequeue.h"
#include "llconsole.h"
#include "lldebugview.h"
@@ -75,6 +77,7 @@
#include "llfloaterpathfindingcharacters.h"
#include "llfloaterpathfindinglinksets.h"
#include "llfloaterpay.h"
+#include "llfloaterpreference.h"
#include "llfloaterreporter.h"
#include "llfloatersearch.h"
#include "llfloaterscriptdebug.h"
@@ -83,9 +86,8 @@
#include "llfloatertools.h"
#include "llfloaterworldmap.h"
#include "llfloaterbuildoptions.h"
-#include "llavataractions.h"
-#include "lllandmarkactions.h"
#include "llgroupmgr.h"
+#include "lllandmarkactions.h"
#include "lltooltip.h"
#include "lltoolface.h"
#include "llhints.h"
@@ -1009,17 +1011,36 @@ class LLAdvancedToggleFeature : public view_listener_t
class LLAdvancedCheckFeature : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
-{
- U32 feature = feature_from_string( userdata.asString() );
- bool new_value = false;
+ {
+ U32 feature = feature_from_string( userdata.asString() );
+ bool new_value = false;
+
+ if ( feature != 0 )
+ {
+ new_value = LLPipeline::toggleRenderDebugFeatureControl( feature );
+ }
+
+ return new_value;
+ }
+};
- if ( feature != 0 )
+class LLAdvancedToggleExperiment : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
{
- new_value = LLPipeline::toggleRenderDebugFeatureControl( feature );
+ std::string feature = userdata.asString();
+ return false;
}
+};
- return new_value;
-}
+class LLAdvancedCheckExperiment : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ bool value = false;
+ std::string feature = userdata.asString();
+ return value;
+ }
};
class LLAdvancedCheckDisplayTextureDensity : public view_listener_t
@@ -4708,6 +4729,51 @@ void handle_object_sit(const LLUUID& object_id)
handle_object_sit(obj, offset);
}
+// Looks for the nearest sittable object -- one whose click-action is set to
+// CLICK_ACTION_SIT, the flag content creators set (usually alongside a custom
+// llSetSitText() label) to mark a prim as a seat -- within a hard-coded
+// multiple of the avatar's height. Used by the game-control "toggle sit"
+// action to find something to sit on before falling back to sitting on the
+// ground. Returns NULL if nothing qualifies.
+LLViewerObject* find_nearby_seat()
+{
+ if (!isAgentAvatarValid())
+ {
+ return NULL;
+ }
+
+ constexpr F32 SEAT_SEARCH_RANGE_HEIGHTS = 2.f;
+ const F32 max_dist = SEAT_SEARCH_RANGE_HEIGHTS * gAgentAvatarp->mBodySize.mV[VZ];
+ const LLVector3 agent_pos = gAgentAvatarp->getPositionAgent();
+
+ LLViewerObject* nearest_seat = NULL;
+ F32 nearest_dist_squared = max_dist * max_dist;
+
+ S32 num_objects = gObjectList.getNumObjects();
+ for (S32 i = 0; i < num_objects; ++i)
+ {
+ LLViewerObject* object = gObjectList.getObject(i);
+ if (!object || object->isDead() || object->isAttachment())
+ {
+ continue;
+ }
+
+ if (object->getPCode() != LL_PCODE_VOLUME || object->getClickAction() != CLICK_ACTION_SIT)
+ {
+ continue;
+ }
+
+ F32 dist_squared = dist_vec_squared(agent_pos, object->getPositionAgent());
+ if (dist_squared <= nearest_dist_squared)
+ {
+ nearest_seat = object;
+ nearest_dist_squared = dist_squared;
+ }
+ }
+
+ return nearest_seat;
+}
+
void near_sit_down_point(bool success, void*)
{
if (success)
@@ -6993,8 +7059,8 @@ class LLAvatarResetSkeleton : public view_listener_t
}
else
{
- avatar->resetSkeleton(false);
- }
+ avatar->resetSkeleton(false);
+ }
}
return true;
}
@@ -7059,9 +7125,9 @@ class LLAvatarResetSelfSkeletonAndAnimations : public view_listener_t
effectp->setSourceObject(gAgentAvatarp);
effectp->setTargetObject((LLViewerObject*)avatar);
effectp->setResetAnimations(true);
- }
- else
- {
+ }
+ else
+ {
avatar->resetSkeleton(true);
}
}
@@ -10310,6 +10376,9 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature");
view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature");
+ view_listener_t::addMenu(new LLAdvancedToggleExperiment(), "Advanced.ToggleExperiment");
+ view_listener_t::addMenu(new LLAdvancedCheckExperiment(), "Advanced.CheckExperiment");
+
view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity");
view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity");
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index a0d47367f4..f69a27e1a4 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -38,6 +38,7 @@ class LLParcelSelection;
class LLObjectSelection;
class LLSelectNode;
class LLViewerObject;
+class LLVector3;
void initialize_edit_menu();
void initialize_spellcheck_menu();
@@ -107,7 +108,9 @@ bool for_sale_selection(LLSelectNode* nodep);
void handle_toggle_flycam();
void handle_object_sit_or_stand();
+void handle_object_sit(LLViewerObject* object, const LLVector3& offset);
void handle_object_sit(const LLUUID& object_id);
+LLViewerObject* find_nearby_seat();
void handle_give_money_dialog();
bool enable_pay_object();
bool enable_buy_object();
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 0b1f1cfcad..74c49a4e88 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -66,6 +66,7 @@
#include "llfloaterpreference.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloatersnapshot.h"
+#include "llgamecontrol.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llimprocessing.h"
@@ -3210,8 +3211,8 @@ void process_crossed_region(LLMessageSystem* msg, void**)
}
-// sends an AgentUpdate message to the server... or not:
-// only when force_send is 'true' OR
+// sends an AgentUpdate message to the server... or not
+// e.g. only when force_send is 'true' OR
// something changed AND the update is not being throttled
void send_agent_update(bool force_send, bool send_reliable)
{
@@ -3280,8 +3281,6 @@ void send_agent_update(bool force_send, bool send_reliable)
return;
}
- bool send_update = force_send || sec_since_last_send > MAX_AGENT_UPDATE_PERIOD;
-
LLVector3 camera_pos_agent = gAgentCamera.getCameraPositionAgent(); // local to avatar's region
LLVector3 camera_at = LLViewerCamera::getInstance()->getAtAxis();
LLQuaternion body_rotation = gAgent.getFrameAgent().getQuaternion();
@@ -3298,6 +3297,7 @@ void send_agent_update(bool force_send, bool send_reliable)
flags |= AU_FLAGS_CLIENT_AUTOPILOT;
}
+ bool send_update = force_send || sec_since_last_send > MAX_AGENT_UPDATE_PERIOD;
if (!send_update)
{
// check to see if anything changed
@@ -3971,6 +3971,11 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
if (measurementp )
{
measurementp->sample(stat_value);
+ if (stat_id == LL_SIM_STAT_FPS)
+ {
+ // let GameControlData's outgoing throttle track the sim's actual rate
+ LLGameControl::setServerFrameRate(stat_value);
+ }
}
else
{
@@ -6184,7 +6189,7 @@ void process_teleport_local(LLMessageSystem *msg,void**)
gAgentCamera.slamLookAt(look_at);
}
- if ( !(gAgent.getTeleportKeepsLookAt() && LLViewerJoystick::getInstance()->getOverrideCamera()) )
+ if ( !(gAgent.getTeleportKeepsLookAt() && gAgent.isCameraExternallyDriven()) )
{
// resetView still runs (cleanup); the false args just leave the camera alone.
gAgentCamera.resetView(!keep_camera_local_tp, !keep_camera_local_tp);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 83452e2f12..bdd110c97b 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -3772,6 +3772,13 @@ bool LLViewerRegion::groupChatPostLinksEnabled() const
return ( mSimulatorFeatures.has("GroupChatPostLinksEnabled") &&
mSimulatorFeatures["GroupChatPostLinksEnabled"].asBoolean());
}
+
+bool LLViewerRegion::gameControlEnabled() const
+{
+ return ( mSimulatorFeatures.has("GameControlEnabled") &&
+ mSimulatorFeatures["GameControlEnabled"].asBoolean());
+}
+
/* Static Functions */
void log_capabilities(const CapabilityMap &capmap)
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 0ad2038490..082325ffe5 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -354,6 +354,9 @@ public:
bool groupChatPostLinksEnabled() const;
+ // does the simulator accept GameControlData messages?
+ bool gameControlEnabled() const;
+
typedef enum
{
CACHE_MISS_TYPE_TOTAL = 0, // total cache miss - object not in cache
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index ab684833ed..8e1169ddbd 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -51,6 +51,8 @@
#include "llfloatertools.h"
#include "lldebugview.h"
#include "llfasttimerview.h"
+#include "llgamecontrol.h"
+#include "llviewerjoystick.h"
#include "llviewerregion.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
@@ -782,6 +784,17 @@ void send_viewer_stats(bool include_preferences)
system["shader_level"] = shader_level;
+ LLSD game_control = LLGameControl::getSessionStatsAsLLSD();
+ if (game_control["devices"].size() > 0)
+ {
+ body["game_control"] = game_control;
+ }
+ LLSD ndof = LLViewerJoystick::instance().getSessionStatsAsLLSD();
+ if (ndof["devices"].size() > 0)
+ {
+ body["3DConnexion"] = ndof;
+ }
+
LLSD &download = body["downloads"];
download["world_kbytes"] = F64Kilobytes(gTotalWorldData).value();
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index bafe4d55c0..908b21e9d0 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -114,6 +114,7 @@
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
#include "llfontfreetype.h"
+#include "llgamecontrol.h"
#include "llgesturemgr.h"
#include "llglheaders.h"
#include "llhudmanager.h"
@@ -763,6 +764,50 @@ public:
av_iter++;
}
}
+ static LLCachedControl<bool> debug_show_game_controller_state(gSavedSettings, "DebugShowControllerState", false);
+ if (debug_show_game_controller_state())
+ {
+ static const char* axis_names[LLGameControl::NUM_MOVE_DIRS] = {
+ "LEFT","RIGHT","FORWARD","BACKWARD", "TURN LEFT", "TURN RIGHT",
+ "LOOK UP","LOOK DOWN", "UP", "DOWN", "ROLL LEFT", "ROLL RIGHT"
+ };
+ static const char* button_names[LLGameControl::NUM_BUTTONS] = {
+ "A", "B", "X", "Y", "BACK", "SELECT", "START", "LSTICK", "RSTICK",
+ "LSHOULDER", "RSHOULDER", "UP", "DOWN", "LEFT", "RIGHT",
+ "MISC1", "PADDLE1", "PADDLE2", "PADDLE3", "PADDLE4", "TOUCHPAD",
+ "B21", "B22", "B23", "B24", "B25", "B26", "B27", "B28", "B29", "B30", "B31",
+ };
+ const LLGameControl::State& gc_state = LLGameControl::getState();
+ for (size_t i = 0; i < gc_state.mAxes.size(); i+=2)
+ {
+ addText(xpos, ypos, llformat(
+ " %-10s %6d %-10s %6d",
+ (i < LLGameControl::NUM_MOVE_DIRS) ? axis_names[i] : "AXIS",
+ (S32)gc_state.mAxes[i],
+ ((i+1) < LLGameControl::NUM_MOVE_DIRS) ? axis_names[i+1] : "AXIS",
+ i < gc_state.mAxes.size() ? (S32)gc_state.mAxes[i+1] : 0
+ ));
+ ypos += y_inc;
+ }
+ addText(xpos, ypos, "Game Controller Final State Axes");
+ ypos += y_inc;
+ static const char* pressed = "░░░░░░░░░░";
+ static const char* released = " ";
+ for (U8 i = 0; i < LLGameControl::NUM_BUTTONS; i += 4)
+ {
+ addText(xpos, ypos, llformat(
+ " %-10s %-10s %-10s %-10s",
+ gc_state.mButtons & (1 << (i+0)) ? pressed : released,
+ gc_state.mButtons & (1 << (i+1)) ? pressed : released,
+ gc_state.mButtons & (1 << (i+2)) ? pressed : released,
+ gc_state.mButtons & (1 << (i+3)) ? pressed : released
+ ));
+ addText(xpos, ypos, llformat(" %-10s %-10s %-10s %-10s", button_names[i],button_names[i+1],button_names[i+2],button_names[i+3]));
+ ypos += y_inc;
+ }
+ addText(xpos, ypos, "Game Controller Final State Buttons");
+ ypos += y_inc;
+ }
static LLCachedControl<bool> debug_show_render_matrices(gSavedSettings, "DebugShowRenderMatrices", false);
if (debug_show_render_matrices())
{
@@ -2928,6 +2973,17 @@ void LLViewerWindow::draw()
// Draw tool specific overlay on world
LLToolMgr::getInstance()->getCurrentTool()->draw();
+ if (gAgentCamera.isUsingFlycam() && LLGameControl::isFlycamCrosshairEnabled())
+ {
+ // Same crosshair image/centering LLToolGun::draw() uses for
+ // mouselook's "ShowCrosshairs" -- flycam has no LLTool of its own
+ // to hang this off of, so it's drawn here instead.
+ LLUIImagePtr crosshair = LLUI::getUIImage("crosshairs.tga");
+ crosshair->draw(
+ ( getWorldViewRectScaled().getWidth() - crosshair->getWidth() ) / 2,
+ ( getWorldViewRectScaled().getHeight() - crosshair->getHeight() ) / 2);
+ }
+
if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() )
{
drawMouselookInstructions();
@@ -3515,6 +3571,22 @@ void LLViewerWindow::moveCursorToCenter()
}
}
+void LLViewerWindow::moveCursorTo(S32 x, S32 y)
+{
+ // Clamp to the whole window (not just the world view) so a gamepad-driven
+ // cursor (see LLAgent::applyExternalActions()'s CONTROL_MODE_CURSOR
+ // handling) can reach the menu bar and toolbars, but not escape the window.
+ x = llclamp(x, 0, getWindowWidthScaled());
+ y = llclamp(y, 0, getWindowHeightScaled());
+
+ LLUI::getInstance()->setMousePositionScreen(x, y);
+
+ // on a forced move, all deltas get zeroed out to prevent jumping
+ mCurrentMousePoint.set(x, y);
+ mLastMousePoint.set(x, y);
+ mCurrentMouseDelta.set(0, 0);
+}
+
//////////////////////////////////////////////////////////////////////
//
@@ -4645,7 +4717,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
LLVector3 mouse_world_start = mouse_point_global;
LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth;
- if (!LLViewerJoystick::getInstance()->getOverrideCamera())
+ if (!gAgent.isCameraExternallyDriven())
{ //always set raycast intersection to mouse_world_end unless
//flycam is on (for DoF effect)
gDebugRaycastIntersection.load3(mouse_world_end.mV);
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 20f2e106c9..e46a53036b 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -326,6 +326,7 @@ public:
void hideCursor();
bool getCursorHidden() { return mCursorHidden; }
void moveCursorToCenter(); // move to center of window
+ void moveCursorTo(S32 x, S32 y); // move to an arbitrary screen-space (GL) position, clamped to the world view
void initTextures(S32 location_id);
void setShowProgress(const bool show);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index e672ca22dc..240078ce9f 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3474,7 +3474,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
static LLCachedControl<bool> render_name_show_self(gSavedSettings, "RenderNameShowSelf");
static LLCachedControl<S32> name_tag_mode(gSavedSettings, "AvatarNameTagMode");
render_name = render_name
- && !gAgentCamera.cameraMouselook()
+ && !gAgentCamera.isHidingAvatarForFirstPerson()
&& (visible_chat || (render_name_show_self && name_tag_mode));
}
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 42cec5854c..7fa88cbb7f 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1087,7 +1087,11 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
switch (camera_mode)
{
case CAMERA_MODE_MOUSELOOK:
- if ((LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson()) || gPipeline.mHeroProbeManager.isMirrorPass())
+ // Flycam entered from mouselook stops hiding the avatar once
+ // it's out of view (see LLAgentCamera::mFlycamHidingAvatar).
+ if (!gAgentCamera.isHidingAvatarForFirstPerson()
+ || (LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson())
+ || gPipeline.mHeroProbeManager.isMirrorPass())
{
attachment->setAttachmentVisibility(true);
}
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 17dbe92813..a20f6b1da7 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -2606,6 +2606,12 @@ void LLVoiceWebRTCConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidat
void LLVoiceWebRTCConnection::processIceUpdates()
{
+ // Don't launch a coroutine on every tick; only do so when there's actually ice data to send and we're not shutting down.
+ if (LLWebRTCVoiceClient::isShuttingDown() || (mIceCandidates.empty() && !mIceCompleted))
+ {
+ return;
+ }
+
mOutstandingRequests++;
LLCoros::getInstance()->launch("LLVoiceWebRTCConnection::processIceUpdatesCoro",
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bccff55a2c..75adea11bd 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8117,7 +8117,7 @@ bool LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst)
if (focus_point.isExactlyZero())
{
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ if (gAgent.isCameraExternallyDriven())
{ // focus on point under cursor
focus_point.set(gDebugRaycastIntersection.getF32ptr());
}
diff --git a/indra/newview/skins/default/textures/bottomtray/Dpad.png b/indra/newview/skins/default/textures/bottomtray/Dpad.png
new file mode 100644
index 0000000000..00fcb4beea
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/Dpad.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/control_table_contents_flycam.xml b/indra/newview/skins/default/xui/en/control_table_contents_flycam.xml
new file mode 100644
index 0000000000..daf54d049f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/control_table_contents_flycam.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<contents>
+ <rows
+ name="flycam_move_forward"
+ value="flycam_move_forward">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Forward" />
+ </rows>
+ <rows
+ name="flycam_move_backward"
+ value="flycam_move_backward">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Backward" />
+ </rows>
+ <rows
+ name="flycam_truck_left"
+ value="flycam_truck_left">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Truck Left" />
+ </rows>
+ <rows
+ name="flycam_truck_right"
+ value="flycam_truck_right">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Truck Right" />
+ </rows>
+ <rows
+ name="flycam_move_up"
+ value="flycam_move_up">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Up" />
+ </rows>
+ <rows
+ name="flycam_move_down"
+ value="flycam_move_down">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Down" />
+ </rows>
+ <rows
+ name="flycam_yaw_left"
+ value="flycam_yaw_left">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Yaw Left" />
+ </rows>
+ <rows
+ name="flycam_yaw_right"
+ value="flycam_yaw_right">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Yaw Right" />
+ </rows>
+ <rows
+ name="flycam_pitch_up"
+ value="flycam_pitch_up">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Pitch Up" />
+ </rows>
+ <rows
+ name="flycam_pitch_down"
+ value="flycam_pitch_down">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Flycam Pitch Down" />
+ </rows>
+ <rows
+ name="flycam_unroll"
+ value="flycam_unroll">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ tool_tip="Reset flycam roll to level"
+ value="Flycam Unroll" />
+ </rows>
+ <rows
+ name="toggle_flycam"
+ value="toggle_flycam">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ tool_tip="Turn flycam on or off"
+ value="Toggle Flycam" />
+ </rows>
+</contents>
diff --git a/indra/newview/skins/default/xui/en/control_table_contents_game_control.xml b/indra/newview/skins/default/xui/en/control_table_contents_game_control.xml
new file mode 100644
index 0000000000..21b8f87633
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/control_table_contents_game_control.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<contents>
+ <rows
+ enabled="false"
+ name="game_control_buttons"
+ value="">
+ <columns
+ type="icontext"
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ label="Game Control Buttons"
+ name="lst_action"
+ value="Dpad" />
+ </rows>
+ <rows
+ name="game_control_button_0"
+ value="game_control_button_0">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_0" />
+ </rows>
+ <rows
+ name="game_control_button_1"
+ value="game_control_button_1">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_1" />
+ </rows>
+ <rows
+ name="game_control_button_2"
+ value="game_control_button_2">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_2" />
+ </rows>
+ <rows
+ name="game_control_button_3"
+ value="game_control_button_3">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_3" />
+ </rows>
+ <rows
+ name="game_control_button_4"
+ value="game_control_button_4">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_4" />
+ </rows>
+ <rows
+ name="game_control_button_5"
+ value="game_control_button_5">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_5" />
+ </rows>
+ <rows
+ name="game_control_button_6"
+ value="game_control_button_6">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_6" />
+ </rows>
+ <rows
+ name="game_control_button_7"
+ value="game_control_button_7">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_7" />
+ </rows>
+ <rows
+ name="game_control_button_8"
+ value="game_control_button_8">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_8" />
+ </rows>
+ <rows
+ name="game_control_button_9"
+ value="game_control_button_9">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_9" />
+ </rows>
+ <rows
+ name="game_control_button_10"
+ value="game_control_button_10">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_10" />
+ </rows>
+ <rows
+ name="game_control_button_11"
+ value="game_control_button_11">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_11" />
+ </rows>
+ <rows
+ name="game_control_button_12"
+ value="game_control_button_12">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_12" />
+ </rows>
+ <rows
+ name="game_control_button_13"
+ value="game_control_button_13">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_13" />
+ </rows>
+ <rows
+ name="game_control_button_14"
+ value="game_control_button_14">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_14" />
+ </rows>
+ <rows
+ name="game_control_button_15"
+ value="game_control_button_15">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_15" />
+ </rows>
+ <rows
+ name="game_control_button_16"
+ value="game_control_button_16">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_16" />
+ </rows>
+ <rows
+ name="game_control_button_17"
+ value="game_control_button_17">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_17" />
+ </rows>
+ <rows
+ name="game_control_button_18"
+ value="game_control_button_18">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_18" />
+ </rows>
+ <rows
+ name="game_control_button_19"
+ value="game_control_button_19">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_19" />
+ </rows>
+ <rows
+ name="game_control_button_20"
+ value="game_control_button_20">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_20" />
+ </rows>
+ <rows
+ name="game_control_button_21"
+ value="game_control_button_21">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_21" />
+ </rows>
+ <rows
+ name="game_control_button_22"
+ value="game_control_button_22">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_22" />
+ </rows>
+ <rows
+ name="game_control_button_23"
+ value="game_control_button_23">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_23" />
+ </rows>
+ <rows
+ name="game_control_button_24"
+ value="game_control_button_24">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_24" />
+ </rows>
+ <rows
+ name="game_control_button_25"
+ value="game_control_button_25">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_25" />
+ </rows>
+ <rows
+ name="game_control_button_26"
+ value="game_control_button_26">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_26" />
+ </rows>
+ <rows
+ name="game_control_button_27"
+ value="game_control_button_27">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_27" />
+ </rows>
+ <rows
+ name="game_control_button_28"
+ value="game_control_button_28">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_28" />
+ </rows>
+ <rows
+ name="game_control_button_29"
+ value="game_control_button_29">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_29" />
+ </rows>
+ <rows
+ name="game_control_button_30"
+ value="game_control_button_30">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_30" />
+ </rows>
+ <rows
+ name="game_control_button_31"
+ value="game_control_button_31">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="BUTTON_31" />
+ </rows>
+</contents>
diff --git a/indra/newview/skins/default/xui/en/control_table_contents_movement.xml b/indra/newview/skins/default/xui/en/control_table_contents_movement.xml
index c9a1c4654e..fe89308adb 100644
--- a/indra/newview/skins/default/xui/en/control_table_contents_movement.xml
+++ b/indra/newview/skins/default/xui/en/control_table_contents_movement.xml
@@ -83,7 +83,7 @@
font="SansSerif"
halign="left"
name="lst_action"
- value="Strafe left" />
+ value="Strafe Left" />
</rows>
<rows
name="slide_right"
@@ -93,7 +93,7 @@
font="SansSerif"
halign="left"
name="lst_action"
- value="Strafe right" />
+ value="Strafe Right" />
</rows>
<rows
name="jump"
@@ -176,6 +176,17 @@
value="Fly/Stop flying" />
</rows>
<rows
+ name="toggle_flycam"
+ value="toggle_flycam">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ tool_tip="Turn flycam on or off"
+ value="Toggle flycam" />
+ </rows>
+ <rows
name="toggle_sit"
value="toggle_sit">
<columns
diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml
index 8070ed55e6..327cbd6aba 100644
--- a/indra/newview/skins/default/xui/en/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/en/floater_font_test.xml
@@ -337,6 +337,44 @@
left="16">
Helvetica size=Large style=BOLD|ITALIC
</text>
+ <!-- SecondLife-game-control font smoke test: gamepad glyphs (icon-only preview). Codepoints from promptfont.h. -->
+ <text
+ type="string"
+ length="1"
+ bottom_delta="40"
+ follows="left|top|right"
+ font="SecondLife-game-control"
+ font.size="Huge"
+ height="32"
+ layout="topleft"
+ left="16">
+ SecondLife-game-control faces/dpad: &#x21A4;&#x21A5;&#x21A6;&#x21A7; &#x219E;&#x219F;&#x21A0;&#x21A1;
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom_delta="36"
+ follows="left|top|right"
+ font="SecondLife-game-control"
+ font.size="Huge"
+ height="32"
+ layout="topleft"
+ left="16">
+ SecondLife-game-control sticks/triggers: &#x21C4;&#x21C5;&#x21C6;&#x21F5; &#x2196;&#x2197;&#x2198;&#x2199;
+ </text>
+ <!-- Same-cell text+icon preview: label text renders in SecondLife-game-control's own Latin letters. -->
+ <text
+ type="string"
+ length="1"
+ bottom_delta="36"
+ follows="left|top|right"
+ font="SecondLife-game-control"
+ font.size="Large"
+ height="24"
+ layout="topleft"
+ left="16">
+ Left stick &#x21C4; Jump &#x21A7; D-pad &#x21A1;
+ </text>
<!--
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml
index e6f0420698..3cba75c08c 100644
--- a/indra/newview/skins/default/xui/en/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/en/floater_joystick.xml
@@ -3,9 +3,9 @@
legacy_header_height="18"
height="500"
layout="topleft"
- name="Joystick"
+ name="3Dconnexion Device"
help_topic="Viewerhelp:Joystick_Configuration"
- title="JOYSTICK CONFIGURATION"
+ title="3DCONNEXION DEVICE CONFIGURATION"
width="569">
<floater.string
name="JoystickDisabled">
@@ -22,7 +22,7 @@
width="50"
mouse_opaque="false"
name="joystick_lbl">
- Joystick:
+ Device:
</text>
<combo_box
allow_text_entry="false"
@@ -48,7 +48,7 @@
width="140" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="JoystickAxis2"
decimal_digits="0"
increment="1"
@@ -62,7 +62,7 @@
width="140" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="JoystickAxis0"
decimal_digits="0"
increment="1"
@@ -76,7 +76,7 @@
width="140" />
<spinner
bottom="76"
- height="10"
+ height="10"
control_name="JoystickAxis4"
decimal_digits="0"
increment="1"
@@ -90,7 +90,7 @@
width="140" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="JoystickAxis5"
decimal_digits="0"
increment="1"
@@ -104,7 +104,7 @@
width="140" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="JoystickAxis3"
decimal_digits="0"
increment="1"
@@ -118,7 +118,7 @@
width="140" />
<spinner
bottom="96"
- height="10"
+ height="10"
control_name="JoystickAxis6"
decimal_digits="0"
increment="1"
@@ -141,7 +141,7 @@
width="60" />
<check_box
bottom_delta="0"
- height="10"
+ height="10"
control_name="Cursor3D"
label="3D Cursor"
layout="topleft"
@@ -150,7 +150,7 @@
width="60" />
<check_box
bottom_delta="0"
- height="10"
+ height="10"
control_name="AutoLeveling"
label="Auto Level"
layout="topleft"
@@ -173,7 +173,7 @@
</text>
<check_box
bottom="134"
- height="10"
+ height="10"
control_name="JoystickAvatarEnabled"
halign="center"
label="Avatar"
@@ -183,7 +183,7 @@
width="60" />
<check_box
bottom_delta="0"
- height="10"
+ height="10"
control_name="JoystickBuildEnabled"
halign="center"
label="Build"
@@ -193,17 +193,18 @@
width="60" />
<check_box
bottom_delta="0"
- height="10"
+ height="10"
control_name="JoystickFlycamEnabled"
halign="center"
label="Flycam"
layout="topleft"
left="289"
name="JoystickFlycamEnabled"
+ tool_tip="Lets this device fly the camera."
width="60" />
<stat_view
height="270"
- label="Joystick Monitor"
+ label="Axis Monitor"
layout="topleft"
left="359"
name="axis_view"
@@ -213,7 +214,7 @@
<stat_bar
bar_max="2"
bar_min="-2"
- show_bar="true"
+ show_bar="true"
label="Axis 0"
label_spacing="1"
layout="topleft"
@@ -225,7 +226,7 @@
<stat_bar
bar_max="2"
bar_min="-2"
- show_bar="true"
+ show_bar="true"
label="Axis 1"
label_spacing="1"
layout="topleft"
@@ -234,7 +235,7 @@
<stat_bar
bar_max="2"
bar_min="-2"
- show_bar="true"
+ show_bar="true"
label="Axis 2"
label_spacing="1"
layout="topleft"
@@ -243,7 +244,7 @@
<stat_bar
bar_max="2"
bar_min="-2"
- show_bar="true"
+ show_bar="true"
label="Axis 3"
label_spacing="1"
layout="topleft"
@@ -252,7 +253,7 @@
<stat_bar
bar_max="2"
bar_min="-2"
- show_bar="true"
+ show_bar="true"
label="Axis 4"
label_spacing="1"
layout="topleft"
@@ -262,7 +263,7 @@
bar_max="2"
bar_min="-2"
label="Axis 5"
- show_bar="true"
+ show_bar="true"
label_spacing="1"
layout="topleft"
name="axis5"
@@ -281,7 +282,7 @@
</text>
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="AvatarAxisScale1"
decimal_digits="2"
label_width="0"
@@ -293,7 +294,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="BuildAxisScale1"
decimal_digits="2"
label_width="0"
@@ -305,7 +306,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="FlycamAxisScale1"
decimal_digits="2"
label_width="0"
@@ -328,7 +329,7 @@
</text>
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="AvatarAxisScale2"
decimal_digits="2"
label_width="0"
@@ -340,7 +341,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="BuildAxisScale2"
decimal_digits="2"
label_width="0"
@@ -352,7 +353,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="FlycamAxisScale2"
decimal_digits="2"
label_width="0"
@@ -375,7 +376,7 @@
</text>
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="AvatarAxisScale0"
decimal_digits="2"
label_width="0"
@@ -387,7 +388,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="BuildAxisScale0"
decimal_digits="2"
label_width="0"
@@ -399,7 +400,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="FlycamAxisScale0"
decimal_digits="2"
label_width="0"
@@ -422,7 +423,7 @@
</text>
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="AvatarAxisScale4"
decimal_digits="2"
label_width="0"
@@ -434,7 +435,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="BuildAxisScale4"
decimal_digits="2"
label_width="0"
@@ -446,7 +447,7 @@
width="56" />
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="FlycamAxisScale4"
decimal_digits="2"
label_width="0"
@@ -595,7 +596,7 @@
</text>
<spinner
bottom_delta="0"
- height="10"
+ height="10"
control_name="AvatarAxisDeadZone2"
decimal_digits="2"
increment="0.01"
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 5345d5a529..28065c184a 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -87,14 +87,14 @@
top="40"
width="658">
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_general.xml"
label="General"
layout="topleft"
help_topic="preferences_general_tab"
name="general" />
<panel
- class="panel_preference_graphics"
+ class="panel_preference_graphics"
filename="panel_preferences_graphics1.xml"
label="Graphics"
layout="topleft"
@@ -110,7 +110,7 @@
name="display3" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_sound.xml"
label="Sound &amp; Media"
layout="topleft"
@@ -123,28 +123,28 @@
layout="topleft"
name="voice" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_chat.xml"
label="Chat"
layout="topleft"
help_topic="preferences_chat_tab"
name="chat" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_move.xml"
label="Move &amp; View"
layout="topleft"
help_topic="preferences_move_tab"
name="move" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_alerts.xml"
label="Notifications"
layout="topleft"
help_topic="preferences_msgs_tab"
name="msgs" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_colors.xml"
label="Colors"
layout="topleft"
@@ -158,14 +158,14 @@
help_topic="preferences_im_tab"
name="im" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_setup.xml"
label="Setup"
layout="topleft"
help_topic="preferences_input_tab"
name="input" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_advanced.xml"
label="Advanced"
layout="topleft"
@@ -185,6 +185,13 @@
layout="topleft"
help_topic="preferences_controls_tab"
name="controls" />
+ <panel
+ class="panel_preference_game_control"
+ filename="panel_preferences_game_control.xml"
+ label="Game Controls"
+ layout="topleft"
+ help_topic="preferences_game_control_tab"
+ name="game_control" />
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index 1ad01ee120..b081e69c7a 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -19,7 +19,7 @@
<file>micross.ttf</file>
</os>
<os name="Mac">
- <file>ヒラギノ角ゴシック W3.ttc</file>
+ <file>ヒラギノ角ゴシック W3.ttc</file>
<file>ヒラギノ角ゴ Pro W3.otf</file>
<file>ヒラギノ角ゴ ProN W3.otf</file>
<file>ヒラギノ明朝 ProN W3.ttc</file>
@@ -88,7 +88,12 @@
comment="Name of emoji font">
<file>TwemojiSVG.ttf</file>
</font>
-
+
+ <font name="SecondLife-game-control"
+ comment="Game-controller button/axis glyphs (based on Promptfont by Shinmera, OFL). Used only on specific game-control UI cells; NOT a global fallback (its glyphs occupy real Unicode arrow codepoints).">
+ <file>SecondLife-game-control.ttf</file>
+ </font>
+
<font
name="Monospace"
comment="Name of monospace font">
diff --git a/indra/newview/skins/default/xui/en/game_control_table_camera_rows.xml b/indra/newview/skins/default/xui/en/game_control_table_camera_rows.xml
new file mode 100644
index 0000000000..def3318dce
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/game_control_table_camera_rows.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<contents>
+ <rows
+ enabled="false"
+ name="camera_actions"
+ value="">
+ <columns
+ type="icontext"
+ column="action"
+ font="SansSerif"
+ halign="left"
+ label="Camera movement"
+ name="action"
+ value="Cam_FreeCam_Off" />
+ </rows>
+ <rows
+ name="advance"
+ value="advance">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera move forward/backward"
+ value="Forward/Backward" />
+ </rows>
+ <rows
+ name="pan"
+ value="pan">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera pan left/right"
+ value="Pan Left/Right" />
+ </rows>
+ <rows
+ name="rise"
+ value="rise">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera rise/fall"
+ value="Rise Up/Down" />
+ </rows>
+ <rows
+ name="pitch"
+ value="pitch">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera adjust pitch"
+ value="Pitch Up/Down" />
+ </rows>
+ <rows
+ name="yaw"
+ value="yaw">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera turn left/right"
+ value="Yaw CCW/CW" />
+ </rows>
+ <rows
+ name="zoom"
+ value="zoom">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera zoom in/out"
+ value="Zoom In/Out" />
+ </rows>
+ <!--
+ <rows
+ name="roll_ccw"
+ value="roll_ccw">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera roll counterclockwise"
+ value="Roll Counterclockwise" />
+ </rows>
+ <rows
+ name="roll_cw"
+ value="roll_cw">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ tool_tip="Camera roll clockwise"
+ value="Roll Clockwise" />
+ </rows>
+ -->
+</contents>
diff --git a/indra/newview/skins/default/xui/en/game_control_table_rows.xml b/indra/newview/skins/default/xui/en/game_control_table_rows.xml
new file mode 100644
index 0000000000..8d3f2b14a5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/game_control_table_rows.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<contents>
+ <rows
+ enabled="false"
+ name="avatar_actions"
+ value="">
+ <columns
+ type="icontext"
+ column="action"
+ font="SansSerif"
+ halign="left"
+ label="Avatar movement"
+ name="action"
+ value="Move_Walk_Off" />
+ </rows>
+ <rows
+ name="push"
+ value="push">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Forward/Backward" />
+ </rows>
+ <rows
+ name="slide"
+ value="slide">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Strafe" />
+ </rows>
+ <rows
+ name="jump"
+ value="jump">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Jump/Up" />
+ </rows>
+ <rows
+ name="crouch"
+ value="crouch">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Crouch/Down" />
+ </rows>
+ <rows
+ name="turn"
+ value="turn">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Turn" />
+ </rows>
+ <rows
+ name="look"
+ value="look">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Look Up/Down" />
+ </rows>
+ <rows
+ name="stop"
+ value="stop">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Stop" />
+ </rows>
+ <rows
+ name="toggle_run"
+ value="toggle_run">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Run" />
+ </rows>
+ <rows
+ name="toggle_fly"
+ value="toggle_fly">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Fly" />
+ </rows>
+ <rows
+ name="toggle_flycam"
+ value="toggle_flycam">
+ <columns
+ column="action"
+ font="SansSerif"
+ halign="left"
+ name="action"
+ value="Flycam" />
+ </rows>
+</contents>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index ad75840d52..644d59fdda 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -19,7 +19,7 @@
label="Inventory..."
name="Inventory"
shortcut="control|I"
- visible="true">
+ visible="true">
<menu_item_check.on_check
function="Floater.Visible"
parameter="inventory" />
@@ -458,7 +458,7 @@
function="Agent.toggleFlying" />
<menu_item_call.on_enable
function="Agent.enableFlyLand" />
- </menu_item_call>
+ </menu_item_call>
<menu_item_call
label="Stop animations"
name="Stop Animating My Avatar"
@@ -507,14 +507,14 @@
parameter="gestures" />
</menu_item_check>
<menu_item_separator/>
- <menu_item_call
+ <menu_item_call
label="Reset skeleton"
layout="topleft"
name="Reset Skeleton">
<menu_item_call.on_click
function="Avatar.ResetSelfSkeleton" />
</menu_item_call>
- <menu_item_call
+ <menu_item_call
label="Reset skeleton and animations"
layout="topleft"
name="Reset Skeleton And Animations">
@@ -766,8 +766,7 @@
function="Floater.Show"
parameter="snapshot" />
</menu_item_call>
-
-<menu_item_call
+ <menu_item_call
label="360 snapshot"
name="Capture 360">
<menu_item_call.on_click
@@ -989,7 +988,7 @@
function="World.EnvSettings"
parameter="sunrise" />
<menu_item_check.on_check
- function="World.EnableEnvSettings"
+ function="World.EnableEnvSettings"
parameter="sunrise" />
</menu_item_check>
<menu_item_check
@@ -1022,7 +1021,7 @@
function="World.EnvSettings"
parameter="sunset" />
<menu_item_check.on_check
- function="World.EnableEnvSettings"
+ function="World.EnableEnvSettings"
parameter="sunset" />
</menu_item_check>
<menu_item_check
@@ -1033,7 +1032,7 @@
function="World.EnvSettings"
parameter="midnight" />
<menu_item_check.on_check
- function="World.EnableEnvSettings"
+ function="World.EnableEnvSettings"
parameter="midnight" />
</menu_item_check>
<menu_item_check
@@ -1044,7 +1043,7 @@
function="World.EnvSettings"
parameter="region" />
<menu_item_check.on_check
- function="World.EnableEnvSettings"
+ function="World.EnableEnvSettings"
parameter="region" />
</menu_item_check>
<menu_item_separator/>
@@ -1066,7 +1065,7 @@
function="World.EnvSettings"
parameter="my_environs" />
</menu_item_call>
-
+
<menu_item_call
label="Personal Lighting..."
name="adjustment_tool">
@@ -1082,7 +1081,7 @@
function="World.EnvSettings"
parameter="pause_clouds" />
<menu_item_check.on_check
- function="World.EnableEnvSettings"
+ function="World.EnableEnvSettings"
parameter="pause_clouds" />
</menu_item_check>
</menu>
@@ -1095,7 +1094,7 @@
<menu_item_check.on_check
function="World.IsMasterAudioMuted"/>
</menu_item_check>
-<!--
+<!--
<menu
create_jump_keys="true"
label="Environment Editor"
@@ -1164,8 +1163,8 @@ function="World.EnvPreset"
</menu_item_call>
</menu>
</menu>
--->
-
+-->
+
</menu>
<menu
create_jump_keys="true"
@@ -1313,7 +1312,7 @@ function="World.EnvPreset"
parameter="pathfinding_linksets" />
<menu_item_call.on_enable
function="Tools.EnablePathfinding" />
- </menu_item_call>
+ </menu_item_call>
<menu_item_separator/>
<menu_item_call
@@ -1336,7 +1335,7 @@ function="World.EnvPreset"
<menu_item_call.on_enable
function="Tools.SomethingSelectedNoHUD" />
</menu_item_call>
-
+
<menu_item_separator/>
<menu
@@ -1664,7 +1663,7 @@ function="World.EnvPreset"
function="View.CheckHighlightTransparent"/>
</menu_item_check>
<menu_item_separator/>
-
+
<menu_item_check
label="No Post-processing"
name="No Post">
@@ -1674,7 +1673,7 @@ function="World.EnvPreset"
function="ToggleControl"
parameter="RenderDisablePostProcessing" />
</menu_item_check>
-
+
<menu
create_jump_keys="true"
@@ -1890,7 +1889,7 @@ function="World.EnvPreset"
userdata="" />
<on_enable
function="Edit.EnableRedo" />
- </menu_item_call>
+ </menu_item_call>
</menu>
<menu
create_jump_keys="true"
@@ -1924,13 +1923,13 @@ function="World.EnvPreset"
<menu_item_call.on_click
function="Advanced.ShowURL"
parameter="http://community.secondlife.com/t5/Forums/ct-p/Forums"/>
- </menu_item_call>
+ </menu_item_call>
<menu_item_call
label="Support portal"
name="Support portal">
<menu_item_call.on_click
function="Advanced.ShowURL"
- parameter="https://support.secondlife.com/"/>
+ parameter="https://support.secondlife.com/"/>
</menu_item_call>
<menu_item_separator/>
<menu_item_call
@@ -1963,7 +1962,7 @@ function="World.EnvPreset"
function="Floater.Show"
parameter="bumps" />
</menu_item_call>
- <menu_item_separator/>
+ <menu_item_separator/>
<menu_item_call
label="About [APP_NAME]"
name="About Second Life">
@@ -2545,7 +2544,7 @@ function="World.EnvPreset"
function="Advanced.ToggleFeature"
parameter="flexible" />
</menu_item_check>
- </menu>
+ </menu>
<menu
label="RLVa"
name="RLVa Embedded"
@@ -2712,7 +2711,7 @@ function="World.EnvPreset"
<menu_item_check.on_click
function="Advanced.ToggleConsole"
parameter="texture" />
- </menu_item_check>
+ </menu_item_check>
<menu_item_check
label="Debug Console"
name="Debug Console"
@@ -2930,6 +2929,16 @@ function="World.EnvPreset"
function="ToggleControl"
parameter="DebugShowMemory" />
</menu_item_check>
+ <menu_item_check
+ label="Show Game Controller State"
+ name="Show Game Controller State">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowControllerState" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowControllerState" />
+ </menu_item_check>
<menu_item_separator/>
@@ -3703,7 +3712,7 @@ function="World.EnvPreset"
<menu_item_call.on_click
function="Develop.ClearCache" />
</menu_item_call>
-
+
</menu>
<menu
@@ -3787,7 +3796,7 @@ function="World.EnvPreset"
name="Dump Scripted Camera">
<menu_item_call.on_click
function="Advanced.DumpScriptedCamera" />
- </menu_item_call>
+ </menu_item_call>
<menu
create_jump_keys="true"
label="Recorder"
@@ -4479,13 +4488,6 @@ function="World.EnvPreset"
function="Advanced.CompressFileTest" />
</menu_item_call>
- <menu_item_call
- label="Enable Visual Leak Detector"
- name="Enable Visual Leak Detector">
- <menu_item_call.on_click
- function="Advanced.ToggleVisualLeakDetector" />
- </menu_item_call>
-
<menu_item_check
label="Output Debug Minidump"
name="Output Debug Minidump">
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
index f8801f9c89..5cd3bed5bc 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml
@@ -6,7 +6,7 @@
label="Controls"
layout="topleft"
left="102"
- name="controls"
+ name="controls_panel"
top="1"
width="517">
<combo_box
@@ -33,6 +33,10 @@
label="When sitting"
name="sitting"
value="3"/>
+ <combo_box.item
+ label="When using flycam"
+ name="flycam"
+ value="4"/>
</combo_box>
<button
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_game_control.xml b/indra/newview/skins/default/xui/en/panel_preferences_game_control.xml
new file mode 100644
index 0000000000..185d621e51
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_game_control.xml
@@ -0,0 +1,1205 @@
+<?xml version="1.0" encoding="utf-8"?>
+<panel
+ border="true"
+ follows="all"
+ height="408"
+ label="Game Controls"
+ layout="topleft"
+ left="102"
+ name="game_control_panel"
+ top="1"
+ width="517">
+ <tab_container
+ name="game_control_tabs"
+ layout="topleft"
+ follows="all"
+ top="2"
+ left="2"
+ right="-2"
+ bottom="-2">
+ <!-- ACTIONS: global, per-mode. Binds canonical inputs to logical actions. -->
+ <panel
+ name="tab_action_mappings"
+ label="Action Mappings">
+ <!-- Mode selector: picks which mode's mappings are edited below; only
+ one mode is shown at a time. The "Enabled" checkbox toggles
+ whether game-control input is converted to that mode's actions
+ (when off, the mode's mappings are locked), and tracks whichever
+ mode is currently selected in the combo box. -->
+ <combo_box
+ name="action_mode"
+ layout="topleft"
+ follows="top|left"
+ top="6"
+ left="1"
+ height="23"
+ width="210"
+ tool_tip="Select a mode to edit its mappings.">
+ <combo_box.item
+ label="When moving avatar"
+ name="avatar"
+ value="0"/>
+ <combo_box.item
+ label="When in mouselook"
+ name="mouselook"
+ value="1"/>
+ <combo_box.item
+ label="When moving flycam"
+ name="flycam"
+ value="2"/>
+ <combo_box.item
+ label="When sitting"
+ name="captive"
+ value="3"/>
+ <combo_box.item
+ label="When using mouse cursor"
+ name="cursor"
+ value="4"/>
+ </combo_box>
+ <check_box
+ name="action_mode_enabled"
+ label="Mode enabled"
+ layout="topleft"
+ follows="top|left"
+ top="10"
+ left="217"
+ height="16"
+ width="70"
+ tool_tip="Uncheck to lock this mode's mappings and stop converting game-control input to this mode's actions."/>
+ <check_box
+ name="flycam_allow_roll"
+ label="Allow roll"
+ layout="topleft"
+ follows="top|left"
+ top="30"
+ left="217"
+ height="16"
+ width="120"
+ tool_tip="Allow Roll input to rotate the flycam about its forward axis. Only shown while editing FlyCam mappings."/>
+ <text
+ type="string"
+ name="speed_slow_label"
+ layout="topleft"
+ follows="top|left"
+ halign="right"
+ top="30"
+ left_pad="8"
+ height="16"
+ width="32">Slow</text>
+ <slider
+ name="speed_factor"
+ layout="topleft"
+ follows="top|left"
+ top_delta="-1"
+ left_pad="4"
+ height="16"
+ width="90"
+ min_val="0.5"
+ max_val="2.0"
+ initial_value="1.0"
+ increment="0.05"
+ decimal_digits="2"
+ show_text="false"
+ tool_tip="FlyCam: camera move speed. Mouselook: turn/look speed. Avatar: turn speed. Only shown while editing FlyCam, Mouselook, or Avatar mappings."/>
+ <text
+ type="string"
+ name="speed_fast_label"
+ layout="topleft"
+ follows="top|left"
+ top_delta="1"
+ left_pad="4"
+ height="16"
+ width="32">Fast</text>
+ <check_box
+ name="flycam_hide_cursor"
+ label="Hide mouse cursor"
+ layout="topleft"
+ follows="top|left"
+ top="48"
+ left="217"
+ height="16"
+ width="130"
+ initial_value="true"
+ tool_tip="Hide the mouse cursor while flying the flycam. It reappears when the mouse is moved and hides again 5 seconds later, or within 1 second once the flycam moves. Only shown while editing FlyCam mappings."/>
+ <check_box
+ name="flycam_crosshair"
+ label="Show crosshair"
+ layout="topleft"
+ follows="top|left"
+ top="48"
+ left_pad="8"
+ height="16"
+ width="150"
+ tool_tip="Draw a crosshair at the center of the screen while flying the flycam. Only shown while editing FlyCam mappings."/>
+ <button
+ name="restore_actions_defaults"
+ layout="topleft"
+ follows="top|right"
+ top="6"
+ right="-8"
+ height="23"
+ width="140"
+ label="Restore Defaults"
+ tool_tip="Restores the default action mappings for the current mode."/>
+ <text
+ type="string"
+ name="current_mode_indicator"
+ layout="topleft"
+ follows="top|left|right"
+ top="68"
+ left="6"
+ right="-1"
+ height="16">Active mode: </text>
+ <panel
+ name="action_mappings_panel"
+ layout="topleft"
+ follows="all"
+ top="88"
+ left="1"
+ right="-1"
+ bottom="-1">
+ <panel
+ name="action_mappings_axes_panel"
+ layout="topleft"
+ follows="top|left|right"
+ top="1"
+ left="1"
+ right="-1"
+ height="146">
+ <scroll_list
+ name="action_mappings_axes"
+ follows="all"
+ top="1"
+ left="1"
+ right="-1"
+ bottom="-1"
+ can_sort="false"
+ column_padding="0"
+ draw_heading="true"
+ multi_select="false"
+ selection_type="header"
+ fg_disable_color="ScrollUnselectedColor">
+ <scroll_list.columns name="action" label="Action" relative_width="0.35"/>
+ <scroll_list.columns name="input" label="Input" relative_width="0.15"/>
+ <scroll_list.columns name="input_description" label="Axis" relative_width="0.35"/>
+ <scroll_list.columns name="invert" label="Invert" type="checkbox" relative_width="0.15"/>
+ </scroll_list>
+ </panel>
+ <panel
+ name="action_mappings_buttons_panel"
+ layout="topleft"
+ follows="all"
+ top="143"
+ left="1"
+ right="-1"
+ bottom="-1">
+ <scroll_list
+ name="action_mappings_buttons"
+ follows="all"
+ top="1"
+ left="1"
+ right="-1"
+ bottom="-1"
+ can_sort="false"
+ column_padding="0"
+ draw_heading="true"
+ multi_select="false"
+ selection_type="header"
+ fg_disable_color="ScrollUnselectedColor">
+ <scroll_list.columns name="action" label="Action" relative_width="0.40"/>
+ <scroll_list.columns name="input" label="Input" relative_width="0.20"/>
+ <scroll_list.columns name="input_description" label="Button" relative_width="0.40"/>
+ </scroll_list>
+ </panel>
+ </panel>
+ </panel>
+ <!-- DEVICES: per-device. Normalizes physical hardware to canonical inputs. -->
+ <panel
+ name="tab_device_mappings"
+ label="Device Mappings">
+ <text
+ type="string"
+ name="nodevice_message"
+ layout="topleft"
+ follows="all"
+ halign="center"
+ valign="center"
+ top="26"
+ left="1"
+ right="-1"
+ bottom="-1">No device</text>
+ <check_box
+ name="show_all_known_devices"
+ label="Show all known devices"
+ layout="topleft"
+ follows="top|left"
+ top="38"
+ left="61"
+ height="16"
+ width="160"/>
+ <text
+ type="string"
+ name="device_prompt"
+ layout="topleft"
+ follows="top|left"
+ valign="center"
+ top="10"
+ left="9"
+ height="23"
+ width="48">Device:</text>
+ <combo_box
+ name="device_list"
+ layout="topleft"
+ follows="top|left"
+ top="10"
+ left="61"
+ height="23"
+ width="260"/>
+ <button
+ name="restore_device_defaults"
+ layout="topleft"
+ follows="top|right"
+ top="10"
+ right="-8"
+ height="23"
+ width="140"
+ label="Restore Defaults"
+ tool_tip="Restores default settings for the selected device."/>
+ <panel
+ name="device_settings"
+ layout="topleft"
+ follows="all"
+ top="66"
+ left="1"
+ right="-1"
+ bottom="-2">
+ <panel
+ name="axis_channels_panel"
+ layout="topleft"
+ follows="top|left|right"
+ top="1"
+ left="1"
+ right="-1"
+ height="146">
+ <scroll_list
+ name="axis_channels"
+ follows="all"
+ top="1"
+ left="1"
+ right="-1"
+ bottom="-1"
+ can_sort="false"
+ column_padding="0"
+ draw_heading="true"
+ multi_select="false"
+ selection_type="header"
+ fg_disable_color="ScrollUnselectedColor">
+ <scroll_list.columns name="input" label="" relative_width="0.15"/>
+ <scroll_list.columns name="input_description" label="What you press" relative_width="0.35"/>
+ <scroll_list.columns name="output_description" label="What you get" relative_width="0.35"/>
+ <scroll_list.columns name="output" label="" relative_width="0.15"/>
+ </scroll_list>
+ </panel>
+ <panel
+ name="button_channels_panel"
+ layout="topleft"
+ follows="all"
+ top="143"
+ left="1"
+ right="-1"
+ bottom="-1">
+ <scroll_list
+ name="button_channels"
+ follows="all"
+ top="1"
+ left="1"
+ right="-1"
+ bottom="-1"
+ can_sort="false"
+ column_padding="0"
+ draw_heading="true"
+ multi_select="false"
+ selection_type="header"
+ fg_disable_color="ScrollUnselectedColor">
+ <scroll_list.columns name="input" label="" relative_width="0.15"/>
+ <scroll_list.columns name="input_description" label="What you press" relative_width="0.35"/>
+ <scroll_list.columns name="output_description" label="What you get" relative_width="0.35"/>
+ <scroll_list.columns name="output" label="" relative_width="0.15"/>
+ </scroll_list>
+ </panel>
+ </panel>
+ </panel>
+ <!-- DEVICE STATE: live, read-only view of the raw input from the selected device. -->
+ <panel
+ name="tab_device_options"
+ label="Device Options">
+ <text
+ type="string"
+ name="state_nodevice_message"
+ layout="topleft"
+ follows="all"
+ halign="center"
+ valign="center"
+ top="26"
+ left="1"
+ right="-1"
+ bottom="-1">No device</text>
+ <text
+ type="string"
+ name="state_device_prompt"
+ layout="topleft"
+ follows="top|left"
+ valign="center"
+ top="10"
+ left="9"
+ height="23"
+ width="48">Device:</text>
+ <combo_box
+ name="options_device_list"
+ layout="topleft"
+ follows="top|left"
+ top="10"
+ left="61"
+ height="23"
+ width="260"/>
+ <button
+ name="restore_device_options_defaults"
+ layout="topleft"
+ follows="top|right"
+ top="10"
+ right="-8"
+ height="23"
+ width="140"
+ label="Restore Defaults"
+ tool_tip="Restores the default Offset, Invert, and Dead Zone for every axis of the selected device."/>
+ <button
+ name="auto_calibrate"
+ layout="topleft"
+ follows="top|right"
+ top="35"
+ right="-8"
+ height="23"
+ width="140"
+ label="Auto calibrate"
+ tool_tip="Samples the selected device's raw axes over 5 frames; any axis that doesn't move is assumed to be at rest, and its Offset and Dead Zone are set from that reading."/>
+ <panel
+ name="device_state_settings"
+ layout="topleft"
+ follows="all"
+ top="63"
+ left="1"
+ right="-1"
+ bottom="-2">
+ <panel
+ name="axis_state_panel"
+ layout="topleft"
+ follows="top|left|right"
+ top="1"
+ left="1"
+ right="-1"
+ height="146">
+ <scroll_list
+ name="axis_state"
+ follows="all"
+ top="1"
+ left="1"
+ right="-1"
+ bottom="-1"
+ can_sort="false"
+ column_padding="0"
+ draw_heading="true"
+ multi_select="false"
+ selection_type="header"
+ fg_disable_color="ScrollUnselectedColor">
+ <scroll_list.columns name="input_glyph" label="Input" relative_width="0.12"/>
+ <scroll_list.columns name="input" label="Axis" relative_width="0.18"/>
+ <scroll_list.columns name="raw_value" label="Raw Value" relative_width="0.14"/>
+ <scroll_list.columns name="offset" label="Offset" relative_width="0.10"/>
+ <scroll_list.columns name="invert" label="Invert" type="checkbox" relative_width="0.10"/>
+ <scroll_list.columns name="dead_zone" label="Dead Zone" relative_width="0.15"/>
+ <scroll_list.columns name="fixed_value" label="Adjusted Value" relative_width="0.21"/>
+ </scroll_list>
+ </panel>
+ <panel
+ name="button_state_panel"
+ layout="topleft"
+ follows="all"
+ top="143"
+ left="1"
+ right="-1"
+ bottom="-1">
+ <scroll_list
+ name="button_state"
+ follows="all"
+ top="1"
+ left="1"
+ right="-1"
+ bottom="-1"
+ can_sort="false"
+ column_padding="0"
+ draw_heading="true"
+ multi_select="false"
+ selection_type="header"
+ fg_disable_color="ScrollUnselectedColor">
+ <scroll_list.columns name="input_glyph" label="Input" relative_width="0.15"/>
+ <scroll_list.columns name="input" label="Button" relative_width="0.45"/>
+ <scroll_list.columns name="value" label="Value" relative_width="0.40"/>
+ </scroll_list>
+ </panel>
+ </panel>
+ </panel>
+ <!-- DATA OUTPUT: live, read-only view of the channel values packed into the
+ most recent outgoing GameControlInput message. -->
+ <panel
+ name="tab_server_data"
+ label="Server Data">
+ <check_box
+ name="game_control_to_server"
+ label="Send GameControl Data to server"
+ layout="topleft"
+ follows="top|left"
+ height="16"
+ width="230"
+ top="8"
+ left="9"/>
+ <text
+ type="string"
+ name="data_note"
+ layout="topleft"
+ follows="top|left|right"
+ word_wrap="true"
+ top="30"
+ left="9"
+ right="-9"
+ height="42">Data sent to the server: canonical axes/buttons, then the semantic axes/buttons for the current mode.</text>
+ <panel
+ name="data_panel"
+ layout="topleft"
+ follows="all"
+ top="70"
+ left="1"
+ right="-1"
+ bottom="-1">
+ <scroll_list
+ name="data_output"
+ follows="all"
+ top="1"
+ left="1"
+ right="-1"
+ bottom="-1"
+ can_sort="false"
+ column_padding="0"
+ draw_heading="true"
+ multi_select="false"
+ selection_type="header"
+ fg_disable_color="ScrollUnselectedColor">
+ <scroll_list.columns name="index" label="#" relative_width="0.1"/>
+ <scroll_list.columns name="output" label="Name" relative_width="0.5"/>
+ <scroll_list.columns name="value" label="Value" relative_width="0.4"/>
+ </scroll_list>
+ </panel>
+ </panel>
+ </tab_container>
+ <spinner
+ name="numeric_value_editor"
+ decimal_digits="0"
+ increment="1"
+ width="100"
+ height="18"/>
+ <!-- axis_input_selector: the canonical axis INPUTS an axis action can be bound
+ to on the Actions tab. The two triggers are offered only as the combined
+ "Triggers ↔" pair (value AXIS_TRIGGERS): each trigger is positive-
+ only, so the pair is treated as one bidirectional axis (left trigger drives
+ the negative direction, right trigger the positive). See the trigger-pair
+ handling in llgamecontrol.cpp (rebuildActionLookup / avatarAxisBridge). -->
+ <combo_box
+ name="axis_input_selector"
+ width="200"
+ height="18">
+ <combo_box.item
+ label="L Stick ↔"
+ name="axis_leftx"
+ value="AXIS_LEFTX"/>
+ <combo_box.item
+ label="L Stick ↕"
+ name="axis_lefty"
+ value="AXIS_LEFTY"/>
+ <combo_box.item
+ label="R Stick ↔"
+ name="axis_rightx"
+ value="AXIS_RIGHTX"/>
+ <combo_box.item
+ label="R Stick ↕"
+ name="axis_righty"
+ value="AXIS_RIGHTY"/>
+ <combo_box.item
+ label="Triggers ↘↙"
+ name="axis_triggers"
+ value="AXIS_TRIGGERS"/>
+ <combo_box.item
+ label="None"
+ name="axis_none"
+ value="AXIS_NONE"/>
+ </combo_box>
+ <!-- axis_input_glyph_selector: the glyph counterpart of axis_input_selector,
+ shown when editing the "Axis" (icon) column. Items are built
+ in C++ from axis_input_selector's values so the value list stays in one
+ place; each item's label is the font glyph for that axis. -->
+ <combo_box
+ name="axis_input_glyph_selector"
+ width="200"
+ height="18"/>
+ <!-- axis_output_selector: the canonical axis a physical device axis maps to on
+ the Devices tab. This is strictly index-based (item N == canonical axis N,
+ matching LLGameControl::KeyboardAxis; the final "None" item == NUM_AXES), so
+ it lists every individual canonical axis, including each trigger separately. -->
+ <combo_box
+ name="axis_output_selector"
+ width="200"
+ height="18">
+ <combo_box.item
+ label="L Stick ↔"
+ name="axis_0"
+ value="AXIS_LEFTX"/>
+ <combo_box.item
+ label="L Stick ↕"
+ name="axis_1"
+ value="AXIS_LEFTY"/>
+ <combo_box.item
+ label="R Stick ↔"
+ name="axis_2"
+ value="AXIS_RIGHTX"/>
+ <combo_box.item
+ label="R Stick ↕"
+ name="axis_3"
+ value="AXIS_RIGHTY"/>
+ <combo_box.item
+ label="L Trigger ↘"
+ name="axis_4"
+ value="AXIS_LEFT_TRIGGER"/>
+ <combo_box.item
+ label="R Trigger ↙"
+ name="axis_5"
+ value="AXIS_RIGHT_TRIGGER"/>
+ <combo_box.item
+ label="Triggers ↘↙"
+ name="axis_output_triggers"
+ value="AXIS_TRIGGERS"/>
+ <combo_box.item
+ label="None"
+ name="axis_none"
+ value="AXIS_NONE"/>
+ </combo_box>
+ <!-- axis_output_glyph_selector: the glyph counterpart of axis_output_selector,
+ shown when editing the "output" (icon) column of the Devices-tab
+ axis-channels table. Items are built in C++ from axis_output_selector's
+ values; each item's label is the font glyph for that canonical axis. -->
+ <combo_box
+ name="axis_output_glyph_selector"
+ width="200"
+ height="18"/>
+ <combo_box
+ name="analog_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Strafe ↔"
+ value="Strafe left/right"/>
+ <combo_box.item
+ label="Advance ↕"
+ value="Advance forward/back"/>
+ <combo_box.item
+ label="Turn ↔"
+ value="Turn left/right"/>
+ <combo_box.item
+ label="Look ↕"
+ value="Look up/down"/>
+ <combo_box.item
+ label="Fly ↕"
+ value="Fly up/down"/>
+ <combo_box.item
+ label="Zoom -/+"
+ value="Zoom +/-"/>
+ <combo_box.item
+ label="Scroll -/+"
+ value="Scroll +/-"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <combo_box
+ name="button_input_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="South"
+ name="BUTTON_0"
+ value="BUTTON_SOUTH"/>
+ <combo_box.item
+ label="East"
+ name="BUTTON_1"
+ value="BUTTON_EAST"/>
+ <combo_box.item
+ label="West"
+ name="BUTTON_2"
+ value="BUTTON_WEST"/>
+ <combo_box.item
+ label="North"
+ name="BUTTON_3"
+ value="BUTTON_NORTH"/>
+ <combo_box.item
+ label="Select"
+ name="BUTTON_4"
+ value="BUTTON_SELECT"/>
+ <combo_box.item
+ label="Home"
+ name="BUTTON_5"
+ value="BUTTON_HOME"/>
+ <combo_box.item
+ label="Start"
+ name="BUTTON_6"
+ value="BUTTON_START"/>
+ <combo_box.item
+ label="L Stick"
+ name="BUTTON_7"
+ value="BUTTON_LEFT_STICK"/>
+ <combo_box.item
+ label="R Stick"
+ name="BUTTON_8"
+ value="BUTTON_RIGHT_STICK"/>
+ <combo_box.item
+ label="L Shoulder"
+ name="BUTTON_9"
+ value="BUTTON_LEFT_SHOULDER"/>
+ <combo_box.item
+ label="R Shoulder"
+ name="BUTTON_10"
+ value="BUTTON_RIGHT_SHOULDER"/>
+ <combo_box.item
+ label="DPad Up"
+ name="BUTTON_11"
+ value="BUTTON_DPAD_UP"/>
+ <combo_box.item
+ label="DPad Down"
+ name="BUTTON_12"
+ value="BUTTON_DPAD_DOWN"/>
+ <combo_box.item
+ label="DPad Left"
+ name="BUTTON_13"
+ value="BUTTON_DPAD_LEFT"/>
+ <combo_box.item
+ label="DPad Right"
+ name="BUTTON_14"
+ value="BUTTON_DPAD_RIGHT"/>
+ <combo_box.item
+ label="Misc1"
+ name="BUTTON_15"
+ value="BUTTON_15"/>
+ <combo_box.item
+ label="Paddle 1"
+ name="BUTTON_16"
+ value="BUTTON_PADDLE1"/>
+ <combo_box.item
+ label="Paddle 2"
+ name="BUTTON_17"
+ value="BUTTON_PADDLE2"/>
+ <combo_box.item
+ label="Paddle 3"
+ name="BUTTON_18"
+ value="BUTTON_PADDLE3"/>
+ <combo_box.item
+ label="Paddle 4"
+ name="BUTTON_19"
+ value="BUTTON_PADDLE4"/>
+ <combo_box.item
+ label="Touchpad"
+ name="BUTTON_20"
+ value="BUTTON_TOUCHPAD"/>
+ <combo_box.item
+ label="BUTTON_21"
+ name="BUTTON_21"
+ value="BUTTON_21"/>
+ <combo_box.item
+ label="BUTTON_22"
+ name="BUTTON_22"
+ value="BUTTON_22"/>
+ <combo_box.item
+ label="BUTTON_23"
+ name="BUTTON_23"
+ value="BUTTON_23"/>
+ <combo_box.item
+ label="BUTTON_24"
+ name="BUTTON_24"
+ value="BUTTON_24"/>
+ <combo_box.item
+ label="BUTTON_25"
+ name="BUTTON_25"
+ value="BUTTON_25"/>
+ <combo_box.item
+ label="BUTTON_26"
+ name="BUTTON_26"
+ value="BUTTON_26"/>
+ <combo_box.item
+ label="BUTTON_27"
+ name="BUTTON_27"
+ value="BUTTON_27"/>
+ <combo_box.item
+ label="BUTTON_28"
+ name="BUTTON_28"
+ value="BUTTON_28"/>
+ <combo_box.item
+ label="BUTTON_29"
+ name="BUTTON_29"
+ value="BUTTON_29"/>
+ <combo_box.item
+ label="BUTTON_30"
+ name="BUTTON_30"
+ value="BUTTON_30"/>
+ <combo_box.item
+ label="BUTTON_31"
+ name="BUTTON_31"
+ value="BUTTON_31"/>
+ <combo_box.item
+ label="None"
+ name="BUTTON_NONE"
+ value="BUTTON_NONE"/>
+ </combo_box>
+ <!-- button_input_glyph_selector: the glyph counterpart of button_input_selector,
+ shown when editing the "Button" (icon) column. Items are built
+ in C++ from button_input_selector's values; each item's label is the
+ fong glyph for that button (falling back to text where none exists). -->
+ <combo_box
+ name="button_input_glyph_selector"
+ width="380"
+ height="18"/>
+ <!--
+ For reference, here are the RAW indices of the various input channels
+ of a standard XBox controller. Button (N) is numbered in parentheses,
+ whereas axisN has N+ and N- labels.
+
+ leftpaddle rightpaddle
+ _______ _______
+ / 4+ '-. .-' 5+ \.
+ leftshoulder _(9)_________'-.____ ____.-'_________(10) rightshoulder
+ / _________ \_________/ \.
+ / / 1- \ (3) \.
+ | | | (4) (5) (6) N |
+ | |0- (7) 0+| _________ (2)W E(1) |
+ | | | / 3- \ S |
+ | | 1+ | | | (0) |
+ | \_________/ |2- (8) 2+| |
+ | leftstick (11) | | |
+ | (13) (14) | 3+ | |
+ | (12) \_________/ |
+ | d-pad rightstick |
+ | ____________________ |
+ | / \ |
+ | / \ |
+ | / \ |
+ \__________/ \__________/
+ -->
+ <combo_box
+ name="binary_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Jump"
+ value="Jump"/>
+ <combo_box.item
+ label="Crouch"
+ value="Crouch"/>
+ <combo_box.item
+ label="Sit"
+ value="Toggle sit"/>
+ <!-- TODO: implement Interact feature
+ <combo_box.item
+ label="Interact"
+ value="Interact"/>
+ -->
+ <combo_box.item
+ label="Toggle speak"
+ value="Toggle speak"/>
+ <combo_box.item
+ label="Toggle mouselook"
+ value="Toggle mouselook"/>
+ <combo_box.item
+ label="FlyCam"
+ value="Toggle flycam"/>
+ <combo_box.item
+ label="Mouse cursor"
+ value="Toggle mouse cursor"/>
+ <combo_box.item
+ label="Advance ↑"
+ value="Advance forward"/>
+ <combo_box.item
+ label="Retreat ↓"
+ value="Advance back"/>
+ <combo_box.item
+ label="Strafe ←"
+ value="Strafe left"/>
+ <combo_box.item
+ label="Strafe →"
+ value="Strafe right"/>
+ <combo_box.item
+ label="Fly ↑"
+ value="Fly up"/>
+ <combo_box.item
+ label="Fly ↓"
+ value="Fly down"/>
+ <combo_box.item
+ label="Turn ←"
+ value="Turn left"/>
+ <combo_box.item
+ label="Turn →"
+ value="Turn right"/>
+ <combo_box.item
+ label="Zoom +"
+ value="Zoom +"/>
+ <combo_box.item
+ label="Zoom -"
+ value="Zoom -"/>
+ <combo_box.item
+ label="Scroll +"
+ value="Scroll +"/>
+ <combo_box.item
+ label="Scroll -"
+ value="Scroll -"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <!-- Mouselook-mode action selectors: initialized as independent copies of the
+ Avatar selectors above (same items/defaults for now), so Mouselook's
+ action set can be tuned separately later without touching Avatar's. -->
+ <combo_box
+ name="mouselook_analog_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Strafe ↔"
+ value="Strafe left/right"/>
+ <combo_box.item
+ label="Advance ↕"
+ value="Advance forward/back"/>
+ <combo_box.item
+ label="Turn ↔"
+ value="Turn left/right"/>
+ <combo_box.item
+ label="Look ↕"
+ value="Look up/down"/>
+ <combo_box.item
+ label="Fly ↕"
+ value="Fly up/down"/>
+ <combo_box.item
+ label="Zoom -/+"
+ value="Zoom +/-"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <combo_box
+ name="mouselook_binary_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Jump"
+ value="Jump"/>
+ <combo_box.item
+ label="Crouch"
+ value="Crouch"/>
+ <combo_box.item
+ label="Sit"
+ value="Toggle sit"/>
+ <combo_box.item
+ label="Toggle speak"
+ value="Toggle speak"/>
+ <combo_box.item
+ label="Toggle mouselook"
+ value="Toggle mouselook"/>
+ <combo_box.item
+ label="FlyCam"
+ value="Toggle flycam"/>
+ <combo_box.item
+ label="Mouse cursor"
+ value="Toggle mouse cursor"/>
+ <combo_box.item
+ label="Mouse left"
+ value="Mouse click left"/>
+ <combo_box.item
+ label="Mouse right"
+ value="Mouse click right"/>
+ <combo_box.item
+ label="Advance ↑"
+ value="Advance forward"/>
+ <combo_box.item
+ label="Retreat ↓"
+ value="Advance back"/>
+ <combo_box.item
+ label="Strafe ←"
+ value="Strafe left"/>
+ <combo_box.item
+ label="Strafe →"
+ value="Strafe right"/>
+ <combo_box.item
+ label="Fly ↑"
+ value="Fly up"/>
+ <combo_box.item
+ label="Fly ↓"
+ value="Fly down"/>
+ <combo_box.item
+ label="Turn ←"
+ value="Turn left"/>
+ <combo_box.item
+ label="Turn →"
+ value="Turn right"/>
+ <combo_box.item
+ label="Zoom +"
+ value="Zoom +"/>
+ <combo_box.item
+ label="Zoom -"
+ value="Zoom -"/>
+ <combo_box.item
+ label="ESC"
+ value="ESC"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <combo_box
+ name="sit_binary_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Stand"
+ value="Toggle sit"/>
+ <!-- TODO: implement Interact feature
+ <combo_box.item
+ label="Interact"
+ value="Interact"/>
+ -->
+ <combo_box.item
+ label="Toggle speak"
+ value="Toggle speak"/>
+ <combo_box.item
+ label="Toggle mouselook"
+ value="Toggle mouselook"/>
+ <combo_box.item
+ label="FlyCam"
+ value="Toggle flycam"/>
+ <combo_box.item
+ label="Mouse cursor"
+ value="Toggle mouse cursor"/>
+ <combo_box.item
+ label="Zoom +"
+ value="Zoom +"/>
+ <combo_box.item
+ label="Zoom -"
+ value="Zoom -"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <!-- Cursor-mode action selectors: initialized as independent copies of the
+ Avatar selectors above, with the left-stick axis actions replaced by
+ "Mouse left/right"/"Mouse up/down" (which drive the on-screen cursor;
+ see LLGameControllerManager::computeAgentActions()) and "Mouse click
+ left/right" added to the button set (shoulder buttons by default).
+ "Cursor up/down/left/right" are a digital (button-only) alternative or
+ addition to "Mouse left/right"/"Mouse up/down" for nudging the cursor,
+ e.g. rebind the D-Pad to these instead of Advance/Strafe. Unbound by
+ default. -->
+ <combo_box
+ name="cursor_analog_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Mouse ↔"
+ value="Mouse left/right"/>
+ <combo_box.item
+ label="Mouse ↕"
+ value="Mouse up/down"/>
+ <combo_box.item
+ label="Turn ↔"
+ value="Turn left/right"/>
+ <combo_box.item
+ label="Look ↕"
+ value="Look up/down"/>
+ <combo_box.item
+ label="Fly ↕"
+ value="Fly up/down"/>
+ <combo_box.item
+ label="Strafe ↔"
+ value="Strafe left/right"/>
+ <combo_box.item
+ label="Advance ↕"
+ value="Advance forward/back"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <combo_box
+ name="cursor_binary_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Jump"
+ value="Jump"/>
+ <combo_box.item
+ label="Crouch"
+ value="Crouch"/>
+ <combo_box.item
+ label="Sit"
+ value="Toggle sit"/>
+ <combo_box.item
+ label="Toggle speak"
+ value="Toggle speak"/>
+ <combo_box.item
+ label="Toggle mouselook"
+ value="Toggle mouselook"/>
+ <combo_box.item
+ label="FlyCam"
+ value="Toggle flycam"/>
+ <combo_box.item
+ label="Toggle mouse cursor"
+ value="Toggle mouse cursor"/>
+ <combo_box.item
+ label="Mouse left"
+ value="Mouse click left"/>
+ <combo_box.item
+ label="Mouse right"
+ value="Mouse click right"/>
+ <combo_box.item
+ label="Advance ↑"
+ value="Advance forward"/>
+ <combo_box.item
+ label="Retreat ↓"
+ value="Advance back"/>
+ <combo_box.item
+ label="Strafe ←"
+ value="Strafe left"/>
+ <combo_box.item
+ label="Strafe →"
+ value="Strafe right"/>
+ <combo_box.item
+ label="Fly ↑"
+ value="Fly up"/>
+ <combo_box.item
+ label="Fly ↓"
+ value="Fly down"/>
+ <combo_box.item
+ label="Turn ←"
+ value="Turn left"/>
+ <combo_box.item
+ label="Turn →"
+ value="Turn right"/>
+ <combo_box.item
+ label="Cursor ↑"
+ value="Cursor up"/>
+ <combo_box.item
+ label="Cursor ↓"
+ value="Cursor down"/>
+ <combo_box.item
+ label="Cursor ←"
+ value="Cursor left"/>
+ <combo_box.item
+ label="Cursor →"
+ value="Cursor right"/>
+ <combo_box.item
+ label="ESC"
+ value="ESC"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <!-- FlyCam-mode action selectors: distinct action sets for the FlyCam mode.
+ Item value is the ASCII action key used in the GameControl settings (it must
+ match the hard-coded key in llgamecontrol.cpp); label is the display text. -->
+ <combo_box
+ name="flycam_analog_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Truck ↔"
+ value="Truck left/right"/>
+ <combo_box.item
+ label="Dolly ↕"
+ value="Dolly forward/back"/>
+ <combo_box.item
+ label="Pan ↔"
+ value="Pan left/right"/>
+ <combo_box.item
+ label="Tilt ↕"
+ value="Tilt up/down"/>
+ <combo_box.item
+ label="Boom ↕"
+ value="Boom up/down"/>
+ <combo_box.item
+ label="Roll ↻↺"
+ value="Roll CCW/CW"/>
+ <combo_box.item
+ label="Zoom -/+"
+ value="Zoom in/out"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+ <combo_box
+ name="flycam_binary_action_selector"
+ width="380"
+ height="18">
+ <combo_box.item
+ label="Zoom -"
+ value="Zoom out"/>
+ <combo_box.item
+ label="Pan →"
+ value="Pan right"/>
+ <combo_box.item
+ label="Pan ←"
+ value="Pan left"/>
+ <combo_box.item
+ label="Zoom +"
+ value="Zoom in"/>
+ <combo_box.item
+ label="Mouse cursor"
+ value="Toggle mouse cursor"/>
+ <combo_box.item
+ label="Leave flycam"
+ value="Toggle flycam"/>
+ <combo_box.item
+ label="Unroll"
+ value="Unroll"/>
+ <combo_box.item
+ label="Roll ↺"
+ value="Roll CCW"/>
+ <combo_box.item
+ label="Roll ↻"
+ value="Roll CW"/>
+ <combo_box.item
+ label="Orbit"
+ value="Orbit"/>
+ <combo_box.item
+ label="Dolly ↑"
+ value="Dolly forward"/>
+ <combo_box.item
+ label="Dolly ↓"
+ value="Dolly back"/>
+ <combo_box.item
+ label="Truck ←"
+ value="Truck left"/>
+ <combo_box.item
+ label="Truck →"
+ value="Truck right"/>
+ <combo_box.item
+ label="Boom ↑"
+ value="Boom up"/>
+ <combo_box.item
+ label="Boom ↓"
+ value="Boom down"/>
+ <combo_box.item
+ label="ESC"
+ value="ESC"/>
+ <combo_box.item
+ label="None"
+ value="None"/>
+ </combo_box>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
index a0489b37b5..c8febd3312 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
@@ -323,7 +323,7 @@
width="200" />
<button
height="23"
- label="Other Devices"
+ label="3Dconnexion devices"
left="30"
name="joystick_setup_button"
top="30"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index e1644da338..5373c6198f 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -71,7 +71,7 @@ Voice Server Version: [VOICE_VERSION]
<string name="LocalTime">[month, datetime, local] [day, datetime, local] [year, datetime, local] [hour, datetime, local]:[min, datetime, local]:[second,datetime, local]</string>
<string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string>
<string name="BuildConfiguration">Build Configuration</string>
-
+
<!-- progress -->
<string name="ProgressRestoring">Restoring...</string>
<string name="ProgressChangingResolution">Changing resolution...</string>
@@ -114,12 +114,12 @@ Voice Server Version: [VOICE_VERSION]
<string name="LoginFailedHeader">Login failed.</string>
<string name="Quit">Quit</string>
<string name="create_account_url">http://join.secondlife.com/?sourceid=[sourceid]</string>
-
+
<string name="AgniGridLabel">Second Life Main Grid (Agni)</string>
<string name="AditiGridLabel">Second Life Beta Test Grid (Aditi)</string>
<string name="AgniGridLabelShort">Agni (production)</string>
<string name="AditiGridLabelShort">Aditi (beta)</string>
-
+
<string name="ViewerDownloadURL">http://secondlife.com/download</string>
<string name="LoginFailedViewerNotPermitted">
The viewer you are using can no longer access Second Life. Please visit the following page to download a new viewer:
@@ -213,7 +213,7 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="YouHaveBeenDisconnected">You have been disconnected from the region you were in.</string>
<string name="SentToInvalidRegion">You were sent to an invalid region.</string>
<string name="TestingDisconnect">Testing viewer disconnect</string>
-
+
<!-- SLShare: User Friendly Filter Names Translation -->
<string name="BlackAndWhite">Black &amp; White</string>
<string name="Colors1970">1970&apos;s Colors</string>
@@ -226,7 +226,7 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="LensFlare">Lens Flare</string>
<string name="Miniature">Miniature</string>
<string name="Toycamera">Toy Camera</string>
-
+
<!-- Tooltip -->
<string name="ReorderClothingTooltip">Drag to reorder layers, or use the arrows</string> <!-- Hint shown on clothing rows that can be dragged to reorder -->
<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
@@ -265,10 +265,10 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="TooltipOutfitNotInInventory">You can only put items or outfits from your personal inventory into "My outfits"</string>
<string name="TooltipCantCreateOutfit">One or more items can't be used inside "My outfits"</string>
<string name="TooltipCantMoveOutfitIntoOutfit">Can not move an outfit into another outfit</string>
-
+
<string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string>
<string name="TooltipDragOntoSelf">You can't move a folder into itself</string>
-
+
<!-- tooltips for Urls -->
<string name="TooltipHttpUrl">Click to view this web page</string>
<string name="TooltipSLURL">Click to view this location's information</string>
@@ -377,7 +377,7 @@ are allowed.
<string name="AssetUploadServerDifficulties">The server is experiencing unexpected difficulties.</string>
<string name="AssetUploadServerUnavaliable">Service not available or upload timeout was reached.</string>
<string name="AssetUploadRequestInvalid">
-Error in upload request. Please visit
+Error in upload request. Please visit
http://secondlife.com/support for help fixing this problem.
</string>
@@ -544,7 +544,8 @@ http://secondlife.com/support for help fixing this problem.
<string name="ForceSitAvatar">Force your avatar to sit</string>
<string name="ChangeEnvSettings">Change your environment settings</string>
<string name="PrivilegedLandAccess">Sell land on your behalf.</string>
-
+ <string name="UseGameControlInputs">Use gamepad inputs.</string>
+
<string name="NotConnected">Not Connected</string>
<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name -->
<string name="JoinAnExperience"/><!-- intentionally blank -->
@@ -2330,7 +2331,7 @@ For AI Character: Get the closest navigable point to the point provided.
<!-- inventory -->
<string name="InventoryNoMatchingItems">No matching items.</string>
- <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
+ <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
<string name="InventoryNoMatchingFavorites">You haven't marked any items as favorites.</string>
<string name="PlacesNoMatchingItems">To add a place to your landmarks, click the star to the right of the location name.</string>
<string name="FavoritesNoMatchingItems">To add a place to your favorites, click the star to the right of the location name, then save the landmark to "Favorites bar".</string>
@@ -2515,7 +2516,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="InvFolder Materials">Materials</string>
<!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
- <string name="InvFolder Friends">Friends</string>
+ <string name="InvFolder Friends">Friends</string>
<string name="InvFolder All">All</string>
<string name="no_attachments">No attachments worn</string>
@@ -2684,7 +2685,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="UploadFailed">File upload failed: </string>
<string name="ObjectOutOfRange">Script (object out of range)</string>
<string name="ScriptWasDeleted">Script (deleted from inventory)</string>
-
+
<!-- god tools -->
<string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string>
@@ -3868,7 +3869,7 @@ Learn more at https://second.life/scripted-agents.
<string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
<string name="this_costs">This costs L$ [AMOUNT]</string>
-
+
<string name="buying_selected_land">This land costs</string>
<string name="this_object_costs">This item costs</string>
<string name="giving">You want to give</string>
@@ -3949,7 +3950,7 @@ Abuse Report</string>
<string name="New Daycycle">New Daycycle</string>
<string name="New Water">New Water</string>
<string name="New Sky">New Sky</string>
-
+
<string name="/bow">/bow</string>
<string name="/clap">/clap</string>
@@ -4032,7 +4033,7 @@ Please check http://status.secondlifegrid.net to see if there is a known problem
<string name="Accounting">Accounting</string>
<string name="Notices">Notices</string>
<string name="Chat">Chat</string>
-
+
<!-- SL Membership -->
<string name="BaseMembership">Base</string>
<string name="PremiumMembership">Premium</string>
@@ -4200,7 +4201,7 @@ Try enclosing path to the editor with double quotes.
<!-- commands -->
- <string
+ <string
name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_AboutLand_Label">About land</string>
<string name="Command_Appearance_Label">Outfits</string>
@@ -4236,7 +4237,7 @@ name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_ResyncAnimations_Label">Resync animations</string>
<string name="Command_AO_Label">AO</string>
- <string
+ <string
name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Command_AboutLand_Tooltip">Information about the land you're visiting</string>
<string name="Command_Appearance_Tooltip">Change your avatar</string>
@@ -4304,7 +4305,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<!-- Spell check settings floater -->
<string name="UserDictionary">[User]</string>
-
+
<!-- Experience Tools strings -->
<string name="experience_tools_experience">Experience</string>
<string name="ExperienceNameNull">(no experience)</string>
@@ -4343,7 +4344,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="material_selection_title">Material selection</string>
<string name="material_selection_text">Select material:</string>
<string name="material_batch_import_text">--- Bulk Upload All ---</string>
-
+
<!-- Conversation log messages -->
<string name="logging_calls_disabled_log_empty">
Conversations are not being logged. To begin keeping a log, choose "Save: Log only" or "Save: Log and transcripts" under Preferences > Chat.
@@ -4366,7 +4367,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Default">Default</string>
<string name="none_paren_cap">(None)</string>
<string name="no_limit">No limit</string>
-
+
<string name="Mav_Details_MAV_FOUND_DEGENERATE_TRIANGLES">
The physics shape contains triangles which are too small. Try simplifying the physics model.
</string>
diff --git a/indra/newview/tests/llgamecontrol_stub.cpp b/indra/newview/tests/llgamecontrol_stub.cpp
new file mode 100644
index 0000000000..22589bcad3
--- /dev/null
+++ b/indra/newview/tests/llgamecontrol_stub.cpp
@@ -0,0 +1,99 @@
+/**
+ * @file llgamecontrol_stub.cpp
+ * @brief Stubbery for LLGameControl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llgamecontrol.h"
+
+#include "SDL3/SDL_events.h"
+
+LLGameControl::ServerState g_state;
+
+// static
+bool LLGameControl::isInitialized()
+{
+ return false;
+}
+
+// static
+void LLGameControl::init()
+{
+}
+
+// static
+void LLGameControl::terminate()
+{
+}
+
+// static
+bool LLGameControl::computeFinalStateAndCheckForChanges()
+{
+ return false;
+}
+
+// static
+void LLGameControl::clearAllState()
+{
+}
+
+// static
+void LLGameControl::processEvents(bool app_has_focus)
+{
+}
+
+// static
+const LLGameControl::State& LLGameControl::getServerState()
+{
+ return g_state;
+}
+
+// static
+void LLGameControl::setIncludeKeyboard(bool include)
+{
+}
+
+// static
+bool LLGameControl::getIncludeKeyboard()
+{
+ return false;
+}
+
+// static
+LLGameControl::InputChannel LLGameControl::getChannelByActionName(const std::string& name)
+{
+ return LLGameControl::InputChannel();
+}
+
+// static
+void LLGameControl::addActionMapping(const std::string& name, LLGameControl::InputChannel channel)
+{
+}
+
+// static
+void LLGameControl::setActionFlags(U32 action_flags)
+{
+}
+
diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp
index a78235c5f7..bb546b5832 100644
--- a/indra/newview/tests/llversioninfo_test.cpp
+++ b/indra/newview/tests/llversioninfo_test.cpp
@@ -31,7 +31,10 @@
#include "llversioninfovars.h"
- #include <iostream>
+#include <iostream>
+
+//#include "llgamecontrol_stub.cpp"
+
// LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The
// macro expands to the string name of the channel, but without quotes. We
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index f451b28475..1e3f2df859 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -79,6 +79,7 @@ class ViewerManifest(LLManifest):
self.exclude("logcontrol.xml")
self.exclude("logcontrol-dev.xml")
self.path("*.ini")
+ self.path("*.txt")
self.path("*.xml")
# include the entire shaders directory recursively
@@ -589,6 +590,9 @@ class Windows_x86_64_Manifest(ViewerManifest):
self.path_optional("vcruntime140_1.dll")
self.path_optional("vcruntime140_threads.dll")
+ # SDL3
+ self.path("SDL3.dll")
+
# BugSplat
if self.args.get('bugsplat'):
self.path("BsSndRpt64.exe")
@@ -989,7 +993,7 @@ class Darwin_x86_64_Manifest(ViewerManifest):
# Remember where we parked this car.
with self.prefix(src=relpkgdir, dst="Frameworks"):
self.path("libndofdev.dylib")
-
+ self.path("libSDL3.dylib") # gamecontrol
if self.args.get('bugsplat'):
self.path2basename(relpkgdir, "BugsplatMac.framework")