diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 25b279ba40..88a717aa53 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -56,6 +56,11 @@ if(XDG_STD) set(pcsx2FinalFlags ${pcsx2FinalFlags} -DXDG_STD) endif() +if(SDL_FOUND) + set(pcsx2FinalFlags ${pcsx2FinalFlags} -DSDL_BUILD) +endif() + + set(Output PCSX2) # Main pcsx2 source @@ -446,6 +451,82 @@ if(PULSEAUDIO_FOUND) set(pcsx2USBHeaders ${pcsx2USBHeaders} USB/usb-mic/audiodev-pulse.h) endif() + + +# PAD resources pre-compilation +set(PADImgHeader "${CMAKE_BINARY_DIR}/pcsx2/PAD/ImgHeader") +set(PADImg "${CMAKE_SOURCE_DIR}/pcsx2/PAD/Img") + +file(MAKE_DIRECTORY ${compiled_images}) + +foreach(result_file IN ITEMS + analog circle cross dp_bottom dp_left dp_right dp_up dualshock2 + joystick_cursor l1 r1 l2 r2 l3 r3 select square start triangle arrow_up + arrow_bottom arrow_left arrow_right) + add_custom_command( + OUTPUT "${PADImgHeader}/${result_file}.h" + COMMAND perl ${CMAKE_SOURCE_DIR}/linux_various/hex2h.pl "${PADImg}/${result_file}.png" "${PADImgHeader}/${result_file}" ) +endforeach() + + +# PAD sources +set(pcsx2PADSources + PAD/controller.cpp + PAD/GamePad.cpp + PAD/SDL/joystick.cpp + PAD/keyboard.cpp + PAD/KeyStatus.cpp + PAD/onepad.cpp + PAD/resources.cpp + PAD/state_management.cpp + PAD/wx_dialog/dialog.cpp + PAD/wx_dialog/opPanel.cpp + PAD/wx_dialog/GamepadConfiguration.cpp + PAD/wx_dialog/JoystickConfiguration.cpp + PAD/ini.cpp + PAD/linux.cpp + ) + +# PAD headers +set(pcsx2PADHeaders + PAD/bitwise.h + PAD/controller.h + PAD/GamePad.h + PAD/SDL/joystick.h + PAD/keyboard.h + PAD/KeyStatus.h + PAD/onepad.h + PAD/resources.h + PAD/state_management.h + PAD/wx_dialog/opPanel.h + PAD/wx_dialog/GamepadConfiguration.h + PAD/wx_dialog/JoystickConfiguration.h + # images + ${PADImgHeader}/analog.h + ${PADImgHeader}/circle.h + ${PADImgHeader}/cross.h + ${PADImgHeader}/dp_bottom.h + ${PADImgHeader}/dp_left.h + ${PADImgHeader}/dp_right.h + ${PADImgHeader}/dp_up.h + ${PADImgHeader}/dualshock2.h + ${PADImgHeader}/joystick_cursor.h + ${PADImgHeader}/l1.h + ${PADImgHeader}/r1.h + ${PADImgHeader}/l2.h + ${PADImgHeader}/r2.h + ${PADImgHeader}/l3.h + ${PADImgHeader}/r3.h + ${PADImgHeader}/select.h + ${PADImgHeader}/square.h + ${PADImgHeader}/start.h + ${PADImgHeader}/triangle.h + ${PADImgHeader}/arrow_up.h + ${PADImgHeader}/arrow_bottom.h + ${PADImgHeader}/arrow_left.h + ${PADImgHeader}/arrow_right.h + ) + # DebugTools sources set(pcsx2DebugToolsSources DebugTools/DebugInterface.cpp @@ -908,6 +989,8 @@ if(Linux) ${pcsx2LinuxHeaders} ${pcsx2USBSources} ${pcsx2USBHeaders} + ${pcsx2PADHeaders} + ${pcsx2PADSources} ) set(Platform_Libs diff --git a/pcsx2/PAD/Linux/CMakeLists.txt b/pcsx2/PAD/Linux/CMakeLists.txt new file mode 100644 index 0000000000..df1de75926 --- /dev/null +++ b/pcsx2/PAD/Linux/CMakeLists.txt @@ -0,0 +1,141 @@ +# Check that people use the good file +if(NOT TOP_CMAKE_WAS_SOURCED) + message(FATAL_ERROR " + You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir. + It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt") +endif() + +set(compiled_images "${CMAKE_BINARY_DIR}/plugins/onepad/ImgHeader") +set(image_sources "${CMAKE_SOURCE_DIR}/plugins/onepad/Img") +set(linux_sources "Linux") +set(linux_headers "Linux") +set(wx_sources "wx_dialog") +set(wx_headers "wx_dialog") + +set(onepadGuiResources + ${compiled_images}/analog.h + ${compiled_images}/circle.h + ${compiled_images}/cross.h + ${compiled_images}/dp_bottom.h + ${compiled_images}/dp_left.h + ${compiled_images}/dp_right.h + ${compiled_images}/dp_up.h + ${compiled_images}/dualshock2.h + ${compiled_images}/joystick_cursor.h + ${compiled_images}/l1.h + ${compiled_images}/r1.h + ${compiled_images}/l2.h + ${compiled_images}/r2.h + ${compiled_images}/l3.h + ${compiled_images}/r3.h + ${compiled_images}/select.h + ${compiled_images}/square.h + ${compiled_images}/start.h + ${compiled_images}/triangle.h + ${compiled_images}/arrow_up.h + ${compiled_images}/arrow_bottom.h + ${compiled_images}/arrow_left.h + ${compiled_images}/arrow_right.h + ) + +# plugin name +set(Output onepad) + +set(onepadFinalFlags + -fvisibility=hidden + -Wall + -Wno-parentheses + ) + +# onepad sources +set(onepadSources + controller.cpp + GamePad.cpp + SDL/joystick.cpp + keyboard.cpp + KeyStatus.cpp + onepad.cpp + resources.cpp + state_management.cpp) + +# onepad headers +set(onepadHeaders + bitwise.h + controller.h + GamePad.h + SDL/joystick.h + keyboard.h + KeyStatus.h + onepad.h + resources.h + state_management.h) + +# onepad wx sources +set(onepadwxSources + ${wx_sources}/dialog.cpp + ${wx_sources}/opPanel.cpp + ${wx_sources}/GamepadConfiguration.cpp + ${wx_headers}/JoystickConfiguration.cpp) + +# onepad wx headers +set(onepadwxHeaders + ${wx_headers}/opPanel.h + ${wx_headers}/GamepadConfiguration.h + ${wx_headers}/JoystickConfiguration.h) + +# onepad Linux sources +set(onepadLinuxSources + ${linux_sources}/ini.cpp + ${linux_sources}/linux.cpp) + +# onepad Linux headers +set(onepadLinuxHeaders) + +set(onepadFinalLibs ${SDL2_LIBRARIES}) +add_definitions(-DSDL_BUILD) + +set(onepadFinalLibs + ${onepadFinalLibs} + ${wxWidgets_LIBRARIES} + ${GTK2_LIBRARIES} + ${X11_LIBRARIES} +) + +set(onepadFinalSources + ${onepadSources} + ${onepadHeaders} + ${onepadwxSources} + ${onepadwxHeaders} + ${onepadLinuxSources} + ${onepadLinuxHeaders} + ${onepadGuiResources} +) + +include_directories( + ${CMAKE_BINARY_DIR}/plugins/onepad/ +) + +### Generate the resources files +file(MAKE_DIRECTORY ${compiled_images}) + +foreach(result_file IN ITEMS + analog circle cross dp_bottom dp_left dp_right dp_up dualshock2 + joystick_cursor l1 r1 l2 r2 l3 r3 select square start triangle arrow_up + arrow_bottom arrow_left arrow_right) + add_custom_command( + OUTPUT "${compiled_images}/${result_file}.h" + COMMAND perl ${CMAKE_SOURCE_DIR}/linux_various/hex2h.pl "${image_sources}/${result_file}.png" "${compiled_images}/${result_file}" ) +endforeach() + +set(RESOURCE_FILES res/game_controller_db.txt) + +add_custom_glib_res("resources" "onepad-res.xml" "onepad_res" ${RESOURCE_FILES}) + + +if(BUILTIN_PAD) + add_pcsx2_lib(${Output} "${onepadFinalSources}" "${onepadFinalLibs}" "${onepadFinalFlags}") +else() + add_pcsx2_plugin(${Output} "${onepadFinalSources}" "${onepadFinalLibs}" "${onepadFinalFlags}") +endif() + +target_compile_features(${Output} PRIVATE cxx_std_17) diff --git a/pcsx2/PAD/Linux/GamePad.cpp b/pcsx2/PAD/Linux/GamePad.cpp new file mode 100644 index 0000000000..1227072566 --- /dev/null +++ b/pcsx2/PAD/Linux/GamePad.cpp @@ -0,0 +1,76 @@ +/* + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GamePad.h" +#ifdef SDL_BUILD +#include "SDL/joystick.h" +#endif + +std::vector> s_vgamePad; + +/** + * Following static methods are just forwarders to their backend + * This is where link between agnostic and specific code is done + **/ + +/** + * Find every interesting devices and create right structure for them(depend on backend) + **/ +void GamePad::EnumerateGamePads(std::vector> &vgamePad) +{ +#ifdef SDL_BUILD + JoystickInfo::EnumerateJoysticks(vgamePad); +#endif +} + +/** + * Safely dispatch to the Rumble method above + **/ +void GamePad::DoRumble(unsigned type, unsigned pad) +{ + int index = uid_to_index(pad); + if (index >= 0) + s_vgamePad[index]->Rumble(type, pad); +} + +size_t GamePad::index_to_uid(int index) +{ + if ((index >= 0) && (index < (int)s_vgamePad.size())) + return s_vgamePad[index]->GetUniqueIdentifier(); + else + return 0; +} + +int GamePad::uid_to_index(int pad) +{ + size_t uid = g_conf.get_joy_uid(pad); + + for (int i = 0; i < (int)s_vgamePad.size(); ++i) { + if (s_vgamePad[i]->GetUniqueIdentifier() == uid) + return i; + } + + // Current uid wasn't found maybe the pad was unplugged. Or + // user didn't select it. Fallback to 1st pad for + // 1st player. And 2nd pad for 2nd player. + if ((int)s_vgamePad.size() > pad) + return pad; + + return -1; +} diff --git a/pcsx2/PAD/Linux/GamePad.h b/pcsx2/PAD/Linux/GamePad.h new file mode 100644 index 0000000000..5a0a2c81b0 --- /dev/null +++ b/pcsx2/PAD/Linux/GamePad.h @@ -0,0 +1,94 @@ +/* + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#include "onepad.h" +#include "controller.h" + +#ifdef SDL_BUILD +#include +#endif + +class GamePad +{ +public: + GamePad() + : m_deadzone(1500) + , m_no_error(false) + { + } + + virtual ~GamePad() + { + } + + GamePad(const GamePad &); // copy constructor + GamePad &operator=(const GamePad &); // assignment + + /* + * Find every interesting devices and create right structure for them(depend on backend) + */ + static void EnumerateGamePads(std::vector> &vgamePad); + + /* + * Update state of every attached devices + */ + virtual void UpdateGamePadState() = 0; + + /* + * Causes devices to rumble + * Rumble will differ according to type which is either 0(small motor) or 1(big motor) + */ + virtual void Rumble(unsigned type, unsigned pad) {} + /* + * Safely dispatch to the Rumble method above + */ + static void DoRumble(unsigned type, unsigned pad); + + /* + * Used for GUI checkbox to give feedback to the user + */ + virtual bool TestForce(float strength = 0.6) { return false; } + + virtual const char *GetName() = 0; + + virtual int GetInput(gamePadValues input) = 0; + + int GetDeadzone() + { + return m_deadzone; + } + + virtual size_t GetUniqueIdentifier() = 0; + + static size_t index_to_uid(int index); + static int uid_to_index(int pad); + + bool IsProperlyInitialized() + { + return m_no_error; + } + +protected: + int m_deadzone; + bool m_no_error; +}; + +extern std::vector> s_vgamePad; diff --git a/pcsx2/PAD/Linux/Img/analog-2.png b/pcsx2/PAD/Linux/Img/analog-2.png new file mode 100644 index 0000000000..0263c1ce16 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/analog-2.png differ diff --git a/pcsx2/PAD/Linux/Img/analog.png b/pcsx2/PAD/Linux/Img/analog.png new file mode 100644 index 0000000000..dbd8c19313 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/analog.png differ diff --git a/pcsx2/PAD/Linux/Img/arrow_bottom.png b/pcsx2/PAD/Linux/Img/arrow_bottom.png new file mode 100644 index 0000000000..8ebc6d5535 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/arrow_bottom.png differ diff --git a/pcsx2/PAD/Linux/Img/arrow_left.png b/pcsx2/PAD/Linux/Img/arrow_left.png new file mode 100644 index 0000000000..4000cb476f Binary files /dev/null and b/pcsx2/PAD/Linux/Img/arrow_left.png differ diff --git a/pcsx2/PAD/Linux/Img/arrow_right.png b/pcsx2/PAD/Linux/Img/arrow_right.png new file mode 100644 index 0000000000..c391d0025b Binary files /dev/null and b/pcsx2/PAD/Linux/Img/arrow_right.png differ diff --git a/pcsx2/PAD/Linux/Img/arrow_up.png b/pcsx2/PAD/Linux/Img/arrow_up.png new file mode 100644 index 0000000000..dc8de6ccde Binary files /dev/null and b/pcsx2/PAD/Linux/Img/arrow_up.png differ diff --git a/pcsx2/PAD/Linux/Img/circle.png b/pcsx2/PAD/Linux/Img/circle.png new file mode 100644 index 0000000000..cabc2681f5 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/circle.png differ diff --git a/pcsx2/PAD/Linux/Img/cross.png b/pcsx2/PAD/Linux/Img/cross.png new file mode 100644 index 0000000000..e108086ce1 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/cross.png differ diff --git a/pcsx2/PAD/Linux/Img/dp_bottom.png b/pcsx2/PAD/Linux/Img/dp_bottom.png new file mode 100644 index 0000000000..0f69cdd4a5 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/dp_bottom.png differ diff --git a/pcsx2/PAD/Linux/Img/dp_left.png b/pcsx2/PAD/Linux/Img/dp_left.png new file mode 100644 index 0000000000..1245499cfc Binary files /dev/null and b/pcsx2/PAD/Linux/Img/dp_left.png differ diff --git a/pcsx2/PAD/Linux/Img/dp_right.png b/pcsx2/PAD/Linux/Img/dp_right.png new file mode 100644 index 0000000000..23fa90cbc0 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/dp_right.png differ diff --git a/pcsx2/PAD/Linux/Img/dp_up.png b/pcsx2/PAD/Linux/Img/dp_up.png new file mode 100644 index 0000000000..60af347bb2 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/dp_up.png differ diff --git a/pcsx2/PAD/Linux/Img/dualshock2.png b/pcsx2/PAD/Linux/Img/dualshock2.png new file mode 100644 index 0000000000..a64cf8edc2 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/dualshock2.png differ diff --git a/pcsx2/PAD/Linux/Img/joystick_cursor.png b/pcsx2/PAD/Linux/Img/joystick_cursor.png new file mode 100644 index 0000000000..8473398102 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/joystick_cursor.png differ diff --git a/pcsx2/PAD/Linux/Img/l1.png b/pcsx2/PAD/Linux/Img/l1.png new file mode 100644 index 0000000000..b1bb1187e8 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/l1.png differ diff --git a/pcsx2/PAD/Linux/Img/l2.png b/pcsx2/PAD/Linux/Img/l2.png new file mode 100644 index 0000000000..0cd26db209 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/l2.png differ diff --git a/pcsx2/PAD/Linux/Img/l3.png b/pcsx2/PAD/Linux/Img/l3.png new file mode 100644 index 0000000000..eff4424d96 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/l3.png differ diff --git a/pcsx2/PAD/Linux/Img/r1.png b/pcsx2/PAD/Linux/Img/r1.png new file mode 100644 index 0000000000..7f162ba21a Binary files /dev/null and b/pcsx2/PAD/Linux/Img/r1.png differ diff --git a/pcsx2/PAD/Linux/Img/r2.png b/pcsx2/PAD/Linux/Img/r2.png new file mode 100644 index 0000000000..62ff3b217b Binary files /dev/null and b/pcsx2/PAD/Linux/Img/r2.png differ diff --git a/pcsx2/PAD/Linux/Img/r3.png b/pcsx2/PAD/Linux/Img/r3.png new file mode 100644 index 0000000000..715b5e35ab Binary files /dev/null and b/pcsx2/PAD/Linux/Img/r3.png differ diff --git a/pcsx2/PAD/Linux/Img/select.png b/pcsx2/PAD/Linux/Img/select.png new file mode 100644 index 0000000000..e89e9fdc5c Binary files /dev/null and b/pcsx2/PAD/Linux/Img/select.png differ diff --git a/pcsx2/PAD/Linux/Img/square.png b/pcsx2/PAD/Linux/Img/square.png new file mode 100644 index 0000000000..bcbed6d51b Binary files /dev/null and b/pcsx2/PAD/Linux/Img/square.png differ diff --git a/pcsx2/PAD/Linux/Img/start.png b/pcsx2/PAD/Linux/Img/start.png new file mode 100644 index 0000000000..cce5853e05 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/start.png differ diff --git a/pcsx2/PAD/Linux/Img/triangle.png b/pcsx2/PAD/Linux/Img/triangle.png new file mode 100644 index 0000000000..a3fd567242 Binary files /dev/null and b/pcsx2/PAD/Linux/Img/triangle.png differ diff --git a/pcsx2/PAD/Linux/KeyStatus.cpp b/pcsx2/PAD/Linux/KeyStatus.cpp new file mode 100644 index 0000000000..fa59fe474b --- /dev/null +++ b/pcsx2/PAD/Linux/KeyStatus.cpp @@ -0,0 +1,198 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2011 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "KeyStatus.h" + +void KeyStatus::Init() +{ + for (int pad = 0; pad < GAMEPAD_NUMBER; pad++) { + m_button[pad] = 0xFFFF; + m_internal_button_kbd[pad] = 0xFFFF; + m_internal_button_joy[pad] = 0xFFFF; + m_state_acces[pad] = false; + + for (int index = 0; index < MAX_KEYS; index++) { + m_button_pressure[pad][index] = 0xFF; + m_internal_button_pressure[pad][index] = 0xFF; + } + + m_analog[pad].lx = m_analog_released_val; + m_analog[pad].ly = m_analog_released_val; + m_analog[pad].rx = m_analog_released_val; + m_analog[pad].ry = m_analog_released_val; + m_internal_analog_kbd[pad].lx = m_analog_released_val; + m_internal_analog_kbd[pad].ly = m_analog_released_val; + m_internal_analog_kbd[pad].rx = m_analog_released_val; + m_internal_analog_kbd[pad].ry = m_analog_released_val; + m_internal_analog_joy[pad].lx = m_analog_released_val; + m_internal_analog_joy[pad].ly = m_analog_released_val; + m_internal_analog_joy[pad].rx = m_analog_released_val; + m_internal_analog_joy[pad].ry = m_analog_released_val; + } +} + +void KeyStatus::press(u32 pad, u32 index, s32 value) +{ + if (!IsAnalogKey(index)) { + m_internal_button_pressure[pad][index] = value; + if (m_state_acces[pad]) + clear_bit(m_internal_button_kbd[pad], index); + else + clear_bit(m_internal_button_joy[pad], index); + } else { + // clamp value + if (value > MAX_ANALOG_VALUE) + value = MAX_ANALOG_VALUE; + else if (value < -MAX_ANALOG_VALUE) + value = -MAX_ANALOG_VALUE; + + // Left -> -- -> Right + // Value range : FFFF8002 -> 0 -> 7FFE + // Force range : 80 -> 0 -> 7F + // Normal mode : expect value 0 -> 80 -> FF + // Reverse mode: expect value FF -> 7F -> 0 + u8 force = (value / 256); + if (analog_is_reversed(pad, index)) + analog_set(pad, index, m_analog_released_val - force); + else + analog_set(pad, index, m_analog_released_val + force); + } +} + +void KeyStatus::release(u32 pad, u32 index) +{ + if (!IsAnalogKey(index)) { + if (m_state_acces[pad]) + set_bit(m_internal_button_kbd[pad], index); + else + set_bit(m_internal_button_joy[pad], index); + } else { + analog_set(pad, index, m_analog_released_val); + } +} + +u16 KeyStatus::get(u32 pad) +{ + return m_button[pad]; +} + +void KeyStatus::analog_set(u32 pad, u32 index, u8 value) +{ + PADAnalog *m_internal_analog_ref; + if (m_state_acces[pad]) + m_internal_analog_ref = &m_internal_analog_kbd[pad]; + else + m_internal_analog_ref = &m_internal_analog_joy[pad]; + + switch (index) { + case PAD_R_LEFT: + case PAD_R_RIGHT: + m_internal_analog_ref->rx = value; + break; + + case PAD_R_DOWN: + case PAD_R_UP: + m_internal_analog_ref->ry = value; + break; + + case PAD_L_LEFT: + case PAD_L_RIGHT: + m_internal_analog_ref->lx = value; + break; + + case PAD_L_DOWN: + case PAD_L_UP: + m_internal_analog_ref->ly = value; + break; + + default: + break; + } +} + +bool KeyStatus::analog_is_reversed(u32 pad, u32 index) +{ + switch (index) { + case PAD_L_RIGHT: + case PAD_L_LEFT: + return (g_conf.pad_options[pad].reverse_lx); + + case PAD_R_LEFT: + case PAD_R_RIGHT: + return (g_conf.pad_options[pad].reverse_rx); + + case PAD_L_UP: + case PAD_L_DOWN: + return (g_conf.pad_options[pad].reverse_ly); + + case PAD_R_DOWN: + case PAD_R_UP: + return (g_conf.pad_options[pad].reverse_ry); + + default: + return false; + } +} + +u8 KeyStatus::get(u32 pad, u32 index) +{ + switch (index) { + case PAD_R_LEFT: + case PAD_R_RIGHT: + return m_analog[pad].rx; + + case PAD_R_DOWN: + case PAD_R_UP: + return m_analog[pad].ry; + + case PAD_L_LEFT: + case PAD_L_RIGHT: + return m_analog[pad].lx; + + case PAD_L_DOWN: + case PAD_L_UP: + return m_analog[pad].ly; + + default: + return m_button_pressure[pad][index]; + } +} + +u8 KeyStatus::analog_merge(u8 kbd, u8 joy) +{ + if (kbd != m_analog_released_val) + return kbd; + else + return joy; +} + +void KeyStatus::commit_status(u32 pad) +{ + m_button[pad] = m_internal_button_kbd[pad] & m_internal_button_joy[pad]; + + for (int index = 0; index < MAX_KEYS; index++) + m_button_pressure[pad][index] = m_internal_button_pressure[pad][index]; + + m_analog[pad].lx = analog_merge(m_internal_analog_kbd[pad].lx, m_internal_analog_joy[pad].lx); + m_analog[pad].ly = analog_merge(m_internal_analog_kbd[pad].ly, m_internal_analog_joy[pad].ly); + m_analog[pad].rx = analog_merge(m_internal_analog_kbd[pad].rx, m_internal_analog_joy[pad].rx); + m_analog[pad].ry = analog_merge(m_internal_analog_kbd[pad].ry, m_internal_analog_joy[pad].ry); +} diff --git a/pcsx2/PAD/Linux/KeyStatus.h b/pcsx2/PAD/Linux/KeyStatus.h new file mode 100644 index 0000000000..ae402e091a --- /dev/null +++ b/pcsx2/PAD/Linux/KeyStatus.h @@ -0,0 +1,80 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2011 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __KEYSTATUS_H__ +#define __KEYSTATUS_H__ + +#include "onepad.h" + +typedef struct +{ + u8 lx, ly; + u8 rx, ry; +} PADAnalog; + +#define MAX_ANALOG_VALUE 32766 + +class KeyStatus +{ +private: + const u8 m_analog_released_val; + + u16 m_button[GAMEPAD_NUMBER]; + u16 m_internal_button_kbd[GAMEPAD_NUMBER]; + u16 m_internal_button_joy[GAMEPAD_NUMBER]; + + u8 m_button_pressure[GAMEPAD_NUMBER][MAX_KEYS]; + u8 m_internal_button_pressure[GAMEPAD_NUMBER][MAX_KEYS]; + + bool m_state_acces[GAMEPAD_NUMBER]; + + PADAnalog m_analog[GAMEPAD_NUMBER]; + PADAnalog m_internal_analog_kbd[GAMEPAD_NUMBER]; + PADAnalog m_internal_analog_joy[GAMEPAD_NUMBER]; + + void analog_set(u32 pad, u32 index, u8 value); + bool analog_is_reversed(u32 pad, u32 index); + u8 analog_merge(u8 kbd, u8 joy); + +public: + KeyStatus() + : m_analog_released_val(0x7F) + { + Init(); + } + void Init(); + + void keyboard_state_acces(u32 pad) { m_state_acces[pad] = true; } + void joystick_state_acces(u32 pad) { m_state_acces[pad] = false; } + + void press(u32 pad, u32 index, s32 value = 0xFF); + void release(u32 pad, u32 index); + + u16 get(u32 pad); + u8 get(u32 pad, u32 index); + + + void commit_status(u32 pad); +}; + +extern KeyStatus g_key_status; + +#endif diff --git a/pcsx2/PAD/Linux/SDL/joystick.cpp b/pcsx2/PAD/Linux/SDL/joystick.cpp new file mode 100644 index 0000000000..0204e9ac1b --- /dev/null +++ b/pcsx2/PAD/Linux/SDL/joystick.cpp @@ -0,0 +1,290 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "joystick.h" +#include "resources.h" +#include // sigaction + +////////////////////////// +// Joystick definitions // +////////////////////////// + +// opens handles to all possible joysticks +void JoystickInfo::EnumerateJoysticks(std::vector> &vjoysticks) +{ + uint32_t flag = SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER; + + if ((SDL_WasInit(0) & flag) != flag) { + // Tell SDL to catch event even if the windows isn't focussed + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + + if (SDL_Init(flag) < 0) + return; + + // WTF! Give me back the control of my system + struct sigaction action = {}; + action.sa_handler = SIG_DFL; + sigaction(SIGINT, &action, nullptr); + sigaction(SIGTERM, &action, nullptr); + + SDL_JoystickEventState(SDL_QUERY); + SDL_GameControllerEventState(SDL_QUERY); + SDL_EventState(SDL_CONTROLLERDEVICEADDED, SDL_ENABLE); + SDL_EventState(SDL_CONTROLLERDEVICEREMOVED, SDL_ENABLE); + + { // Support as much Joystick as possible + GBytes *bytes = g_resource_lookup_data(onepad_res_get_resource(), "/onepad/res/game_controller_db.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, nullptr); + + size_t size = 0; + // SDL forget to add const for SDL_RWFromMem API... + void *data = const_cast(g_bytes_get_data(bytes, &size)); + + SDL_GameControllerAddMappingsFromRW(SDL_RWFromMem(data, size), 1); + + g_bytes_unref(bytes); + + // Add user mapping too + for (auto const &map : g_conf.sdl2_mapping) + SDL_GameControllerAddMapping(map.c_str()); + } + } + + vjoysticks.clear(); + + for (int i = 0; i < SDL_NumJoysticks(); ++i) { + vjoysticks.push_back(std::unique_ptr(new JoystickInfo(i))); + // Something goes wrong in the init, let's drop it + if (!vjoysticks.back()->IsProperlyInitialized()) + vjoysticks.pop_back(); + } +} + +void JoystickInfo::Rumble(unsigned type, unsigned pad) +{ + if (type >= m_effects_id.size()) + return; + + if (!(g_conf.pad_options[pad].forcefeedback)) + return; + + if (m_haptic == nullptr) + return; + + int id = m_effects_id[type]; + if (SDL_HapticRunEffect(m_haptic, id, 1) != 0) { + fprintf(stderr, "ERROR: Effect is not working! %s, id is %d\n", SDL_GetError(), id); + } +} + +JoystickInfo::~JoystickInfo() +{ + // Haptic must be closed before the joystick + if (m_haptic != nullptr) { + for (const auto &eid : m_effects_id) { + if (eid >= 0) + SDL_HapticDestroyEffect(m_haptic, eid); + } + + SDL_HapticClose(m_haptic); + } + + if (m_controller != nullptr) { +#if SDL_MINOR_VERSION >= 4 + // Version before 2.0.4 are bugged, JoystickClose crashes randomly + // Note: GameControllerClose calls JoystickClose) + SDL_GameControllerClose(m_controller); +#endif + } +} + +JoystickInfo::JoystickInfo(int id) + : GamePad() + , m_controller(nullptr) + , m_haptic(nullptr) + , m_unique_id(0) +{ + SDL_Joystick *joy = nullptr; + m_effects_id.fill(-1); + // Values are hardcoded currently but it could be later extended to allow remapping of the buttons + m_pad_to_sdl[PAD_L2] = SDL_CONTROLLER_AXIS_TRIGGERLEFT; + m_pad_to_sdl[PAD_R2] = SDL_CONTROLLER_AXIS_TRIGGERRIGHT; + m_pad_to_sdl[PAD_L1] = SDL_CONTROLLER_BUTTON_LEFTSHOULDER; + m_pad_to_sdl[PAD_R1] = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; + m_pad_to_sdl[PAD_TRIANGLE] = SDL_CONTROLLER_BUTTON_Y; + m_pad_to_sdl[PAD_CIRCLE] = SDL_CONTROLLER_BUTTON_B; + m_pad_to_sdl[PAD_CROSS] = SDL_CONTROLLER_BUTTON_A; + m_pad_to_sdl[PAD_SQUARE] = SDL_CONTROLLER_BUTTON_X; + m_pad_to_sdl[PAD_SELECT] = SDL_CONTROLLER_BUTTON_BACK; + m_pad_to_sdl[PAD_L3] = SDL_CONTROLLER_BUTTON_LEFTSTICK; + m_pad_to_sdl[PAD_R3] = SDL_CONTROLLER_BUTTON_RIGHTSTICK; + m_pad_to_sdl[PAD_START] = SDL_CONTROLLER_BUTTON_START; + m_pad_to_sdl[PAD_UP] = SDL_CONTROLLER_BUTTON_DPAD_UP; + m_pad_to_sdl[PAD_RIGHT] = SDL_CONTROLLER_BUTTON_DPAD_RIGHT; + m_pad_to_sdl[PAD_DOWN] = SDL_CONTROLLER_BUTTON_DPAD_DOWN; + m_pad_to_sdl[PAD_LEFT] = SDL_CONTROLLER_BUTTON_DPAD_LEFT; + m_pad_to_sdl[PAD_L_UP] = SDL_CONTROLLER_AXIS_LEFTY; + m_pad_to_sdl[PAD_L_RIGHT] = SDL_CONTROLLER_AXIS_LEFTX; + m_pad_to_sdl[PAD_L_DOWN] = SDL_CONTROLLER_AXIS_LEFTY; + m_pad_to_sdl[PAD_L_LEFT] = SDL_CONTROLLER_AXIS_LEFTX; + m_pad_to_sdl[PAD_R_UP] = SDL_CONTROLLER_AXIS_RIGHTY; + m_pad_to_sdl[PAD_R_RIGHT] = SDL_CONTROLLER_AXIS_RIGHTX; + m_pad_to_sdl[PAD_R_DOWN] = SDL_CONTROLLER_AXIS_RIGHTY; + m_pad_to_sdl[PAD_R_LEFT] = SDL_CONTROLLER_AXIS_RIGHTX; + + if (SDL_IsGameController(id)) { + m_controller = SDL_GameControllerOpen(id); + joy = SDL_GameControllerGetJoystick(m_controller); + } else { + joy = SDL_JoystickOpen(id); + } + + if (joy == nullptr) { + fprintf(stderr, "onepad:failed to open joystick %d\n", id); + return; + } + + // Collect Device Information + char guid[64]; + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joy), guid, 64); + const char *devname = SDL_JoystickNameForIndex(id); + + if (m_controller == nullptr) { + fprintf(stderr, "onepad: Joystick (%s,GUID:%s) isn't yet supported by the SDL2 game controller API\n" + "Fortunately you can use AntiMicro (https://github.com/AntiMicro/antimicro) or Steam to configure your joystick\n" + "The mapping can be stored in OnePAD2.ini as 'SDL2 = <...mapping description...>'\n" + "Please report it to us (https://github.com/PCSX2/pcsx2/issues) so we can add your joystick to our internal database.", + devname, guid); + +#if SDL_MINOR_VERSION >= 4 // Version before 2.0.4 are bugged, JoystickClose crashes randomly + SDL_JoystickClose(joy); +#endif + + return; + } + + std::hash hash_me; + m_unique_id = hash_me(std::string(guid)); + + // Default haptic effect + SDL_HapticEffect effects[NB_EFFECT]; + for (int i = 0; i < NB_EFFECT; i++) { + SDL_HapticEffect effect; + memset(&effect, 0, sizeof(SDL_HapticEffect)); // 0 is safe default + SDL_HapticDirection direction; + direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding. + direction.dir[0] = 18000; + effect.periodic.direction = direction; + effect.periodic.period = 10; + effect.periodic.magnitude = (Sint16)(g_conf.get_ff_intensity()); // Effect at maximum instensity + effect.periodic.offset = 0; + effect.periodic.phase = 18000; + effect.periodic.length = 125; // 125ms feels quite near to original + effect.periodic.delay = 0; + effect.periodic.attack_length = 0; + /* Sine and triangle are quite probably the best, don't change that lightly and if you do + * keep effects ordered by type + */ + if (i == 0) { + /* Effect for small motor */ + /* Sine seems to be the only effect making little motor from DS3/4 react + * Intensity has pretty much no effect either(which is coherent with what is explain in hid_sony driver + */ + effect.type = SDL_HAPTIC_SINE; + } else { + /** Effect for big motor **/ + effect.type = SDL_HAPTIC_TRIANGLE; + } + + effects[i] = effect; + } + + if (SDL_JoystickIsHaptic(joy)) { + m_haptic = SDL_HapticOpenFromJoystick(joy); + + for (auto &eid : m_effects_id) { + eid = SDL_HapticNewEffect(m_haptic, &effects[0]); + if (eid < 0) { + fprintf(stderr, "ERROR: Effect is not uploaded! %s\n", SDL_GetError()); + m_haptic = nullptr; + break; + } + } + } + + fprintf(stdout, "onepad: controller (%s) detected%s, GUID:%s\n", + devname, m_haptic ? " with rumble support" : "", guid); + + m_no_error = true; +} + +const char *JoystickInfo::GetName() +{ + return SDL_JoystickName(SDL_GameControllerGetJoystick(m_controller)); +} + +size_t JoystickInfo::GetUniqueIdentifier() +{ + return m_unique_id; +} + +bool JoystickInfo::TestForce(float strength = 0.60) +{ + // This code just use standard rumble to check that SDL handles the pad correctly! --3kinox + if (m_haptic == nullptr) + return false; // Otherwise, core dump! + + SDL_HapticRumbleInit(m_haptic); + + // Make the haptic pad rumble 60% strength for half a second, shoudld be enough for user to see if it works or not + if (SDL_HapticRumblePlay(m_haptic, strength, 400) != 0) { + fprintf(stderr, "ERROR: Rumble is not working! %s\n", SDL_GetError()); + return false; + } + + return true; +} + +int JoystickInfo::GetInput(gamePadValues input) +{ + float k = g_conf.get_sensibility() / 100.0; // convert sensibility to float + + // Handle analog inputs which range from -32k to +32k. Range conversion is handled later in the controller + if (IsAnalogKey(input)) { + int value = SDL_GameControllerGetAxis(m_controller, (SDL_GameControllerAxis)m_pad_to_sdl[input]); + value *= k; + return (abs(value) > m_deadzone) ? value : 0; + } + + // Handle triggers which range from 0 to +32k. They must be converted to 0-255 range + if (input == PAD_L2 || input == PAD_R2) { + int value = SDL_GameControllerGetAxis(m_controller, (SDL_GameControllerAxis)m_pad_to_sdl[input]); + return (value > m_deadzone) ? value / 128 : 0; + } + + // Remain buttons + int value = SDL_GameControllerGetButton(m_controller, (SDL_GameControllerButton)m_pad_to_sdl[input]); + return value ? 0xFF : 0; // Max pressure +} + +void JoystickInfo::UpdateGamePadState() +{ + SDL_GameControllerUpdate(); +} diff --git a/pcsx2/PAD/Linux/SDL/joystick.h b/pcsx2/PAD/Linux/SDL/joystick.h new file mode 100644 index 0000000000..d10dba6d69 --- /dev/null +++ b/pcsx2/PAD/Linux/SDL/joystick.h @@ -0,0 +1,63 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +#include "GamePad.h" +#include "onepad.h" +#include "controller.h" +#define NB_EFFECT 2 // Don't use more than two, ps2 only has one for big motor and one for small(like most systems) +// holds all joystick info +class JoystickInfo : public GamePad +{ +public: + JoystickInfo(int id); + ~JoystickInfo(); + + JoystickInfo(const JoystickInfo &) = delete; // copy constructor + JoystickInfo &operator=(const JoystickInfo &) = delete; // assignment + + + // opens handles to all possible joysticks + static void EnumerateJoysticks(std::vector> &vjoysticks); + + void Rumble(unsigned type, unsigned pad) override; + + bool TestForce(float) override; + + const char *GetName() final; + + int GetInput(gamePadValues input) final; + + void UpdateGamePadState() final; + + size_t GetUniqueIdentifier() final; + +private: + SDL_GameController *m_controller; + SDL_Haptic *m_haptic; + std::array m_effects_id; + size_t m_unique_id; + std::array m_pad_to_sdl; +}; diff --git a/pcsx2/PAD/Linux/bitwise.h b/pcsx2/PAD/Linux/bitwise.h new file mode 100644 index 0000000000..bb4a2751bc --- /dev/null +++ b/pcsx2/PAD/Linux/bitwise.h @@ -0,0 +1,44 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +template +static void __forceinline set_bit(T &value, int bit) +{ + value |= (1 << bit); +} + +template +static void __forceinline clear_bit(T &value, int bit) +{ + value &= ~(1 << bit); +} + +template +static void __forceinline toggle_bit(T &value, int bit) +{ + value ^= (1 << bit); +} + +template +static bool __forceinline test_bit(T &value, int bit) +{ + return (value & (1 << bit)); +} diff --git a/pcsx2/PAD/Linux/controller.cpp b/pcsx2/PAD/Linux/controller.cpp new file mode 100644 index 0000000000..339ca823d1 --- /dev/null +++ b/pcsx2/PAD/Linux/controller.cpp @@ -0,0 +1,44 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "onepad.h" +#include "controller.h" + +__forceinline void set_keyboard_key(int pad, int keysym, int index) +{ + g_conf.keysym_map[pad][keysym] = index; +} + +__forceinline int get_keyboard_key(int pad, int keysym) +{ + // You must use find instead of [] + // [] will create an element if the key does not exist and return 0 + std::map::iterator it = g_conf.keysym_map[pad].find(keysym); + if (it != g_conf.keysym_map[pad].end()) + return it->second; + else + return -1; +} + +__forceinline bool IsAnalogKey(int index) +{ + return ((index >= PAD_L_UP) && (index <= PAD_R_LEFT)); +} diff --git a/pcsx2/PAD/Linux/controller.h b/pcsx2/PAD/Linux/controller.h new file mode 100644 index 0000000000..c0710c9ca9 --- /dev/null +++ b/pcsx2/PAD/Linux/controller.h @@ -0,0 +1,129 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once +#include // for memset +#define MAX_KEYS 24 + +extern void set_keyboard_key(int pad, int keysym, int index); +extern int get_keyboard_key(int pad, int keysym); +extern bool IsAnalogKey(int index); + +class PADconf +{ + u32 ff_intensity; + u32 sensibility; + +public: + union + { + struct + { + u16 forcefeedback : 1; + u16 reverse_lx : 1; + u16 reverse_ly : 1; + u16 reverse_rx : 1; + u16 reverse_ry : 1; + u16 mouse_l : 1; + u16 mouse_r : 1; + u16 _free : 9; // The 9 remaining bits are unused, do what you wish with them ;) + } pad_options[GAMEPAD_NUMBER]; // One for each pads + u32 packed_options; // Only first 8 bits of each 16 bits series are really used, rest is padding + }; + + u32 log; + u32 ftw; + std::map keysym_map[GAMEPAD_NUMBER]; + std::array unique_id; + std::vector sdl2_mapping; + + PADconf() { init(); } + + void init() + { + log = 0; + ftw = 1; + packed_options = 0; + ff_intensity = 0x7FFF; // set it at max value by default + sensibility = 100; + for (int pad = 0; pad < GAMEPAD_NUMBER; pad++) { + keysym_map[pad].clear(); + } + unique_id.fill(0); + sdl2_mapping.clear(); + } + + void set_joy_uid(u32 pad, size_t uid) + { + if (pad < GAMEPAD_NUMBER) + unique_id[pad] = uid; + } + + size_t get_joy_uid(u32 pad) + { + if (pad < GAMEPAD_NUMBER) + return unique_id[pad]; + else + return 0; + } + + /** + * Return (a copy of) private memner ff_instensity + **/ + u32 get_ff_intensity() + { + return ff_intensity; + } + + /** + * Set intensity while checking that the new value is within + * valid range, more than 0x7FFF will cause pad not to rumble(and less than 0 is obviously bad) + **/ + void set_ff_intensity(u32 new_intensity) + { + if (new_intensity <= 0x7FFF) { + ff_intensity = new_intensity; + } + } + + /** + * Set sensibility value. + * There will be an upper range, and less than 0 is obviously wrong. + * We are doing object oriented code, so members are definitely not supposed to be public. + **/ + void set_sensibility(u32 new_sensibility) + { + if (new_sensibility > 0) + { + sensibility = new_sensibility; + } + else + { + sensibility = 1; + } + } + + u32 get_sensibility() + { + return sensibility; + } +}; +extern PADconf g_conf; diff --git a/pcsx2/PAD/Linux/ini.cpp b/pcsx2/PAD/Linux/ini.cpp new file mode 100644 index 0000000000..41f27addca --- /dev/null +++ b/pcsx2/PAD/Linux/ini.cpp @@ -0,0 +1,132 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "GamePad.h" +#include "keyboard.h" +#include "onepad.h" + +extern std::string s_strIniPath; + +void DefaultKeyboardValues() +{ + set_keyboard_key(0, XK_a, PAD_L2); + set_keyboard_key(0, XK_semicolon, PAD_R2); + set_keyboard_key(0, XK_w, PAD_L1); + set_keyboard_key(0, XK_p, PAD_R1); + set_keyboard_key(0, XK_i, PAD_TRIANGLE); + set_keyboard_key(0, XK_l, PAD_CIRCLE); + set_keyboard_key(0, XK_k, PAD_CROSS); + set_keyboard_key(0, XK_j, PAD_SQUARE); + set_keyboard_key(0, XK_v, PAD_SELECT); + set_keyboard_key(0, XK_n, PAD_START); + set_keyboard_key(0, XK_e, PAD_UP); + set_keyboard_key(0, XK_f, PAD_RIGHT); + set_keyboard_key(0, XK_d, PAD_DOWN); + set_keyboard_key(0, XK_s, PAD_LEFT); +} + +void SaveConfig() +{ + FILE *f; + + const std::string iniFile(s_strIniPath + "OnePAD2.ini"); + f = fopen(iniFile.c_str(), "w"); + if (f == NULL) { + printf("OnePAD: failed to save ini %s\n", iniFile.c_str()); + return; + } + + fprintf(f, "first_time_wizard = %d\n", g_conf.ftw); + fprintf(f, "log = %d\n", g_conf.log); + fprintf(f, "options = %d\n", g_conf.packed_options); + fprintf(f, "mouse_sensibility = %d\n", g_conf.get_sensibility()); + fprintf(f, "ff_intensity = %d\n", g_conf.get_ff_intensity()); + fprintf(f, "uid[0] = %zu\n", g_conf.get_joy_uid(0)); + fprintf(f, "uid[1] = %zu\n", g_conf.get_joy_uid(1)); + + for (int pad = 0; pad < GAMEPAD_NUMBER; pad++) + for (auto const &it : g_conf.keysym_map[pad]) + fprintf(f, "PAD %d:KEYSYM 0x%x = %d\n", pad, it.first, it.second); + + for (auto const &it : g_conf.sdl2_mapping) + fprintf(f, "SDL2 = %s\n", it.c_str()); + + fclose(f); +} + +void LoadConfig() +{ + FILE *f; + bool have_user_setting = false; + + g_conf.init(); + + const std::string iniFile(s_strIniPath + "OnePAD2.ini"); + f = fopen(iniFile.c_str(), "r"); + if (f == NULL) { + printf("OnePAD: failed to load ini %s\n", iniFile.c_str()); + SaveConfig(); //save and return + return; + } + + u32 value; + + if (fscanf(f, "first_time_wizard = %u\n", &value) == 1) + g_conf.ftw = value; + + if (fscanf(f, "log = %u\n", &value) == 1) + g_conf.log = value; + + if (fscanf(f, "options = %u\n", &value) == 1) + g_conf.packed_options = value; + + if (fscanf(f, "mouse_sensibility = %u\n", &value) == 1) + g_conf.set_sensibility(value); + + if (fscanf(f, "ff_intensity = %u\n", &value) == 1) + g_conf.set_ff_intensity(value); + + size_t uid; + if (fscanf(f, "uid[0] = %zu\n", &uid) == 1) + g_conf.set_joy_uid(0, uid); + if (fscanf(f, "uid[1] = %zu\n", &uid) == 1) + g_conf.set_joy_uid(1, uid); + + u32 pad; + u32 keysym; + u32 index; + while (fscanf(f, "PAD %u:KEYSYM 0x%x = %u\n", &pad, &keysym, &index) == 3) { + set_keyboard_key(pad & 1, keysym, index); + if (pad == 0) + have_user_setting = true; + } + + char sdl2[512]; + while (fscanf(f, "SDL2 = %511[^\n]\n", sdl2) == 1) + g_conf.sdl2_mapping.push_back(std::string(sdl2)); + + if (!have_user_setting) + DefaultKeyboardValues(); + + fclose(f); +} diff --git a/pcsx2/PAD/Linux/keyboard.cpp b/pcsx2/PAD/Linux/keyboard.cpp new file mode 100644 index 0000000000..81c962b969 --- /dev/null +++ b/pcsx2/PAD/Linux/keyboard.cpp @@ -0,0 +1,359 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Theoretically, this header is for anything to do with keyboard input. + * Pragmatically, event handing's going in here too. + */ + +#if defined(__unix__) +#include +#include +#elif defined(__APPLE__) +#include +#endif + +#include "keyboard.h" + +#ifdef _WIN32 +char *KeysymToChar(int keysym) +{ + LPWORD temp; + + ToAscii((UINT)keysym, NULL, NULL, temp, NULL); + return (char *)temp; +} +#endif + +/// g_key_status.press but with proper handling for analog buttons +static void PressButton(u32 pad, u32 button) { + // Analog controls. + if (IsAnalogKey(button)) { + switch (button) { + case PAD_R_LEFT: + case PAD_R_UP: + case PAD_L_LEFT: + case PAD_L_UP: + g_key_status.press(pad, button, -MAX_ANALOG_VALUE); + break; + case PAD_R_RIGHT: + case PAD_R_DOWN: + case PAD_L_RIGHT: + case PAD_L_DOWN: + g_key_status.press(pad, button, MAX_ANALOG_VALUE); + break; + } + } else { + g_key_status.press(pad, button); + } +} + +#if defined(__APPLE__) +// Mac keyboard input code is based on Dolphin's Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ + +// All keycodes are 16 bits or less, so we use top 16 bits to differentiate source +// Keyboard keys use discriminator 0 +// Mouse buttons use discriminator 1 + +void UpdateKeyboardInput() { + for (int pad = 0; pad < GAMEPAD_NUMBER; pad++) { + const auto& map = g_conf.keysym_map[pad]; + // If we loop over all keys press/release based on current state, + // joystick axes (which have two bound keys) will always go to the later-polled key + // Instead, release all keys first and then set the ones that are pressed + for (const auto& key : map) g_key_status.release(pad, key.second); + for (const auto& key : map) { + bool state; + if (key.first >> 16 == 0) { + state = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, key.first); + } else { + state = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, (CGMouseButton)(key.first & 0xFFFF)); + } + if (state) PressButton(pad, key.second); + } + } +} + +bool PollForNewKeyboardKeys(u32 &pkey) { + // All keycodes in are 0x7e or lower. If you notice + // keys that aren't being recognized, bump this number up! + for (int key = 0; key < 0x80; key++) { + if (CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, key)) { + pkey = key == kVK_Escape ? 0 : key; + return true; + } + } + for (auto btn : {kCGMouseButtonLeft, kCGMouseButtonCenter, kCGMouseButtonRight}) { + if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, btn)) { + pkey = btn | (1 << 16); + return true; + } + } + return false; +} +#elif defined(__unix__) +static bool s_grab_input = false; +static bool s_Shift = false; +static unsigned int s_previous_mouse_x = 0; +static unsigned int s_previous_mouse_y = 0; + +void AnalyzeKeyEvent(keyEvent &evt) +{ + KeySym key = (KeySym)evt.key; + int pad = 0; + int index = -1; + + for (int cpad = 0; cpad < GAMEPAD_NUMBER; cpad++) { + int tmp_index = get_keyboard_key(cpad, key); + if (tmp_index != -1) { + pad = cpad; + index = tmp_index; + } + } + + switch (evt.evt) { + case KeyPress: + // Shift F12 is not yet use by pcsx2. So keep it to grab/ungrab input + // I found it very handy vs the automatic fullscreen detection + // 1/ Does not need to detect full-screen + // 2/ Can use a debugger in full-screen + // 3/ Can grab input in window without the need of a pixelated full-screen + if (key == XK_Shift_R || key == XK_Shift_L) + s_Shift = true; + if (key == XK_F12 && s_Shift) { + if (!s_grab_input) { + s_grab_input = true; + XGrabPointer(GSdsp, GSwin, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, GSwin, None, CurrentTime); + XGrabKeyboard(GSdsp, GSwin, True, GrabModeAsync, GrabModeAsync, CurrentTime); + } else { + s_grab_input = false; + XUngrabPointer(GSdsp, CurrentTime); + XUngrabKeyboard(GSdsp, CurrentTime); + } + } + + if (index != -1) + PressButton(pad, index); + + //PAD_LOG("Key pressed:%d\n", index); + + event.evt = KEYPRESS; + event.key = key; + break; + + case KeyRelease: + if (key == XK_Shift_R || key == XK_Shift_L) + s_Shift = false; + + if (index != -1) + g_key_status.release(pad, index); + + event.evt = KEYRELEASE; + event.key = key; + break; + + case FocusIn: + break; + + case FocusOut: + s_Shift = false; + break; + + case ButtonPress: + if (index != -1) + g_key_status.press(pad, index); + break; + + case ButtonRelease: + if (index != -1) + g_key_status.release(pad, index); + break; + + case MotionNotify: + // FIXME: How to handle when the mouse does not move, no event generated!!! + // 1/ small move == no move. Cons : can not do small movement + // 2/ use a watchdog timer thread + // 3/ ??? idea welcome ;) + if (g_conf.pad_options[pad].mouse_l | g_conf.pad_options[pad].mouse_r) { + unsigned int pad_x; + unsigned int pad_y; + // Note when both PADOPTION_MOUSE_R and PADOPTION_MOUSE_L are set, take only the right one + if (g_conf.pad_options[pad].mouse_r) { + pad_x = PAD_R_RIGHT; + pad_y = PAD_R_UP; + } else { + pad_x = PAD_L_RIGHT; + pad_y = PAD_L_UP; + } + + unsigned x = evt.key & 0xFFFF; + unsigned int value = (s_previous_mouse_x > x) ? s_previous_mouse_x - x : x - s_previous_mouse_x; + value *= g_conf.get_sensibility(); + + if (x == 0) + g_key_status.press(pad, pad_x, -MAX_ANALOG_VALUE); + else if (x == 0xFFFF) + g_key_status.press(pad, pad_x, MAX_ANALOG_VALUE); + else if (x < (s_previous_mouse_x - 2)) + g_key_status.press(pad, pad_x, -value); + else if (x > (s_previous_mouse_x + 2)) + g_key_status.press(pad, pad_x, value); + else + g_key_status.release(pad, pad_x); + + + unsigned y = evt.key >> 16; + value = (s_previous_mouse_y > y) ? s_previous_mouse_y - y : y - s_previous_mouse_y; + value *= g_conf.get_sensibility(); + + if (y == 0) + g_key_status.press(pad, pad_y, -MAX_ANALOG_VALUE); + else if (y == 0xFFFF) + g_key_status.press(pad, pad_y, MAX_ANALOG_VALUE); + else if (y < (s_previous_mouse_y - 2)) + g_key_status.press(pad, pad_y, -value); + else if (y > (s_previous_mouse_y + 2)) + g_key_status.press(pad, pad_y, value); + else + g_key_status.release(pad, pad_y); + + s_previous_mouse_x = x; + s_previous_mouse_y = y; + } + + break; + } +} + +void UpdateKeyboardInput() +{ + keyEvent evt = {0}; + XEvent E = {0}; + + // Keyboard input send by PCSX2 + g_ev_fifo.consume_all(AnalyzeKeyEvent); + + // keyboard input + while (XPending(GSdsp) > 0) { + XNextEvent(GSdsp, &E); + + // Change the format of the structure to be compatible with GSOpen2 + // mode (event come from pcsx2 not X) + evt.evt = E.type; + switch (E.type) { + case MotionNotify: + evt.key = (E.xbutton.x & 0xFFFF) | (E.xbutton.y << 16); + break; + case ButtonRelease: + case ButtonPress: + evt.key = E.xbutton.button; + break; + default: + evt.key = (int)XLookupKeysym(&E.xkey, 0); + } + + AnalyzeKeyEvent(evt); + } +} + +bool PollForNewKeyboardKeys(u32 &pkey) +{ + GdkEvent *ev = gdk_event_get(); + + if (ev != NULL) { + if (ev->type == GDK_KEY_PRESS) { + pkey = ev->key.keyval != GDK_KEY_Escape ? ev->key.keyval : 0; + return true; + } else if (ev->type == GDK_BUTTON_PRESS) { + pkey = ev->button.button; + return true; + } + } + + return false; +} + +#else +LRESULT WINAPI PADwndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static bool lbutton = false, rbutton = false; + for (int pad = 0; pad < GAMEPAD_NUMBER; ++pad) + { + g_key_status.keyboard_state_acces(pad); + } + + switch (msg) { + case WM_KEYDOWN: + if (lParam & 0x40000000) + return TRUE; + + for (int pad = 0; pad < GAMEPAD_NUMBER; ++pad) { + for (int i = 0; i < MAX_KEYS; i++) { + assert(0); +#if 0 + if (wParam == get_key(pad, i)) { + g_key_status.press(pad, i); + break; + } +#endif + } + } + + event.evt = KEYPRESS; + event.key = wParam; + break; + + case WM_KEYUP: + for (int pad = 0; pad < GAMEPAD_NUMBER; ++pad) { + for (int i = 0; i < MAX_KEYS; i++) { + assert(0); +#if 0 + if (wParam == get_key(pad, i)) { + g_key_status.release(pad, i); + break; + } +#endif + } + } + + + event.evt = KEYRELEASE; + event.key = wParam; + break; + + case WM_DESTROY: + case WM_QUIT: + event.evt = KEYPRESS; + event.key = VK_ESCAPE; + return GSwndProc(hWnd, msg, wParam, lParam); + + default: + return GSwndProc(hWnd, msg, wParam, lParam); + } + + for (int pad = 0; pad < GAMEPAD_NUMBER; ++pad) + g_key_status.commit_status(pad); + + return TRUE; +} +#endif diff --git a/pcsx2/PAD/Linux/keyboard.h b/pcsx2/PAD/Linux/keyboard.h new file mode 100644 index 0000000000..3a4d4a7f77 --- /dev/null +++ b/pcsx2/PAD/Linux/keyboard.h @@ -0,0 +1,45 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __KEYBOARD_H__ +#define __KEYBOARD_H__ + +#include "onepad.h" + +#if defined(__unix__) || defined(__APPLE__) + +extern void AnalyzeKeyEvent(keyEvent &evt); +extern void UpdateKeyboardInput(); +extern bool PollForNewKeyboardKeys(u32 &pkey); +#ifndef __APPLE__ +extern Display *GSdsp; +extern Window GSwin; +#endif + +#else + +extern char *KeysymToChar(int keysym); +extern WNDPROC GSwndProc; +extern HWND GShwnd; + +#endif + +#endif diff --git a/pcsx2/PAD/Linux/linux.cpp b/pcsx2/PAD/Linux/linux.cpp new file mode 100644 index 0000000000..8390212ce9 --- /dev/null +++ b/pcsx2/PAD/Linux/linux.cpp @@ -0,0 +1,141 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GamePad.h" +#include "onepad.h" +#include "keyboard.h" +#include "state_management.h" + +#include +#include "wx_dialog/dialog.h" + +#ifndef __APPLE__ +Display *GSdsp; +Window GSwin; +#endif + +static void SysMessage(const char *fmt, ...) +{ + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg) - 1] == '\n') + msg[strlen(msg) - 1] = 0; + + wxMessageDialog dialog(nullptr, msg, "Info", wxOK); + dialog.ShowModal(); +} + +EXPORT_C_(void) +PADabout() +{ + SysMessage("OnePad is a rewrite of Zerofrog's ZeroPad, done by arcum42."); +} + +EXPORT_C_(s32) +PADtest() +{ + return 0; +} + +s32 _PADopen(void *pDsp) +{ +#ifndef __APPLE__ + GSdsp = *(Display **)pDsp; + GSwin = (Window) * (((u32 *)pDsp) + 1); +#endif + + return 0; +} + +void _PADclose() +{ + s_vgamePad.clear(); +} + +void PollForJoystickInput(int cpad) +{ + int index = GamePad::uid_to_index(cpad); + if (index < 0) + return; + + auto &gamePad = s_vgamePad[index]; + + gamePad->UpdateGamePadState(); + + for (int i = 0; i < MAX_KEYS; i++) { + s32 value = gamePad->GetInput((gamePadValues)i); + if (value != 0) + g_key_status.press(cpad, i, value); + else + g_key_status.release(cpad, i); + } +} + +EXPORT_C_(void) +PADupdate(int pad) +{ +#ifndef __APPLE__ + // Gamepad inputs don't count as an activity. Therefore screensaver will + // be fired after a couple of minute. + // Emulate an user activity + static int count = 0; + count++; + if ((count & 0xFFF) == 0) { + // 1 call every 4096 Vsync is enough + XResetScreenSaver(GSdsp); + } +#endif + + // Actually PADupdate is always call with pad == 0. So you need to update both + // pads -- Gregory + + // Poll keyboard/mouse event. There is currently no way to separate pad0 from pad1 event. + // So we will populate both pad in the same time + for (int cpad = 0; cpad < GAMEPAD_NUMBER; cpad++) { + g_key_status.keyboard_state_acces(cpad); + } + UpdateKeyboardInput(); + + // Get joystick state + Commit + for (int cpad = 0; cpad < GAMEPAD_NUMBER; cpad++) { + g_key_status.joystick_state_acces(cpad); + + PollForJoystickInput(cpad); + + g_key_status.commit_status(cpad); + } + + Pad::rumble_all(); +} + +EXPORT_C_(void) +PADconfigure() +{ + LoadConfig(); + + DisplayDialog(); + return; +} diff --git a/pcsx2/PAD/Linux/onepad.cpp b/pcsx2/PAD/Linux/onepad.cpp new file mode 100644 index 0000000000..3375472808 --- /dev/null +++ b/pcsx2/PAD/Linux/onepad.cpp @@ -0,0 +1,358 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include + +#include "keyboard.h" +#include "onepad.h" +#include "svnrev.h" +#include "state_management.h" + +#ifdef __linux__ +#include +#endif +#ifdef _MSC_VER +#define snprintf sprintf_s +#endif + +PADconf g_conf; +static char libraryName[256]; + +keyEvent event; + +static keyEvent s_event; +std::string s_strIniPath("inis/"); +std::string s_strLogPath("logs/"); + +const u32 version = PS2E_PAD_VERSION; +const u32 revision = 2; +const u32 build = 0; // increase that with each version +#define PAD_SAVE_STATE_VERSION ((revision << 8) | (build << 0)) + +FILE *padLog = NULL; + +KeyStatus g_key_status; + +MtQueue g_ev_fifo; + +static void InitLibraryName() +{ +#ifdef PUBLIC + + // Public Release! + // Output a simplified string that's just our name: + + strcpy(libraryName, "OnePAD"); + +#else + + // Use TortoiseSVN's SubWCRev utility's output + // to label the specific revision: + + snprintf(libraryName, 255, "OnePAD %lld%s" +#ifdef PCSX2_DEBUG + "-Debug" +#elif defined(PCSX2_DEVBUILD) + "-Dev" +#endif + , + SVN_REV, + SVN_MODS ? "m" : ""); +#endif +} + +EXPORT_C_(u32) +PS2EgetLibType() +{ + return PS2E_LT_PAD; +} + +EXPORT_C_(const char *) +PS2EgetLibName() +{ + InitLibraryName(); + return libraryName; +} + +EXPORT_C_(u32) +PS2EgetLibVersion2(u32 type) +{ + return (version << 16) | (revision << 8) | build; +} + +void __Log(const char *fmt, ...) +{ + va_list list; + + if (padLog == NULL) + return; + va_start(list, fmt); + vfprintf(padLog, fmt, list); + va_end(list); +} + +void __LogToConsole(const char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + + if (padLog != NULL) + vfprintf(padLog, fmt, list); + + printf("OnePAD: "); + vprintf(fmt, list); + va_end(list); +} + +void initLogging() +{ +#ifdef PAD_LOG + if (padLog) + return; + + const std::string LogFile(s_strLogPath + "padLog.txt"); + padLog = fopen(LogFile.c_str(), "w"); + + if (padLog) + setvbuf(padLog, NULL, _IONBF, 0); + + PAD_LOG("PADinit\n"); +#endif +} + +void CloseLogging() +{ +#ifdef PAD_LOG + if (padLog) { + fclose(padLog); + padLog = NULL; + } +#endif +} + +EXPORT_C_(s32) +PADinit(u32 flags) +{ + initLogging(); + + LoadConfig(); + + Pad::reset_all(); + + query.reset(); + + for (int port = 0; port < 2; port++) + slots[port] = 0; + + return 0; +} + +EXPORT_C_(void) +PADshutdown() +{ + CloseLogging(); +} + +EXPORT_C_(s32) +PADopen(void *pDsp) +{ + memset(&event, 0, sizeof(event)); + g_key_status.Init(); + + g_ev_fifo.reset(); + +#if defined(__unix__) || defined(__APPLE__) + GamePad::EnumerateGamePads(s_vgamePad); +#endif + return _PADopen(pDsp); +} + +EXPORT_C_(void) +PADsetSettingsDir(const char *dir) +{ + // Get the path to the ini directory. + s_strIniPath = (dir == NULL) ? "inis/" : dir; +} + +EXPORT_C_(void) +PADsetLogDir(const char *dir) +{ + // Get the path to the log directory. + s_strLogPath = (dir == NULL) ? "logs/" : dir; + + // Reload the log file after updated the path + CloseLogging(); + initLogging(); +} + +EXPORT_C_(void) +PADclose() +{ + _PADclose(); +} + +EXPORT_C_(u32) +PADquery() +{ + return 3; // both +} + +EXPORT_C_(s32) +PADsetSlot(u8 port, u8 slot) +{ + port--; + slot--; + if (port > 1 || slot > 3) { + return 0; + } + // Even if no pad there, record the slot, as it is the active slot regardless. + slots[port] = slot; + + return 1; +} + +EXPORT_C_(s32) +PADfreeze(int mode, freezeData *data) +{ + if (!data) + return -1; + + if (mode == FREEZE_SIZE) { + data->size = sizeof(PadPluginFreezeData); + + } else if (mode == FREEZE_LOAD) { + PadPluginFreezeData *pdata = (PadPluginFreezeData *)(data->data); + + Pad::stop_vibrate_all(); + + if (data->size != sizeof(PadPluginFreezeData) || pdata->version != PAD_SAVE_STATE_VERSION || + strncmp(pdata->format, "OnePad", sizeof(pdata->format))) + return 0; + + query = pdata->query; + if (pdata->query.slot < 4) { + query = pdata->query; + } + + // Tales of the Abyss - pad fix + // - restore data for both ports + for (int port = 0; port < 2; port++) { + for (int slot = 0; slot < 4; slot++) { + u8 mode = pdata->padData[port][slot].mode; + + if (mode != MODE_DIGITAL && mode != MODE_ANALOG && mode != MODE_DS2_NATIVE) { + break; + } + + memcpy(&pads[port][slot], &pdata->padData[port][slot], sizeof(PadFreezeData)); + } + + if (pdata->slot[port] < 4) + slots[port] = pdata->slot[port]; + } + + } else if (mode == FREEZE_SAVE) { + if (data->size != sizeof(PadPluginFreezeData)) + return 0; + + PadPluginFreezeData *pdata = (PadPluginFreezeData *)(data->data); + + // Tales of the Abyss - pad fix + // - PCSX2 only saves port0 (save #1), then port1 (save #2) + + memset(pdata, 0, data->size); + strncpy(pdata->format, "OnePad", sizeof(pdata->format)); + pdata->version = PAD_SAVE_STATE_VERSION; + pdata->query = query; + + for (int port = 0; port < 2; port++) { + for (int slot = 0; slot < 4; slot++) { + pdata->padData[port][slot] = pads[port][slot]; + } + + pdata->slot[port] = slots[port]; + } + + } else { + return -1; + } + + return 0; +} + +EXPORT_C_(u8) +PADstartPoll(int pad) +{ + return pad_start_poll(pad); +} + +EXPORT_C_(u8) +PADpoll(u8 value) +{ + return pad_poll(value); +} + +// PADkeyEvent is called every vsync (return NULL if no event) +EXPORT_C_(keyEvent *) +PADkeyEvent() +{ +#ifdef SDL_BUILD + // Take the opportunity to handle hot plugging here + SDL_Event events; + while (SDL_PollEvent(&events)) { + switch (events.type) { + case SDL_CONTROLLERDEVICEADDED: + case SDL_CONTROLLERDEVICEREMOVED: + GamePad::EnumerateGamePads(s_vgamePad); + break; + default: + break; + } + } +#endif + if (g_ev_fifo.size() == 0) { + // PAD_LOG("No events in queue, returning empty event\n"); + s_event = event; + event.evt = 0; + event.key = 0; + return &s_event; + } + s_event = g_ev_fifo.dequeue(); + AnalyzeKeyEvent(s_event); + // PAD_LOG("Returning Event. Event Type: %d, Key: %d\n", s_event.evt, s_event.key); + return &s_event; +} + +#if defined(__unix__) +EXPORT_C_(void) +PADWriteEvent(keyEvent &evt) +{ + // if (evt.evt != 6) { // Skip mouse move events for logging + // PAD_LOG("Pushing Event. Event Type: %d, Key: %d\n", evt.evt, evt.key); + // } + g_ev_fifo.push(evt); +} +#endif diff --git a/pcsx2/PAD/Linux/onepad.h b/pcsx2/PAD/Linux/onepad.h new file mode 100644 index 0000000000..b20abd5290 --- /dev/null +++ b/pcsx2/PAD/Linux/onepad.h @@ -0,0 +1,138 @@ +/* OnePAD - author: arcum42(@gmail.com) + * Copyright (C) 2009 + * + * Based on ZeroPAD, author zerofrog@gmail.com + * Copyright (C) 2006-2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __PAD_H__ +#define __PAD_H__ + +#define GAMEPAD_NUMBER 2 // numbers of gamepad + +#include +#include + +#ifdef _WIN32 +#include +#include + +#else + +#include +#include +#include + +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define PADdefs +#include "PS2Edefs.h" + +enum PadOptions { + PADOPTION_FORCEFEEDBACK = 0x1, + PADOPTION_REVERSELX = 0x2, + PADOPTION_REVERSELY = 0x4, + PADOPTION_REVERSERX = 0x8, + PADOPTION_REVERSERY = 0x10, + PADOPTION_MOUSE_L = 0x20, + PADOPTION_MOUSE_R = 0x40, +}; + +enum PadCommands { + CMD_SET_VREF_PARAM = 0x40, + CMD_QUERY_DS2_ANALOG_MODE = 0x41, + CMD_READ_DATA_AND_VIBRATE = 0x42, + CMD_CONFIG_MODE = 0x43, + CMD_SET_MODE_AND_LOCK = 0x44, + CMD_QUERY_MODEL_AND_MODE = 0x45, + CMD_QUERY_ACT = 0x46, // ?? + CMD_QUERY_COMB = 0x47, // ?? + CMD_QUERY_MODE = 0x4C, // QUERY_MODE ?? + CMD_VIBRATION_TOGGLE = 0x4D, + CMD_SET_DS2_NATIVE_MODE = 0x4F // SET_DS2_NATIVE_MODE +}; + +enum gamePadValues { + PAD_L2 = 0, // L2 button + PAD_R2, // R2 button + PAD_L1, // L1 button + PAD_R1, // R1 button + PAD_TRIANGLE, // Triangle button ▲ + PAD_CIRCLE, // Circle button ● + PAD_CROSS, // Cross button ✖ + PAD_SQUARE, // Square button ■ + PAD_SELECT, // Select button + PAD_L3, // Left joystick button (L3) + PAD_R3, // Right joystick button (R3) + PAD_START, // Start button + PAD_UP, // Directional pad ↑ + PAD_RIGHT, // Directional pad → + PAD_DOWN, // Directional pad ↓ + PAD_LEFT, // Directional pad ← + PAD_L_UP, // Left joystick (Up) ↑ + PAD_L_RIGHT, // Left joystick (Right) → + PAD_L_DOWN, // Left joystick (Down) ↓ + PAD_L_LEFT, // Left joystick (Left) ← + PAD_R_UP, // Right joystick (Up) ↑ + PAD_R_RIGHT, // Right joystick (Right) → + PAD_R_DOWN, // Right joystick (Down) ↓ + PAD_R_LEFT // Right joystick (Left) ← +}; + +#if defined(__unix__) || defined(__APPLE__) +#include "GamePad.h" +#endif +#include "bitwise.h" +#include "controller.h" +#include "KeyStatus.h" +#include "mt_queue.h" + +#ifdef _MSC_VER +#define EXPORT_C_(type) extern "C" __declspec(dllexport) type CALLBACK +#else +#define EXPORT_C_(type) extern "C" __attribute__((stdcall, externally_visible, visibility("default"))) type +#endif + +extern FILE *padLog; +extern void initLogging(); + +#define PAD_LOG __Log +//#define PAD_LOG __LogToConsole + +extern keyEvent event; +extern MtQueue g_ev_fifo; + +s32 _PADopen(void *pDsp); +void _PADclose(); +void PADsetMode(int pad, int mode); + +void __Log(const char *fmt, ...); +void __LogToConsole(const char *fmt, ...); +void LoadConfig(); +void SaveConfig(); + +void SysMessage(char *fmt, ...); + +#endif diff --git a/pcsx2/PAD/Linux/res/game_controller_db.txt b/pcsx2/PAD/Linux/res/game_controller_db.txt new file mode 100644 index 0000000000..105ad9b45a --- /dev/null +++ b/pcsx2/PAD/Linux/res/game_controller_db.txt @@ -0,0 +1,499 @@ +# Mac OS, Linux - from # https://github.com/gabomdq/ +# Mac OS X +030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,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, +03000000c82d00000650000001000000,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:Mac OS X, +03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,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, +030000003512000012ab000001000000,8BitDo NES30 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, +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, +03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,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:a5,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000260000001000000,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, +03000000c82d00000261000000010000,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, +03000000c82d00000031000001000000,8BitDo Wireless Adapter,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, +03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,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, +03000000a00500003232000008010000,8Bitdo Zero GamePad,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 GamePad,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, +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, +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,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, +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 V.3 Rumble 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:+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, +03000000ad1b000001f9000000000000,Gamestop BB-070 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,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000102000000000000,GameStop Xbox 360 Wired 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, +030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,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, +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, +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,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, +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,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, +030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro Pad,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, +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,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 mini4,a: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, +030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X, +03000000830500006020000000010000,iBuffalo SNES 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, +03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,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 Wireless 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, +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 Gamepad (DInput),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 Gamepad (DInput),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 Gamepad (XInput),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 USB,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, +030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),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 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:Mac OS X, +03000000380700005082000000010000,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,x:b0,y:b3,platform:Mac OS X, +03000000380700008433000000010000,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:Mac OS X, +03000000380700008483000000010000,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,x:b0,y:b3,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, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,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, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),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, +03000000d8140000cecf000000000000,MC 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, +030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, +03000000d62000007162000001000000,Moga Pro 2 HID,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 XP5-A 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 XP5-A 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, +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, +030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d620000011a7000000020000,Nintendo Switch Core (Plus) 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: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, +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, +03000000550900001472000025050000,NVIDIA Controller v01.04,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, +030000006f0e00000901000002010000,PDP Versus Fighting Pad,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,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, +030000004c050000da0c000000010000,Playstation Classic 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: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, +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, +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,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,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,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,x:b0,y:b3,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),a: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,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 Fightpad for 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,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, +03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,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, +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, +03000000c6240000fefa000000000000,Rock Candy Gamepad for 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, +03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,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 USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,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, +30000004c050000e60c0000000100000,Sony DualSense,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: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,x:b0,y:b3,platform:Mac OS X, +030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,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,x:b0,y:b3,platform:Mac OS X, +03000000d11800000094000000010000,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, +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,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, +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, +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, +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, +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, +03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000bd12000015d0000000010000,Tomee SNES USB 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, +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, +030000006f0e00000302000025040000,Victrix Pro Fight Stick for 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,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000702000003060000,Victrix Pro Fight Stick for 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,x:b0,y:b3,platform:Mac OS X, +03000000791d00000103000009010000,Wii Classic Controller,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, +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,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, +03000000c6240000045d000000000000,Xbox 360 Wired 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 Wireless 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, +030000005e040000d102000000000000,Xbox One Wired 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 Wired 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, +030000005e040000e302000000000000,Xbox One Wired 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 Wireless 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 Wireless 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, +030000005e040000ea02000000000000,Xbox Wireless 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 Wireless 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, +03000000172700004431000029010000,XiaoMi Game 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 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:Mac OS X, +03000000120c0000101e000000010000,ZEROPLUS P4 Wired 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:Mac OS X, + +# 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, +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, +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, +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, +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, +03000000c82d00000190000011010000,8Bitdo NES30 Pro 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, +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, +03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +030000003512000012ab000010010000,8Bitdo SFC30 GamePad,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, +05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,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+,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, +05000000c82d00000261000000010000,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, +05000000202800000900000000010000,8BitDo SNES30 Gamepad,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, +030000005e0400008e02000020010000,8BitDo Wireless Adapter,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, +03000000c82d00000031000011010000,8BitDo Wireless Adapter,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, +03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,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, +05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +05000000a00500003232000008010000,8Bitdo Zero GamePad,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, +030000006f0e00001302000000010000,Afterglow,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 Controller for 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, +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 Wired 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, +03000000100000008200000011010000,Akishop Customs PS360+ v1.66,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 Pad,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 Game 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, +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, +03000000120c00000500000010010000,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, +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,x:b0,y:b3,platform:Linux, +03000000c21100000791000011010000,Be1 GC101 Controller 1.03 mode,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, +03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03 mode,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux, +030000005e0400008e02000003030000,Be1 GC101 Xbox 360 Controller mode,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +03000000666600006706000000010000,boom PSX to PC Converter,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, +03000000ffff0000ffff000000010000,Chinese-made 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, +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, +030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,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 V.3 Rumble 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:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, +03000000790000000600000010010000,DragonRise Inc. Generic USB 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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +030000004f04000004b3000010010000,Dual Power 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, +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, +03000000341a000005f7000010010000,GameCube {HuiJia USB box},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, +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, +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 Co. Ltd PS(R) 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, +030000006f0e00001304000000010000,Generic X-Box pad,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, +03000000f0250000c183000010010000,Goodbetterbest Ltd USB 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, +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, +030000007d0400000540000000010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,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 Inc. USB 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, +06000000adde0000efbe000002010000,Hidromancer Game 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,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000c9110000f055000011010000,HJC Game 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, +03000000632500002605000010010000,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:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, +030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 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, +030000000d0f0000c100000011010000,HORI CO. LTD. HORIPAD S,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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006a00000011010000,HORI CO. LTD. 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 CO. LTD. 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, +030000000d0f00002200000011010000,HORI CO. LTD. 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,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008500000010010000,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: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,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, +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,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, +030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro Pad,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, +030000000d0f0000aa00000011010000,HORI Real Arcade Pro,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, +030000000d0f00001600000000010000,Hori Real Arcade Pro.EX-SE (Xbox 360),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, +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,x:b0,y:b3,platform:Linux, +030000000d0f0000ee00000011010000,HORIPAD mini4,a: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, +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, +030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,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, +03000000830500006020000010010000,iBuffalo SNES 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, +050000006964726f69643a636f6e0000,idroid:con,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 PCU#0 Gamepad Interface,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, +0500000049190000020400001b010000,Ipega PG-9069 - Bluetooth Gamepad,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 - Bluetooth 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, +030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,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, +03000000300f00001001000010010000,Jess Tech Dual Analog 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, +03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil Pad,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 USB Game 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, +03000000242f00002d00000011010000,JYS Wireless 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 Wireless 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, +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 Gamepad (XInput),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 Gamepad (XInput),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 Gamepad (XInput),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 Gamepad (DInput),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 Gamepad (XInput),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, +030000006d0400000ac2000010010000,Logitech Inc. WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux, +030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,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, +05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a: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, +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,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, +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,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,x:b0,y:b3,platform:Linux, +03000000380700001647000010040000,Mad Catz Wired 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 Wired Xbox 360 Controller (SFIV),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, +03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,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,MadCatz PC USB Wired Stick 8838,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, +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, +03000000790000004418000010010000,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:Linux, +03000000790000004318000010010000,Mayflash GameCube Controller Adapter,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: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, +0300000025090000e803000001010000,Mayflash Wii Classic Controller,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, +03000000780000000600000010010000,Microntek USB 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, +030000005e0400000e00000000010000,Microsoft SideWinder,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, +030000005e0400008e02000004010000,Microsoft X-Box 360 pad,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 X-Box 360 pad,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, +030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad - Wired,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, +050000005e040000050b000003090000,Microsoft X-Box One Elite 2 pad,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, +030000005e040000e302000003020000,Microsoft X-Box One Elite pad,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 S pad - Wired,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, +030000005e040000d102000001010000,Microsoft X-Box One pad,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 X-Box One pad (Firmware 2015),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 X-Box One pad v2,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, +030000005e0400008502000000010000,Microsoft X-Box pad (Japan),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 X-Box pad v2 (US),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, +03000000c62400001a53000000010000,Mini PE,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, +05000000d6200000e589000001000000,Moga 2 HID,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 HID,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 XP5-A 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 XP5-A 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, +03000000250900006688000000010000,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: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, +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, +030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux, +060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, +03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b2,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:b0,y:b3,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500000920000001800000,Nintendo Switch Pro Controller (joycond),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,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +030000007e0500000920000011810000,Nintendo Switch Pro Controller Wired (joycond),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,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500003003000001000000,Nintendo Wii Remote 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, +05000000010000000100000003000000,Nintendo Wiimote,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, +030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,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, +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 v01.04,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,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, +05000000550900001472000001000000,NVIDIA Controller v01.04,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,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,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,odroidgo2_joypad,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,odroidgo2_joypad_v11,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, +030000005e0400000202000000010000,Old Xbox pad,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, +05000000362800000100000002010000,OUYA Game 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 Game 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, +03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB 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, +03000000790000001c18000011010000,PC Game 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, +03000000ff1100003133000010010000,PC Game 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 Wired Xbox One Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +030000006f0e0000b802000013020000,PDP AFTERGLOW Wired Xbox One Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,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, +030000006f0e00008001000011010000,PDP CO. LTD. Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,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, +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, +030000006f0e00008701000011010000,PDP Rock Candy Wired Controller for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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, +030000006f0e00000901000011010000,PDP Versus Fighting Pad,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, +030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,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, +030000006f0e00008501000011010000,PDP Wired Fight Pad 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, +0500000049190000030400001b010000,PG-9099,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, +030000004c050000da0c000011010000,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, +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, +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, +03000000c62400001a58000001010000,PowerA Xbox One Cabled,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,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, +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, +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, +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, +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,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, +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,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,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,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,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, +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,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,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, +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, +030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,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 Technologies GC/N64 to USB v3.6,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, +030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,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, +030000008916000000fd000024010000,Razer Onza Tournament Edition,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, +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,x:b0,y:b3,platform:Linux, +03000000321500000810000011010000,Razer Panthera Evo Arcade Stick for PS4,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b13,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,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, +03000000321500000011000011010000,Razer Raion Fightpad for 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,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, +03000000790000001100000010010000,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: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, +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, +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, +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, +03000000a306000023f6000011010000,Saitek Cyborg V.1 Game 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,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b10,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, +03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,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, +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 Pad,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, +03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,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, +03000000a306000020f6000011010000,Saitek PS2700 Rumble 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,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600001005000000010000,Saitek 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, +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, +03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux, +03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired 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, +03000000632500007505000010010000,SHANWAN PS3/PC 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 PS3/PC Wired GamePad,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, +03000000632500002305000010010000,ShanWan 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:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000341a00000908000010010000,SL-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:Linux, +030000004c050000e60c000011010000,Sony DualSense,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:Linux, +050000004c050000e60c000000010000,Sony DualSense,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: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 Wireless 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, +030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,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, +03000000d11800000094000011010000,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, +03000000de2800000112000001000000,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:Linux, +03000000de2800000211000001000000,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: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,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,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,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,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +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:Linux, +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: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, +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 for USB,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: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,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +03000000457500002211000010010000,SZMY-POWER CO. LTD. 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, +030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. 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:Linux, +030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,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, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,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, +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, +030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,x:b1,y:b3,leftshoulder:b4,rightshoulder:b6,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,platform:Linux, +030000004f04000026b3000002040000,Thrustmaster Gamepad 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 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, +030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,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 Wireless 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, +030000004f04000007d0000000010000,Thrustmaster T Mini Wireless,a: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, +03000000bd12000015d0000010010000,Tomee SNES USB 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, +03000000100800000100000010010000,Twin USB 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, +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 Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +030000006f0e00000302000011010000,Victrix Pro Fight Stick for 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,x:b0,y:b3,platform:Linux, +030000006f0e00000702000011010000,Victrix Pro Fight Stick for 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,x:b0,y:b3,platform:Linux, +05000000ac0500003232000001000000,VR-BOX,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, +03000000791d00000103000010010000,Wii Classic Controller,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, +050000000d0f0000f600000001000000,Wireless 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, +030000005e0400008e02000010010000,X360 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,X360 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, +030000005e0400001907000000010000,X360 Wireless 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, +030000005e0400009102000007010000,X360 Wireless 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,X360 Wireless 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,X360 Wireless 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, +0000000058626f782033363020576900,Xbox 360 Wireless 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, +030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),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 Gamepad (userspace driver),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, +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, +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, +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, +030000005e040000ea02000000000000,Xbox One Wireless 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 Wireless 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 Wireless 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, +030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),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,xbox360 Wireless 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, +03000000450c00002043000010010000,XEOX Gamepad SL-6556-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, +03000000ac0500005b05000010010000,Xiaoji 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, +05000000172700004431000029010000,XiaoMi Game 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,Xin-Mo Xin-Mo 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, +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 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:Linux, +03000000120c0000101e000011010000,ZEROPLUS P4 Wired 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:Linux, diff --git a/pcsx2/PAD/Linux/res/onepad-res.xml b/pcsx2/PAD/Linux/res/onepad-res.xml new file mode 100644 index 0000000000..b231d41004 --- /dev/null +++ b/pcsx2/PAD/Linux/res/onepad-res.xml @@ -0,0 +1,6 @@ + + + + game_controller_db.txt + + diff --git a/pcsx2/PAD/Linux/state_management.cpp b/pcsx2/PAD/Linux/state_management.cpp new file mode 100644 index 0000000000..aff9cedd7a --- /dev/null +++ b/pcsx2/PAD/Linux/state_management.cpp @@ -0,0 +1,468 @@ +/* OnePAD + * Copyright (C) 2016 + * + * Based on LilyPad + * Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "state_management.h" +#include "GamePad.h" + +// Typical packet response on the bus +static const u8 ConfigExit[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const u8 noclue[7] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5A}; +static const u8 setMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const u8 queryModelDS2[7] = {0x5A, 0x03, 0x02, 0x00, 0x02, 0x01, 0x00}; +static const u8 queryModelDS1[7] = {0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00}; +static const u8 queryComb[7] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}; +static const u8 queryMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A}; + +static u8 queryMaskMode[7] = {0x5A, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x5A}; + +static const u8 queryAct[2][7] = { + {0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}, + {0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14}}; + +QueryInfo query; +Pad pads[2][4]; +int slots[2] = {0, 0}; + +////////////////////////////////////////////////////////////////////// +// QueryInfo implementation +////////////////////////////////////////////////////////////////////// + +void QueryInfo::reset() +{ + port = 0; + slot = 0; + lastByte = 1; + currentCommand = 0; + numBytes = 0; + queryDone = 1; + memset(response, 0xF3, sizeof(response)); +} + +u8 QueryInfo::start_poll(int _port) +{ + if (port > 1) { + reset(); + return 0; + } + + queryDone = 0; + port = _port; + slot = slots[port]; + numBytes = 2; + lastByte = 0; + + return 0xFF; +} + +////////////////////////////////////////////////////////////////////// +// Pad implementation +////////////////////////////////////////////////////////////////////// + +void Pad::set_mode(int _mode) +{ + mode = _mode; + +#if 0 + fprintf(stdout, "OnePad: set new pad mode="); + if (mode == MODE_DIGITAL) + fprintf(stdout, "DIGITAL\n"); + else if (mode == MODE_ANALOG) + fprintf(stdout, "ANALOG\n"); + else if (mode == MODE_DS2_NATIVE) + fprintf(stdout, "DS2 NATIVE\n"); + else + fprintf(stdout, "??? 0x%x\n", mode); +#endif +} + +void Pad::set_vibrate(int motor, u8 val) +{ + nextVibrate[motor] = val; +} + +void Pad::reset_vibrate() +{ + set_vibrate(0, 0); + set_vibrate(1, 0); + memset(vibrate, 0xFF, sizeof(vibrate)); + vibrate[0] = 0x5A; +} + +void Pad::reset() +{ + memset(this, 0, sizeof(PadFreezeData)); + + set_mode(MODE_DIGITAL); + umask[0] = umask[1] = 0xFF; + + // Sets up vibrate variable. + reset_vibrate(); +} + +void Pad::rumble(unsigned port) +{ + for (unsigned motor = 0; motor < 2; motor++) { + // TODO: Probably be better to send all of these at once. + if (nextVibrate[motor] | currentVibrate[motor]) { + currentVibrate[motor] = nextVibrate[motor]; + + GamePad::DoRumble(motor, port); + } + } +} + +void Pad::stop_vibrate_all() +{ +#if 0 + for (int i=0; i<8; i++) { + SetVibrate(i&1, i>>1, 0, 0); + SetVibrate(i&1, i>>1, 1, 0); + } +#endif + // FIXME equivalent ? + for (int port = 0; port < 2; port++) + for (int slot = 0; slot < 4; slot++) + pads[port][slot].reset_vibrate(); +} + +void Pad::reset_all() +{ + for (int port = 0; port < 2; port++) + for (int slot = 0; slot < 4; slot++) + pads[port][slot].reset(); +} + +void Pad::rumble_all() +{ + for (unsigned port = 0; port < 2; port++) + for (unsigned slot = 0; slot < 4; slot++) + pads[port][slot].rumble(port); +} + +////////////////////////////////////////////////////////////////////// +// Pad implementation +////////////////////////////////////////////////////////////////////// + +inline bool IsDualshock2() +{ +// FIXME +#if 0 + return config.padConfigs[query.port][query.slot].type == Dualshock2Pad || + (config.padConfigs[query.port][query.slot].type == GuitarPad && config.GH2); +#else + return true; +#endif +} + +u8 pad_start_poll(u8 pad) +{ + return query.start_poll(pad - 1); +} + +u8 pad_poll(u8 value) +{ + if (query.lastByte + 1 >= query.numBytes) { + return 0; + } + if (query.lastByte && query.queryDone) { + return query.response[++query.lastByte]; + } + + Pad *pad = &pads[query.port][query.slot]; + + if (query.lastByte == 0) { + query.lastByte++; + query.currentCommand = value; + + switch (value) { + case CMD_CONFIG_MODE: + if (pad->config) { + // In config mode. Might not actually be leaving it. + query.set_result(ConfigExit); + return 0xF3; + } + [[fallthrough]]; // fallthrough on purpose (but I don't know why) + + case CMD_READ_DATA_AND_VIBRATE: { + query.response[2] = 0x5A; +#if 0 + int i; + Update(query.port, query.slot); + ButtonSum *sum = &pad->sum; + + u8 b1 = 0xFF, b2 = 0xFF; + for (i = 0; i<4; i++) { + b1 -= (sum->buttons[i] > 0) << i; + } + for (i = 0; i<8; i++) { + b2 -= (sum->buttons[i+4] > 0) << i; + } +#endif + +// FIXME +#if 0 + if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) { + sum->buttons[15] = 255; + // Not sure about this. Forces wammy to be from 0 to 0x7F. + // if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0; + } +#endif + +#if 0 + for (i = 4; i<8; i++) { + b1 -= (sum->buttons[i+8] > 0) << i; + } +#endif + +// FIXME +#if 0 + //Left, Right and Down are always pressed on Pop'n Music controller. + if (config.padConfigs[query.port][query.slot].type == PopnPad) + b1=b1 & 0x1f; +#endif + + uint16_t buttons = g_key_status.get(query.port); + + query.numBytes = 5; + + query.response[3] = (buttons >> 8) & 0xFF; + query.response[4] = (buttons >> 0) & 0xFF; + + if (pad->mode != MODE_DIGITAL) { // ANALOG || DS2 native + query.numBytes = 9; + + query.response[5] = g_key_status.get(query.port, PAD_R_RIGHT); + query.response[6] = g_key_status.get(query.port, PAD_R_UP); + query.response[7] = g_key_status.get(query.port, PAD_L_RIGHT); + query.response[8] = g_key_status.get(query.port, PAD_L_UP); + + if (pad->mode != MODE_ANALOG) { // DS2 native + query.numBytes = 21; + + query.response[9] = !test_bit(buttons, 13) ? g_key_status.get(query.port, PAD_RIGHT) : 0; + query.response[10] = !test_bit(buttons, 15) ? g_key_status.get(query.port, PAD_LEFT) : 0; + query.response[11] = !test_bit(buttons, 12) ? g_key_status.get(query.port, PAD_UP) : 0; + query.response[12] = !test_bit(buttons, 14) ? g_key_status.get(query.port, PAD_DOWN) : 0; + + query.response[13] = !test_bit(buttons, 4) ? g_key_status.get(query.port, PAD_TRIANGLE) : 0; + query.response[14] = !test_bit(buttons, 5) ? g_key_status.get(query.port, PAD_CIRCLE) : 0; + query.response[15] = !test_bit(buttons, 6) ? g_key_status.get(query.port, PAD_CROSS) : 0; + query.response[16] = !test_bit(buttons, 7) ? g_key_status.get(query.port, PAD_SQUARE) : 0; + query.response[17] = !test_bit(buttons, 2) ? g_key_status.get(query.port, PAD_L1) : 0; + query.response[18] = !test_bit(buttons, 3) ? g_key_status.get(query.port, PAD_R1) : 0; + query.response[19] = !test_bit(buttons, 0) ? g_key_status.get(query.port, PAD_L2) : 0; + query.response[20] = !test_bit(buttons, 1) ? g_key_status.get(query.port, PAD_R2) : 0; + } + } + +#if 0 + query.response[3] = b1; + query.response[4] = b2; + + query.numBytes = 5; + if (pad->mode != MODE_DIGITAL) { + query.response[5] = Cap((sum->sticks[0].horiz+255)/2); + query.response[6] = Cap((sum->sticks[0].vert+255)/2); + query.response[7] = Cap((sum->sticks[1].horiz+255)/2); + query.response[8] = Cap((sum->sticks[1].vert+255)/2); + + query.numBytes = 9; + if (pad->mode != MODE_ANALOG) { + // Good idea? No clue. + //query.response[3] &= pad->mask[0]; + //query.response[4] &= pad->mask[1]; + + // No need to cap these, already done int CapSum(). + query.response[9] = (unsigned char)sum->buttons[13]; //D-pad right + query.response[10] = (unsigned char)sum->buttons[15]; //D-pad left + query.response[11] = (unsigned char)sum->buttons[12]; //D-pad up + query.response[12] = (unsigned char)sum->buttons[14]; //D-pad down + + query.response[13] = (unsigned char) sum->buttons[8]; + query.response[14] = (unsigned char) sum->buttons[9]; + query.response[15] = (unsigned char) sum->buttons[10]; + query.response[16] = (unsigned char) sum->buttons[11]; + query.response[17] = (unsigned char) sum->buttons[6]; + query.response[18] = (unsigned char) sum->buttons[7]; + query.response[19] = (unsigned char) sum->buttons[4]; + query.response[20] = (unsigned char) sum->buttons[5]; + query.numBytes = 21; + } + } +#endif + } + + query.lastByte = 1; + return pad->mode; + + case CMD_SET_VREF_PARAM: + query.set_final_result(noclue); + break; + + case CMD_QUERY_DS2_ANALOG_MODE: + // Right? Wrong? No clue. + if (pad->mode == MODE_DIGITAL) { + queryMaskMode[1] = queryMaskMode[2] = queryMaskMode[3] = 0; + queryMaskMode[6] = 0x00; + } else { + queryMaskMode[1] = pad->umask[0]; + queryMaskMode[2] = pad->umask[1]; + queryMaskMode[3] = 0x03; + // Not entirely sure about this. + //queryMaskMode[3] = 0x01 | (pad->mode == MODE_DS2_NATIVE)*2; + queryMaskMode[6] = 0x5A; + } + query.set_final_result(queryMaskMode); + break; + + case CMD_SET_MODE_AND_LOCK: + query.set_result(setMode); + pad->reset_vibrate(); + break; + + case CMD_QUERY_MODEL_AND_MODE: + if (IsDualshock2()) { + query.set_final_result(queryModelDS2); + } else { + query.set_final_result(queryModelDS1); + } + // Not digital mode. + query.response[5] = (pad->mode & 0xF) != 1; + break; + + case CMD_QUERY_ACT: + query.set_result(queryAct[0]); + break; + + case CMD_QUERY_COMB: + query.set_final_result(queryComb); + break; + + case CMD_QUERY_MODE: + query.set_result(queryMode); + break; + + case CMD_VIBRATION_TOGGLE: + memcpy(query.response + 2, pad->vibrate, 7); + query.numBytes = 9; + //query.set_result(pad->vibrate); // warning copy 7b not 8 (but it is really important?) + pad->reset_vibrate(); + break; + + case CMD_SET_DS2_NATIVE_MODE: + if (IsDualshock2()) { + query.set_result(setNativeMode); + } else { + query.set_final_result(setNativeMode); + } + break; + + default: + query.numBytes = 0; + query.queryDone = 1; + break; + } + + return 0xF3; + + } else { + query.lastByte++; + + switch (query.currentCommand) { + case CMD_READ_DATA_AND_VIBRATE: + if (query.lastByte == pad->vibrateI[0]) + pad->set_vibrate(1, 255 * (value & 1)); + else if (query.lastByte == pad->vibrateI[1]) + pad->set_vibrate(0, value); + + break; + + case CMD_CONFIG_MODE: + if (query.lastByte == 3) { + query.queryDone = 1; + pad->config = value; + } + break; + + case CMD_SET_MODE_AND_LOCK: + if (query.lastByte == 3 && value < 2) { + pad->set_mode(value ? MODE_ANALOG : MODE_DIGITAL); + } else if (query.lastByte == 4) { + if (value == 3) + pad->modeLock = 3; + else + pad->modeLock = 0; + + query.queryDone = 1; + } + break; + + case CMD_QUERY_ACT: + if (query.lastByte == 3) { + if (value < 2) + query.set_result(queryAct[value]); + // bunch of 0's + // else query.set_result(setMode); + query.queryDone = 1; + } + break; + + case CMD_QUERY_MODE: + if (query.lastByte == 3 && value < 2) { + query.response[6] = 4 + value * 3; + query.queryDone = 1; + } + // bunch of 0's + //else data = setMode; + break; + + case CMD_VIBRATION_TOGGLE: + if (query.lastByte >= 3) { + if (value == 0) { + pad->vibrateI[0] = (u8)query.lastByte; + } else if (value == 1) { + pad->vibrateI[1] = (u8)query.lastByte; + } + pad->vibrate[query.lastByte - 2] = value; + } + break; + + case CMD_SET_DS2_NATIVE_MODE: + if (query.lastByte == 3 || query.lastByte == 4) { + pad->umask[query.lastByte - 3] = value; + } else if (query.lastByte == 5) { + if (!(value & 1)) + pad->set_mode(MODE_DIGITAL); + else if (!(value & 2)) + pad->set_mode(MODE_ANALOG); + else + pad->set_mode(MODE_DS2_NATIVE); + } + break; + + default: + return 0; + } + + return query.response[query.lastByte]; + } +} diff --git a/pcsx2/PAD/Linux/state_management.h b/pcsx2/PAD/Linux/state_management.h new file mode 100644 index 0000000000..8f02e21c20 --- /dev/null +++ b/pcsx2/PAD/Linux/state_management.h @@ -0,0 +1,119 @@ +/* OnePAD + * Copyright (C) 2016 + * + * Based on LilyPad + * Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "onepad.h" + +#define MODE_DIGITAL 0x41 +#define MODE_ANALOG 0x73 +#define MODE_DS2_NATIVE 0x79 + +// The state of the PS2 bus +struct QueryInfo +{ + u8 port; + u8 slot; + u8 lastByte; + u8 currentCommand; + u8 numBytes; + u8 queryDone; + u8 response[42]; + + void reset(); + u8 start_poll(int port); + + template + void set_result(const u8 (&rsp)[S]) + { + memcpy(response + 2, rsp, S); + numBytes = 2 + S; + } + + template + void set_final_result(const u8 (&rsp)[S]) + { + set_result(rsp); + queryDone = 1; + } +}; + +// Freeze data, for a single pad. Basically has all pad state that +// a PS2 can set. +struct PadFreezeData +{ + // Digital / Analog / DS2 Native + u8 mode; + + u8 modeLock; + + // In config mode + u8 config; + + u8 vibrate[8]; + u8 umask[2]; + + // Vibration indices. + u8 vibrateI[2]; + + // Last vibration value sent to controller. + // Only used so as not to call vibration + // functions when old and new values are both 0. + u8 currentVibrate[2]; + + // Next vibrate val to send to controller. If next and current are + // both 0, nothing is sent to the controller. Otherwise, it's sent + // on every update. + u8 nextVibrate[2]; +}; + +class Pad : public PadFreezeData +{ +public: + // Lilypad store here the state of PC pad + + void rumble(unsigned port); + void set_vibrate(int motor, u8 val); + void reset_vibrate(); + void reset(); + + void set_mode(int mode); + + static void reset_all(); + static void stop_vibrate_all(); + static void rumble_all(); +}; + +// Full state to manage save state +struct PadPluginFreezeData +{ + char format[8]; + u32 version; + // active slot for port + u8 slot[2]; + PadFreezeData padData[2][4]; + QueryInfo query; +}; + +extern QueryInfo query; +extern Pad pads[2][4]; +extern int slots[2]; + +extern u8 pad_start_poll(u8 pad); +extern u8 pad_poll(u8 value); diff --git a/pcsx2/PAD/Linux/wx_dialog/GamepadConfiguration.cpp b/pcsx2/PAD/Linux/wx_dialog/GamepadConfiguration.cpp new file mode 100644 index 0000000000..757c675c8d --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/GamepadConfiguration.cpp @@ -0,0 +1,185 @@ +/* GamepadConfiguration.cpp + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "GamepadConfiguration.h" + +GamepadConfiguration::GamepadConfiguration(int pad, wxWindow *parent) + : wxDialog(parent, wxID_ANY, _T("Gamepad"), wxDefaultPosition, wxDefaultSize, + wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN) +{ + m_pad_id = pad; + + wxBoxSizer *gamepad_box = new wxBoxSizer(wxVERTICAL); + + wxArrayString choices; + for (const auto &j : s_vgamePad) { + choices.Add(j->GetName()); + } + + m_joy_map = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices); + m_cb_rumble = new wxCheckBox(this, enable_rumble_id, _T("&Enable rumble")); + + wxStaticBoxSizer *rumble_box = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Rumble intensity")); + m_sl_rumble_intensity = new wxSlider(this, rumble_slider_id, 0, 0, 0x7FFF, wxDefaultPosition, wxDefaultSize, + wxSL_HORIZONTAL | wxSL_LABELS | wxSL_BOTTOM); + + wxStaticBoxSizer *joy_box = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Joystick sensibility")); + m_sl_joystick_sensibility = new wxSlider(this, joy_slider_id, 0, 0, 200, wxDefaultPosition, wxDefaultSize, + wxSL_HORIZONTAL | wxSL_LABELS | wxSL_BOTTOM); + + gamepad_box->Add(m_joy_map, wxSizerFlags().Expand().Border(wxALL, 5)); + gamepad_box->Add(m_cb_rumble, wxSizerFlags().Expand()); + + rumble_box->Add(m_sl_rumble_intensity, wxSizerFlags().Expand().Border(wxALL, 5)); + joy_box->Add(m_sl_joystick_sensibility, wxSizerFlags().Expand().Border(wxALL, 5)); + + gamepad_box->Add(rumble_box, wxSizerFlags().Expand().Border(wxALL, 5)); + gamepad_box->Add(joy_box, wxSizerFlags().Expand().Border(wxALL, 5)); + + gamepad_box->Add(CreateSeparatedButtonSizer(wxOK), wxSizerFlags().Right().Border(wxALL, 5)); + + Bind(wxEVT_BUTTON, &GamepadConfiguration::OnOk, this, wxID_OK); + Bind(wxEVT_SCROLL_THUMBRELEASE, &GamepadConfiguration::OnSliderReleased, this); + Bind(wxEVT_CHECKBOX, &GamepadConfiguration::OnCheckboxChange, this); + Bind(wxEVT_CHOICE, &GamepadConfiguration::OnChoiceChange, this); + + repopulate(); + + SetSizerAndFit(gamepad_box); +} + +/** + Initialize the frame + Check if a gamepad is detected + Check if the gamepad support rumbles +*/ +void GamepadConfiguration::InitGamepadConfiguration() +{ + repopulate(); // Set label and fit simulated key array + /* + * Check if there exist at least one pad available + * if the pad id is 0, you need at least 1 gamepad connected, + * if the pad id is 1, you need at least 2 gamepads connected, + * Prevent to use a none initialized value on s_vgamePad (core dump) + */ + if (s_vgamePad.size() >= m_pad_id + 1) { + /* + * Determine if the device can use rumble + * Use TestForce with a very low strength (can't be felt) + * May be better to create a new function in order to check only that + */ + + // Bad idea. Some connected devices might support rumble but not all connected devices. + // if (!s_vgamePad[m_pad_id]->TestForce(0.001f)) { + // wxMessageBox(L"Rumble is not available for your device."); + // m_cb_rumble->Disable(); // disable the rumble checkbox + // m_sl_rumble_intensity->Disable(); // disable the rumble intensity slider + // } + } else { + wxMessageBox(L"No gamepad detected."); + m_sl_joystick_sensibility->Disable(); // disable the joystick sensibility slider + m_cb_rumble->Disable(); // disable the rumble checkbox + m_sl_rumble_intensity->Disable(); // disable the rumble intensity slider + } +} + +void GamepadConfiguration::OnOk(wxCommandEvent &event) +{ + Destroy(); +} + +/** + * Slider event, called when the use release the slider button + * @FIXME The current solution can't change the joystick sensibility and the rumble intensity + * for a specific gamepad. The same value is used for both +*/ +void GamepadConfiguration::OnSliderReleased(wxCommandEvent &event) +{ + wxSlider *sl_tmp = (wxSlider *)event.GetEventObject(); + int sl_id = sl_tmp->GetId(); + + if (sl_id == rumble_slider_id) + { + g_conf.set_ff_intensity(m_sl_rumble_intensity->GetValue()); + + // convert in a float value between 0 and 1, and run rumble feedback. + // 0 to 1 scales to 0x0 to 0x7FFF + s_vgamePad[m_pad_id]->TestForce(m_sl_rumble_intensity->GetValue() / 0x7FFF); + } + else if (sl_id == joy_slider_id) + { + g_conf.set_sensibility(m_sl_joystick_sensibility->GetValue()); + } +} + +/** + * Checkbox event, called when the value of the checkbox change +*/ +void GamepadConfiguration::OnCheckboxChange(wxCommandEvent &event) +{ + wxCheckBox *cb_tmp = (wxCheckBox *)event.GetEventObject(); // get the slider object + int cb_id = cb_tmp->GetId(); + + if (cb_id == enable_rumble_id) + { + g_conf.pad_options[m_pad_id].forcefeedback = (m_cb_rumble->GetValue()) ? (u32)1 : (u32)0; + if (m_cb_rumble->GetValue()) + { + s_vgamePad[m_pad_id]->TestForce(); + m_sl_rumble_intensity->Enable(); + } + else + { + m_sl_rumble_intensity->Disable(); + } + } +} + +/* + * Checkbox event, called when the value of the choice box change + */ +void GamepadConfiguration::OnChoiceChange(wxCommandEvent &event) +{ + wxChoice *choice_tmp = (wxChoice *)event.GetEventObject(); + int id = choice_tmp->GetSelection(); + if (id != wxNOT_FOUND) + { + g_conf.set_joy_uid(m_pad_id, GamePad::index_to_uid(id)); + } +} + +/****************************************/ +/*********** Methods functions **********/ +/****************************************/ + +// Set button values +void GamepadConfiguration::repopulate() +{ + m_cb_rumble->SetValue(g_conf.pad_options[m_pad_id].forcefeedback); + + m_sl_rumble_intensity->SetValue(g_conf.get_ff_intensity()); + m_sl_joystick_sensibility->SetValue(g_conf.get_sensibility()); + + u32 joyid = GamePad::uid_to_index(m_pad_id); + if (joyid < m_joy_map->GetCount() && !m_joy_map->IsEmpty()) + m_joy_map->SetSelection(joyid); + + // enable rumble intensity slider if the checkbox is checked + m_sl_rumble_intensity->Enable(m_cb_rumble->GetValue()); +} diff --git a/pcsx2/PAD/Linux/wx_dialog/GamepadConfiguration.h b/pcsx2/PAD/Linux/wx_dialog/GamepadConfiguration.h new file mode 100644 index 0000000000..26ef8cefa7 --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/GamepadConfiguration.h @@ -0,0 +1,57 @@ +/* GamepadConfiguration.h + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#ifndef __GAMEPADCONFIGURATION_H__ +#define __GAMEPADCONFIGURATION_H__ + +#include + +#include "../GamePad.h" +#include "../keyboard.h" +#include "../onepad.h" + +static const s32 rumble_slider_id = wxID_HIGHEST + 200 + 1; +static const s32 joy_slider_id = wxID_HIGHEST + 200 + 2; +static const s32 enable_rumble_id = wxID_HIGHEST + 200 + 3; + +class GamepadConfiguration : public wxDialog +{ + wxCheckBox *m_cb_rumble; + wxSlider *m_sl_rumble_intensity, *m_sl_joystick_sensibility; + wxChoice *m_joy_map; + + u32 m_pad_id; + + // Methods + void repopulate(); + + // Events + void OnOk(wxCommandEvent &); + void OnSliderReleased(wxCommandEvent &); + void OnCheckboxChange(wxCommandEvent &); + void OnChoiceChange(wxCommandEvent &); + +public: + GamepadConfiguration(int, wxWindow *); + void InitGamepadConfiguration(); +}; + +#endif // __GAMEPADCONFIGURATION_H__ diff --git a/pcsx2/PAD/Linux/wx_dialog/JoystickConfiguration.cpp b/pcsx2/PAD/Linux/wx_dialog/JoystickConfiguration.cpp new file mode 100644 index 0000000000..dc4ac70c96 --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/JoystickConfiguration.cpp @@ -0,0 +1,211 @@ +/* JoystickConfiguration.cpp + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "JoystickConfiguration.h" + +// Constructor of JoystickConfiguration +JoystickConfiguration::JoystickConfiguration(int pad, bool left, wxWindow *parent) + : wxDialog(parent, wxID_ANY, _T("Joystick configuration"), wxDefaultPosition, wxDefaultSize, + wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN) +{ + m_init_reverse_Lx = m_init_reverse_Ly = + m_init_reverse_Rx = m_init_reverse_Ry = + m_init_mouse_Ljoy = m_init_mouse_Rjoy = false; + + m_pad_id = pad; + m_isForLeftJoystick = left; + + wxBoxSizer *joy_conf_box = new wxBoxSizer(wxVERTICAL); + + if (m_isForLeftJoystick) + { + m_cb_reverse_Lx = new wxCheckBox(this, Lx_check_id, _T("Reverse Lx")); + m_cb_reverse_Ly = new wxCheckBox(this, Ly_check_id, _T("Reverse Ly")); + m_cb_mouse_Ljoy = new wxCheckBox(this, Ljoy_check_id, _T("Use mouse for left analog joystick")); + + joy_conf_box->Add(m_cb_reverse_Lx, wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT, 5)); + joy_conf_box->Add(m_cb_reverse_Ly, wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT, 5)); + joy_conf_box->Add(m_cb_mouse_Ljoy, wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT, 5)); + + m_cb_reverse_Rx = m_cb_reverse_Ry = m_cb_mouse_Rjoy = nullptr; + + } + else + { + m_cb_reverse_Rx = new wxCheckBox(this, Rx_check_id, _T("Reverse Rx")); + m_cb_reverse_Ry = new wxCheckBox(this, Ry_check_id, _T("Reverse Ry")); + m_cb_mouse_Rjoy = new wxCheckBox(this, Rjoy_check_id, _T("Use mouse for right analog joystick")); + + joy_conf_box->Add(m_cb_reverse_Rx, wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT, 5)); + joy_conf_box->Add(m_cb_reverse_Ry, wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT, 5)); + joy_conf_box->Add(m_cb_mouse_Rjoy, wxSizerFlags().Expand().Border(wxLEFT | wxRIGHT, 5)); + + m_cb_reverse_Lx = m_cb_reverse_Ly = m_cb_mouse_Ljoy = nullptr; + } + + joy_conf_box->Add(CreateSeparatedButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Border(wxALL, 5).Right()); + + Bind(wxEVT_BUTTON, &JoystickConfiguration::OnOk, this, wxID_OK); + Bind(wxEVT_BUTTON, &JoystickConfiguration::OnCancel, this, wxID_CANCEL); + Bind(wxEVT_CHECKBOX, &JoystickConfiguration::OnCheckboxChange, this); + + SetSizerAndFit(joy_conf_box); +} + +/** + Initialize the frame + Check if a gamepad is detected +*/ +void JoystickConfiguration::InitJoystickConfiguration() +{ + repopulate(); // Set label and fit simulated key array + /* + * Check if there exist at least one pad available + * if the pad id is 0, you need at least 1 gamepad connected, + * if the pad id is 1, you need at least 2 gamepads connected, + * Prevent to use a none initialized value on s_vgamePad (core dump) + */ + if (s_vgamePad.size() < m_pad_id + 1) { + if (s_vgamePad.empty()) + wxMessageBox(L"No gamepad detected."); + else + wxMessageBox(L"No second gamepad detected."); + + // disable all checkboxes + if (m_isForLeftJoystick) + { + m_cb_reverse_Lx->Disable(); + m_cb_reverse_Ly->Disable(); + } + else + { + m_cb_reverse_Rx->Disable(); + m_cb_reverse_Ry->Disable(); + } + } +} + +void JoystickConfiguration::OnOk(wxCommandEvent &event) +{ + Destroy(); +} + +void JoystickConfiguration::OnCancel(wxCommandEvent &event) +{ + reset(); + Destroy(); +} + +/** + * Checkbox event, called when the value of the checkbox change +*/ +void JoystickConfiguration::OnCheckboxChange(wxCommandEvent &event) +{ + wxCheckBox *cb_tmp = (wxCheckBox *)event.GetEventObject(); // get the slider object + int cb_id = cb_tmp->GetId(); + + if (m_isForLeftJoystick) + { + switch (cb_id) + { + case Lx_check_id: + g_conf.pad_options[m_pad_id].reverse_lx = m_cb_reverse_Lx->GetValue(); + break; + + case Ly_check_id: + g_conf.pad_options[m_pad_id].reverse_ly = m_cb_reverse_Ly->GetValue(); + break; + + case Ljoy_check_id: + g_conf.pad_options[m_pad_id].mouse_l = m_cb_mouse_Ljoy->GetValue(); + break; + + default: + break; + } + } + else + { + switch (cb_id) + { + case Rx_check_id: + g_conf.pad_options[m_pad_id].reverse_rx = m_cb_reverse_Rx->GetValue(); + break; + + case Ry_check_id: + g_conf.pad_options[m_pad_id].reverse_ry = m_cb_reverse_Ry->GetValue(); + break; + + case Rjoy_check_id: + g_conf.pad_options[m_pad_id].mouse_r = m_cb_mouse_Rjoy->GetValue(); + break; + + default: + break; + } + } +} + +/****************************************/ +/*********** Methods functions **********/ +/****************************************/ + +// Reset checkbox and slider values +void JoystickConfiguration::reset() +{ + if (m_isForLeftJoystick) + { + m_cb_reverse_Lx->SetValue(m_init_reverse_Lx); + m_cb_reverse_Ly->SetValue(m_init_reverse_Ly); + m_cb_mouse_Ljoy->SetValue(m_init_mouse_Ljoy); + } + else + { + m_cb_reverse_Rx->SetValue(m_init_reverse_Rx); + m_cb_reverse_Ry->SetValue(m_init_reverse_Ry); + m_cb_mouse_Rjoy->SetValue(m_init_mouse_Rjoy); + } +} + +// Set button values +void JoystickConfiguration::repopulate() +{ + if (m_isForLeftJoystick) + { + m_init_reverse_Lx = g_conf.pad_options[m_pad_id].reverse_lx; + m_cb_reverse_Lx->SetValue(m_init_reverse_Lx); + + m_init_reverse_Ly = g_conf.pad_options[m_pad_id].reverse_ly; + m_cb_reverse_Ly->SetValue(m_init_reverse_Ly); + + m_init_mouse_Ljoy = g_conf.pad_options[m_pad_id].mouse_l; + m_cb_mouse_Ljoy->SetValue(m_init_mouse_Ljoy); + } + else + { + m_init_reverse_Rx = g_conf.pad_options[m_pad_id].reverse_rx; + m_cb_reverse_Rx->SetValue(m_init_reverse_Rx); + + m_init_reverse_Ry = g_conf.pad_options[m_pad_id].reverse_ry; + m_cb_reverse_Ry->SetValue(m_init_reverse_Ry); + + m_init_mouse_Rjoy = g_conf.pad_options[m_pad_id].mouse_r; + m_cb_mouse_Rjoy->SetValue(m_init_mouse_Rjoy); + } +} diff --git a/pcsx2/PAD/Linux/wx_dialog/JoystickConfiguration.h b/pcsx2/PAD/Linux/wx_dialog/JoystickConfiguration.h new file mode 100644 index 0000000000..ba8dc0f9b8 --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/JoystickConfiguration.h @@ -0,0 +1,64 @@ +/* JoystickConfiguration.h + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#ifndef __JOYSTICKCONFIGURATION_H__ +#define __JOYSTICKCONFIGURATION_H__ + +#include + +#include "../GamePad.h" +#include "../keyboard.h" +#include "../onepad.h" + +static const s32 Lx_check_id = wxID_HIGHEST + 100 + 1; +static const s32 Ly_check_id = wxID_HIGHEST + 100 + 2; +static const s32 Ljoy_check_id = wxID_HIGHEST + 100 + 3; + +static const s32 Rx_check_id = wxID_HIGHEST + 100 + 4; +static const s32 Ry_check_id = wxID_HIGHEST + 100 + 5; +static const s32 Rjoy_check_id = wxID_HIGHEST + 100 + 6; + +class JoystickConfiguration : public wxDialog +{ + wxCheckBox *m_cb_reverse_Lx, *m_cb_reverse_Ly, *m_cb_reverse_Rx, *m_cb_reverse_Ry, + *m_cb_mouse_Ljoy, // Use mouse for left joystick + *m_cb_mouse_Rjoy; // Use mouse for right joystick + + u32 m_pad_id; + // isForLeftJoystick -> true is for Left Joystick, false is for Right Joystick + bool m_init_reverse_Lx, m_init_reverse_Ly, m_init_reverse_Rx, m_init_reverse_Ry, + m_init_mouse_Ljoy, m_init_mouse_Rjoy, m_isForLeftJoystick; + + // Methods + void repopulate(); + void reset(); + + // Events + void OnCheckboxChange(wxCommandEvent &); + void OnOk(wxCommandEvent &); + void OnCancel(wxCommandEvent &); + +public: + JoystickConfiguration(int, bool, wxWindow *); + void InitJoystickConfiguration(); +}; + +#endif // __JOYSTICKCONFIGURATION_H__ diff --git a/pcsx2/PAD/Linux/wx_dialog/dialog.cpp b/pcsx2/PAD/Linux/wx_dialog/dialog.cpp new file mode 100644 index 0000000000..fa8cd93366 --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/dialog.cpp @@ -0,0 +1,640 @@ +/* dialog.cpp + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "dialog.h" + +#ifdef __APPLE__ +#include + +static std::string KeyName(int pad, int key, int keysym) +{ + // Mouse + if (keysym >> 16) { + switch (keysym & 0xFFFF) { + case kCGMouseButtonLeft: + return "Mouse Left"; + case kCGMouseButtonRight: + return "Mouse Right"; + case kCGMouseButtonCenter: + return "Mouse Middle"; + default: // Use only number for extra button + return "Mouse " + std::to_string(keysym & 0xFFFF); + } + } + + switch (keysym) { + case kVK_ANSI_A: return "A"; + case kVK_ANSI_B: return "B"; + case kVK_ANSI_C: return "C"; + case kVK_ANSI_D: return "D"; + case kVK_ANSI_E: return "E"; + case kVK_ANSI_F: return "F"; + case kVK_ANSI_G: return "G"; + case kVK_ANSI_H: return "H"; + case kVK_ANSI_I: return "I"; + case kVK_ANSI_J: return "J"; + case kVK_ANSI_K: return "K"; + case kVK_ANSI_L: return "L"; + case kVK_ANSI_M: return "M"; + case kVK_ANSI_N: return "N"; + case kVK_ANSI_O: return "O"; + case kVK_ANSI_P: return "P"; + case kVK_ANSI_Q: return "Q"; + case kVK_ANSI_R: return "R"; + case kVK_ANSI_S: return "S"; + case kVK_ANSI_T: return "T"; + case kVK_ANSI_U: return "U"; + case kVK_ANSI_V: return "V"; + case kVK_ANSI_W: return "W"; + case kVK_ANSI_X: return "X"; + case kVK_ANSI_Y: return "Y"; + case kVK_ANSI_Z: return "Z"; + case kVK_ANSI_0: return "0"; + case kVK_ANSI_1: return "1"; + case kVK_ANSI_2: return "2"; + case kVK_ANSI_3: return "3"; + case kVK_ANSI_4: return "4"; + case kVK_ANSI_5: return "5"; + case kVK_ANSI_6: return "6"; + case kVK_ANSI_7: return "7"; + case kVK_ANSI_8: return "8"; + case kVK_ANSI_9: return "9"; + case kVK_ANSI_Grave: return "`"; + case kVK_ANSI_Minus: return "-"; + case kVK_ANSI_Equal: return "="; + case kVK_ANSI_LeftBracket: return "["; + case kVK_ANSI_RightBracket: return "]"; + case kVK_ANSI_Backslash: return "\\"; + case kVK_ANSI_Semicolon: return ";"; + case kVK_ANSI_Quote: return "'"; + case kVK_ANSI_Comma: return ","; + case kVK_ANSI_Period: return "."; + case kVK_ANSI_Slash: return "/"; + case kVK_Escape: return "⎋"; + case kVK_Tab: return "⇥"; + case kVK_Delete: return "⌫"; + case kVK_ForwardDelete: return "⌦"; + case kVK_Return: return "↩"; + case kVK_Space: return "␣"; + case kVK_ANSI_KeypadDecimal: return "Keypad ."; + case kVK_ANSI_KeypadMultiply: return "Keypad *"; + case kVK_ANSI_KeypadPlus: return "Keypad +"; + case kVK_ANSI_KeypadClear: return "⌧"; + case kVK_ANSI_KeypadDivide: return "Keypad /"; + case kVK_ANSI_KeypadEnter: return "⌤"; + case kVK_ANSI_KeypadMinus: return "Keypad -"; + case kVK_ANSI_KeypadEquals: return "Keypad ="; + case kVK_ANSI_Keypad0: return "Keypad 0"; + case kVK_ANSI_Keypad1: return "Keypad 1"; + case kVK_ANSI_Keypad2: return "Keypad 2"; + case kVK_ANSI_Keypad3: return "Keypad 3"; + case kVK_ANSI_Keypad4: return "Keypad 4"; + case kVK_ANSI_Keypad5: return "Keypad 5"; + case kVK_ANSI_Keypad6: return "Keypad 6"; + case kVK_ANSI_Keypad7: return "Keypad 7"; + case kVK_ANSI_Keypad8: return "Keypad 8"; + case kVK_ANSI_Keypad9: return "Keypad 9"; + case kVK_Command: return "Left ⌘"; + case kVK_Shift: return "Left ⇧"; + case kVK_CapsLock: return "⇪"; + case kVK_Option: return "Left ⌥"; + case kVK_Control: return "Left ⌃"; + case kVK_RightCommand: return "Right ⌘"; + case kVK_RightShift: return "Right ⇧"; + case kVK_RightOption: return "Right ⌥"; + case kVK_RightControl: return "Right ⌃"; + case kVK_Function: return "fn"; + case kVK_VolumeUp: return "Volume Up"; + case kVK_VolumeDown: return "Volume Down"; + case kVK_Mute: return "Mute"; + case kVK_F1: return "F1"; + case kVK_F2: return "F2"; + case kVK_F3: return "F3"; + case kVK_F4: return "F4"; + case kVK_F5: return "F5"; + case kVK_F6: return "F6"; + case kVK_F7: return "F7"; + case kVK_F8: return "F8"; + case kVK_F9: return "F9"; + case kVK_F10: return "F10"; + case kVK_F11: return "F11"; + case kVK_F12: return "F12"; + case kVK_F13: return "F13"; + case kVK_F14: return "F14"; + case kVK_F15: return "F15"; + case kVK_F16: return "F16"; + case kVK_F17: return "F17"; + case kVK_F18: return "F18"; + case kVK_F19: return "F19"; + case kVK_F20: return "F20"; + case kVK_Help: return "Help"; + case kVK_Home: return "↖"; + case kVK_PageUp: return "⇞"; + case kVK_End: return "↘"; + case kVK_PageDown: return "⇟"; + case kVK_LeftArrow: return "←"; + case kVK_RightArrow: return "→"; + case kVK_DownArrow: return "↓"; + case kVK_UpArrow: return "↑"; + case kVK_ISO_Section: return "Section"; + case kVK_JIS_Yen: return "¥"; + case kVK_JIS_Underscore: return "_"; + case kVK_JIS_KeypadComma: return "Keypad ,"; + case kVK_JIS_Eisu: return "英数"; + case kVK_JIS_Kana: return "かな"; + default: return "Key " + std::to_string(keysym); + } +} +#else +static std::string KeyName(int pad, int key, int keysym) +{ + // Mouse + if (keysym < 10) { + switch (keysym) { + case 0: + return ""; + case 1: + return "Mouse Left"; + case 2: + return "Mouse Middle"; + case 3: + return "Mouse Right"; + default: // Use only number for extra button + return "Mouse " + std::to_string(keysym); + } + } + + return std::string(XKeysymToString(keysym)); +} +#endif + +// Construtor of Dialog +Dialog::Dialog() + : wxDialog(NULL, // Parent + wxID_ANY, // ID + _T("OnePad configuration"), // Title + wxDefaultPosition, // Position + wxSize(DEFAULT_WIDTH, DEFAULT_HEIGHT), // Width + Lenght + // Style + wxSYSTEM_MENU | + wxCAPTION | + wxCLOSE_BOX | + wxCLIP_CHILDREN) +{ + + /* + * Define the size and the position of each button : + * padding[ButtonID][0] : Width + * padding[ButtonID][1] : Height + * padding[ButtonID][2] : x position + * padding[ButtonID][3] : y position + */ + int padding[BUTTONS_LENGHT][4]; + + // L1 + padding[PAD_L1][0] = 218; // Width + padding[PAD_L1][1] = 28; // Height + padding[PAD_L1][2] = 50; // X + padding[PAD_L1][3] = 175; // Y + + // L2 + padding[PAD_L2][0] = 218; // Width + padding[PAD_L2][1] = 28; // Height + padding[PAD_L2][2] = 50; // X + padding[PAD_L2][3] = 104; // Y + + // R1 + padding[PAD_R1][0] = 218; // Width + padding[PAD_R1][1] = 28; // Height + padding[PAD_R1][2] = 726; // X + padding[PAD_R1][3] = 175; // Y + + // R2 + padding[PAD_R2][0] = 218; // Width + padding[PAD_R2][1] = 28; // Height + padding[PAD_R2][2] = 726; // X + padding[PAD_R2][3] = 104; // Y + + // Triangle + padding[PAD_TRIANGLE][0] = 218; // Width + padding[PAD_TRIANGLE][1] = 28; // Height + padding[PAD_TRIANGLE][2] = 726; // X + padding[PAD_TRIANGLE][3] = 246; // Y + + // Circle + padding[PAD_CIRCLE][0] = 218; // Width + padding[PAD_CIRCLE][1] = 28; // Height + padding[PAD_CIRCLE][2] = 726; // X + padding[PAD_CIRCLE][3] = 319; // Y + + // Cross + padding[PAD_CROSS][0] = 218; // Width + padding[PAD_CROSS][1] = 28; // Height + padding[PAD_CROSS][2] = 726; // X + padding[PAD_CROSS][3] = 391; // Y + + // Square + padding[PAD_SQUARE][0] = 218; // Width + padding[PAD_SQUARE][1] = 28; // Height + padding[PAD_SQUARE][2] = 726; // X + padding[PAD_SQUARE][3] = 463; // Y + + // Directional pad up + padding[PAD_UP][0] = 100; // Width + padding[PAD_UP][1] = 25; // Height + padding[PAD_UP][2] = 108; // X + padding[PAD_UP][3] = 290; // Y + + // Directional pad down + padding[PAD_DOWN][0] = 100; // Width + padding[PAD_DOWN][1] = 25; // Height + padding[PAD_DOWN][2] = 108; // X + padding[PAD_DOWN][3] = 340; // Y + + // Directional pad right + padding[PAD_RIGHT][0] = 109; // Width + padding[PAD_RIGHT][1] = 25; // Height + padding[PAD_RIGHT][2] = 159; // X + padding[PAD_RIGHT][3] = 315; // Y + + // Directional pad left + padding[PAD_LEFT][0] = 109; // Width + padding[PAD_LEFT][1] = 25; // Height + padding[PAD_LEFT][2] = 50; // X + padding[PAD_LEFT][3] = 315; // Y + + // Left Joystick up + padding[PAD_L_UP][0] = 100; // Width + padding[PAD_L_UP][1] = 25; // Height + padding[PAD_L_UP][2] = 325; // X + padding[PAD_L_UP][3] = 527; // Y + + // Left Joystick down + padding[PAD_L_DOWN][0] = 100; // Width + padding[PAD_L_DOWN][1] = 25; // Height + padding[PAD_L_DOWN][2] = 325; // X + padding[PAD_L_DOWN][3] = 577; // Y + + // Left Joystick right + padding[PAD_L_RIGHT][0] = 109; // Width + padding[PAD_L_RIGHT][1] = 25; // Height + padding[PAD_L_RIGHT][2] = 377; // X + padding[PAD_L_RIGHT][3] = 552; // Y + + // Left Joystick left + padding[PAD_L_LEFT][0] = 109; // Width + padding[PAD_L_LEFT][1] = 25; // Height + padding[PAD_L_LEFT][2] = 268; // X + padding[PAD_L_LEFT][3] = 552; // Y + + // L3 + padding[PAD_L3][0] = 218; // Width + padding[PAD_L3][1] = 28; // Height + padding[PAD_L3][2] = 268; // X + padding[PAD_L3][3] = 641; // Y + + // Right Joystick up + padding[PAD_R_UP][0] = 100; // Width + padding[PAD_R_UP][1] = 25; // Height + padding[PAD_R_UP][2] = 555; // X + padding[PAD_R_UP][3] = 527; // Y + + // Right Joystick down + padding[PAD_R_DOWN][0] = 100; // Width + padding[PAD_R_DOWN][1] = 25; // Height + padding[PAD_R_DOWN][2] = 555; // X + padding[PAD_R_DOWN][3] = 577; // Y + + // Right Joystick right + padding[PAD_R_RIGHT][0] = 109; // Width + padding[PAD_R_RIGHT][1] = 25; // Height + padding[PAD_R_RIGHT][2] = 607; // X + padding[PAD_R_RIGHT][3] = 552; // Y + + // Right Joystick left + padding[PAD_R_LEFT][0] = 109; // Width + padding[PAD_R_LEFT][1] = 25; // Height + padding[PAD_R_LEFT][2] = 498; // X + padding[PAD_R_LEFT][3] = 552; // Y + + // R3 + padding[PAD_R3][0] = 218; // Width + padding[PAD_R3][1] = 28; // Height + padding[PAD_R3][2] = 498; // X + padding[PAD_R3][3] = 641; // Y + + // Start + padding[PAD_START][0] = 218; // Width + padding[PAD_START][1] = 28; // Height + padding[PAD_START][2] = 503; // X + padding[PAD_START][3] = 34; // Y + + // Select + padding[PAD_SELECT][0] = 218; // Width + padding[PAD_SELECT][1] = 28; // Height + padding[PAD_SELECT][2] = 273; // X + padding[PAD_SELECT][3] = 34; // Y + + // Analog + padding[Analog][0] = 218; // Width + padding[Analog][1] = 28; // Height + padding[Analog][2] = 50; // X + padding[Analog][3] = 452; // Y + + // Left Joystick Configuration + padding[JoyL_config][0] = 180; // Width + padding[JoyL_config][1] = 28; // Height + padding[JoyL_config][2] = 50; // X + padding[JoyL_config][3] = 550; // Y + + // Right Joystick Configuration + padding[JoyR_config][0] = 180; // Width + padding[JoyR_config][1] = 28; // Height + padding[JoyR_config][2] = 764; // X + padding[JoyR_config][3] = 550; // Y + + // Gamepad Configuration + padding[Gamepad_config][0] = 180; // Width + padding[Gamepad_config][1] = 28; // Height + padding[Gamepad_config][2] = 50; // X + padding[Gamepad_config][3] = 585; // Y + + // Set All Buttons + padding[Set_all][0] = 180; // Width + padding[Set_all][1] = 28; // Height + padding[Set_all][2] = 764; // X + padding[Set_all][3] = 585; // Y + + // Apply modifications without exit + padding[Apply][0] = 70; // Width + padding[Apply][1] = 28; // Height + padding[Apply][2] = 833; // X + padding[Apply][3] = 642; // Y + + // Ok button + padding[Ok][0] = 70; // Width + padding[Ok][1] = 28; // Height + padding[Ok][2] = 913; // X + padding[Ok][3] = 642; // Y + + // Cancel button + padding[Cancel][0] = 70; // Width + padding[Cancel][1] = 28; // Height + padding[Cancel][2] = 753; // X + padding[Cancel][3] = 642; // Y + + // create a new Notebook + m_tab_gamepad = new wxNotebook(this, wxID_ANY); + for (int i = 0; i < GAMEPAD_NUMBER; ++i) { + // Tabs panels + m_pan_tabs[i] = new opPanel( + m_tab_gamepad, + wxID_ANY, + wxDefaultPosition, + wxSize(DEFAULT_WIDTH, DEFAULT_HEIGHT)); + // Add new page + // Define label + std::stringstream sstm; + std::string label = "Gamepad "; + sstm << label << i; + // New page creation + m_tab_gamepad->AddPage( + m_pan_tabs[i], // Parent + wxString(sstm.str().c_str(), wxConvUTF8) // Title + ); + + for (int j = 0; j < BUTTONS_LENGHT; ++j) { + // Gamepad buttons + m_bt_gamepad[i][j] = new wxButton( + m_pan_tabs[i], // Parent + wxID_HIGHEST + j + 1, // ID + _T("Undefined"), // Label + wxPoint(padding[j][2], padding[j][3]), // Position + wxSize(padding[j][0], padding[j][1]) // Size + ); + } + // Redefine others gui buttons label + m_bt_gamepad[i][JoyL_config]->SetLabel(_T("&Left Joystick Config")); + m_bt_gamepad[i][JoyR_config]->SetLabel(_T("&Right Joystick Config")); + m_bt_gamepad[i][Gamepad_config]->SetLabel(_T("&Gamepad Configuration")); + m_bt_gamepad[i][Set_all]->SetLabel(_T("&Set All Buttons")); + m_bt_gamepad[i][Cancel]->SetLabel(_T("&Cancel")); + m_bt_gamepad[i][Apply]->SetLabel(_T("&Apply")); + m_bt_gamepad[i][Ok]->SetLabel(_T("&Ok")); + + // Disable analog button (not yet supported) + m_bt_gamepad[i][Analog]->Disable(); + } + + Bind(wxEVT_BUTTON, &Dialog::OnButtonClicked, this); + + for (int i = 0; i < GAMEPAD_NUMBER; ++i) { + for (int j = 0; j < NB_IMG; ++j) { + m_pressed[i][j] = false; + } + } +} + +void Dialog::InitDialog() +{ + GamePad::EnumerateGamePads(s_vgamePad); // activate gamepads + LoadConfig(); // Load configuration from the ini file + repopulate(); // Set label and fit simulated key array +} + +/****************************************/ +/*********** Events functions ***********/ +/****************************************/ + +void Dialog::OnButtonClicked(wxCommandEvent &event) +{ + // Affichage d'un message à chaque clic sur le bouton + wxButton *bt_tmp = (wxButton *)event.GetEventObject(); // get the button object + int bt_id = bt_tmp->GetId() - wxID_HIGHEST - 1; // get the real ID + int gamepad_id = m_tab_gamepad->GetSelection(); // get the tab ID (equivalent to the gamepad id) + if (bt_id >= 0 && bt_id <= PAD_R_LEFT) { // if the button ID is a gamepad button + bt_tmp->Disable(); // switch the button state to "Disable" + config_key(gamepad_id, bt_id); + bt_tmp->Enable(); // switch the button state to "Enable" + } else if (bt_id == Gamepad_config) { // If the button ID is equals to the Gamepad_config button ID + GamepadConfiguration gamepad_config(gamepad_id, this); + + gamepad_config.InitGamepadConfiguration(); + gamepad_config.ShowModal(); + } else if (bt_id == JoyL_config) { // If the button ID is equals to the JoyL_config button ID + JoystickConfiguration joystick_config(gamepad_id, true, this); + + joystick_config.InitJoystickConfiguration(); + joystick_config.ShowModal(); + } else if (bt_id == JoyR_config) { // If the button ID is equals to the JoyR_config button ID + JoystickConfiguration joystick_config(gamepad_id, false, this); + + joystick_config.InitJoystickConfiguration(); + joystick_config.ShowModal(); + } else if (bt_id == Set_all) { // If the button ID is equals to the Set_all button ID + for (int i = 0; i < MAX_KEYS; ++i) { + bt_tmp = m_bt_gamepad[gamepad_id][i]; + switch (i) { + case PAD_L_UP: // Left joystick (Up) ↑ + m_pan_tabs[gamepad_id]->ShowImg(img_l_arrow_up); + break; + case PAD_L_RIGHT: // Left joystick (Right) → + m_pan_tabs[gamepad_id]->ShowImg(img_l_arrow_right); + break; + case PAD_L_DOWN: // Left joystick (Down) ↓ + m_pan_tabs[gamepad_id]->ShowImg(img_l_arrow_bottom); + break; + case PAD_L_LEFT: // Left joystick (Left) ← + m_pan_tabs[gamepad_id]->ShowImg(img_l_arrow_left); + break; + case PAD_R_UP: // Right joystick (Up) ↑ + m_pan_tabs[gamepad_id]->ShowImg(img_r_arrow_up); + break; + case PAD_R_RIGHT: // Right joystick (Right) → + m_pan_tabs[gamepad_id]->ShowImg(img_r_arrow_right); + break; + case PAD_R_DOWN: // Right joystick (Down) ↓ + m_pan_tabs[gamepad_id]->ShowImg(img_r_arrow_bottom); + break; + case PAD_R_LEFT: // Right joystick (Left) ← + m_pan_tabs[gamepad_id]->ShowImg(img_r_arrow_left); + break; + default: + m_pan_tabs[gamepad_id]->ShowImg(i); + break; + } + m_pan_tabs[gamepad_id]->Refresh(); + m_pan_tabs[gamepad_id]->Update(); + config_key(gamepad_id, i); + switch (i) { + case PAD_L_UP: // Left joystick (Up) ↑ + m_pan_tabs[gamepad_id]->HideImg(img_l_arrow_up); + break; + case PAD_L_RIGHT: // Left joystick (Right) → + m_pan_tabs[gamepad_id]->HideImg(img_l_arrow_right); + break; + case PAD_L_DOWN: // Left joystick (Down) ↓ + m_pan_tabs[gamepad_id]->HideImg(img_l_arrow_bottom); + break; + case PAD_L_LEFT: // Left joystick (Left) ← + m_pan_tabs[gamepad_id]->HideImg(img_l_arrow_left); + break; + case PAD_R_UP: // Right joystick (Up) ↑ + m_pan_tabs[gamepad_id]->HideImg(img_r_arrow_up); + break; + case PAD_R_RIGHT: // Right joystick (Right) → + m_pan_tabs[gamepad_id]->HideImg(img_r_arrow_right); + break; + case PAD_R_DOWN: // Right joystick (Down) ↓ + m_pan_tabs[gamepad_id]->HideImg(img_r_arrow_bottom); + break; + case PAD_R_LEFT: // Right joystick (Left) ← + m_pan_tabs[gamepad_id]->HideImg(img_r_arrow_left); + break; + default: + m_pan_tabs[gamepad_id]->HideImg(i); + break; + } + m_pan_tabs[gamepad_id]->Refresh(); + m_pan_tabs[gamepad_id]->Update(); + usleep(500000); // give enough time to the user to release the button + } + } else if (bt_id == Ok) { // If the button ID is equals to the Ok button ID + SaveConfig(); // Save the configuration + Close(); // Close the window + } else if (bt_id == Apply) { // If the button ID is equals to the Apply button ID + SaveConfig(); // Save the configuration + } else if (bt_id == Cancel) { // If the button ID is equals to the cancel button ID + Close(); // Close the window + } +} + +/****************************************/ +/*********** Methods functions **********/ +/****************************************/ + +void Dialog::config_key(int pad, int key) +{ + bool captured = false; + u32 key_pressed = 0; + + while (!captured) { + if (PollForNewKeyboardKeys(key_pressed)) { + // special case for keyboard/mouse to handle multiple keys + // Note: key_pressed == 0 when ESC is hit to abort the capture + if (key_pressed > 0) { + clear_key(pad, key); + set_keyboard_key(pad, key_pressed, key); + m_simulatedKeys[pad][key] = key_pressed; + } + captured = true; + } + } + m_bt_gamepad[pad][key]->SetLabel( + KeyName(pad, key, m_simulatedKeys[pad][key]).c_str()); +} + +void Dialog::clear_key(int pad, int key) +{ + // Erase the keyboard binded key + u32 keysim = m_simulatedKeys[pad][key]; + m_simulatedKeys[pad][key] = 0; + + // erase gamepad entry (keysim map) + g_conf.keysym_map[pad].erase(keysim); +} + + +// Set button values +void Dialog::repopulate() +{ + for (int gamepad_id = 0; gamepad_id < GAMEPAD_NUMBER; ++gamepad_id) { + // keyboard/mouse key + for (const auto &it : g_conf.keysym_map[gamepad_id]) { + int keysym = it.first; + int key = it.second; + + m_bt_gamepad[gamepad_id][key]->SetLabel( + KeyName(gamepad_id, key, keysym).c_str()); + + m_simulatedKeys[gamepad_id][key] = keysym; + } + } +} + +// Main +void DisplayDialog() +{ + if (g_conf.ftw) { + wxString info("The OnePad GUI is provided to map the keyboard/mouse to the virtual PS2 pad.\n\n" + "Gamepads/Joysticks are plug and play. The active gamepad can be selected in the 'Gamepad Configuration' panel.\n\n" + "If you prefer to manually map your gamepad, you should use the 'onepad-legacy' plugin instead."); + + wxMessageDialog ftw(nullptr, info); + ftw.ShowModal(); + + g_conf.ftw = 0; + SaveConfig(); + } + + Dialog dialog; + + dialog.InitDialog(); + dialog.ShowModal(); +} diff --git a/pcsx2/PAD/Linux/wx_dialog/dialog.h b/pcsx2/PAD/Linux/wx_dialog/dialog.h new file mode 100644 index 0000000000..ac0228b552 --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/dialog.h @@ -0,0 +1,98 @@ +/* dialog.h + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#ifndef __DIALOG_H__ +#define __DIALOG_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../GamePad.h" +#include "../keyboard.h" +#include "../onepad.h" +#include "opPanel.h" + +#include "GamepadConfiguration.h" +#include "JoystickConfiguration.h" + +// Allow to found quickly button id +// e.g L2 → 0, triangle → 4, ... +// see onepad.h for more details about gamepad button id + +enum gui_buttons { + Analog = PAD_R_LEFT + 1, // Analog button (not yet supported ?) + JoyL_config, // Left Joystick Configuration + JoyR_config, // Right Joystick Configuration + Gamepad_config, // Gamepad Configuration + Set_all, // Set all buttons + Apply, // Apply modifications without exit + Ok, // Apply modifications and exit + Cancel // Exit without apply modificatons +}; + +#define BUTTONS_LENGHT 32 // numbers of buttons on the gamepad +#define UPDATE_TIME 5 +#define DEFAULT_WIDTH 1000 +#define DEFAULT_HEIGHT 740 + +class Dialog : public wxDialog +{ + // Panels + opPanel *m_pan_tabs[GAMEPAD_NUMBER]; // Gamepad Tabs box + // Notebooks + wxNotebook *m_tab_gamepad; // Joysticks Tabs + // Buttons + wxButton *m_bt_gamepad[GAMEPAD_NUMBER][BUTTONS_LENGHT]; // Joystick button use to modify the button mapping + // Contain all simulated key + u32 m_simulatedKeys[GAMEPAD_NUMBER][MAX_KEYS]; + // Timer + wxTimer m_time_update_gui; + // Check if the gui must display feddback image + bool m_pressed[GAMEPAD_NUMBER][NB_IMG]; + + // methods + void config_key(int, int); + void clear_key(int, int); + void repopulate(); + + // Events + void OnButtonClicked(wxCommandEvent &); + void JoystickEvent(wxTimerEvent &); + +public: + Dialog(); + void InitDialog(); + void show(); +}; + +extern void DisplayDialog(); // Main function + +#endif // __DIALOG_H__ diff --git a/pcsx2/PAD/Linux/wx_dialog/opPanel.cpp b/pcsx2/PAD/Linux/wx_dialog/opPanel.cpp new file mode 100644 index 0000000000..dfc2a4dafe --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/opPanel.cpp @@ -0,0 +1,237 @@ +/* opPanel.cpp + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "opPanel.h" +#include "ImgHeader/dualshock2.h" +#include "ImgHeader/cross.h" +#include "ImgHeader/circle.h" +#include "ImgHeader/square.h" +#include "ImgHeader/triangle.h" +#include "ImgHeader/dp_left.h" +#include "ImgHeader/dp_right.h" +#include "ImgHeader/dp_up.h" +#include "ImgHeader/dp_bottom.h" +#include "ImgHeader/l1.h" +#include "ImgHeader/r1.h" +#include "ImgHeader/l2.h" +#include "ImgHeader/l3.h" +#include "ImgHeader/r2.h" +#include "ImgHeader/r3.h" +#include "ImgHeader/start.h" +#include "ImgHeader/select.h" +#include "ImgHeader/analog.h" +#include "ImgHeader/joystick_cursor.h" +#include "ImgHeader/arrow_up.h" +#include "ImgHeader/arrow_right.h" +#include "ImgHeader/arrow_bottom.h" +#include "ImgHeader/arrow_left.h" + +opPanel::opPanel(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize) + : wxPanel(parent, id, pos, size) +{ + m_picture[img_background] = EmbeddedImage().Get(); + + m_picture[img_start] = EmbeddedImage().Get(); + m_picture[img_select] = EmbeddedImage().Get(); + m_picture[img_analog] = EmbeddedImage().Get(); + + m_picture[img_dp_left] = EmbeddedImage().Get(); + m_picture[img_dp_right] = EmbeddedImage().Get(); + m_picture[img_dp_up] = EmbeddedImage().Get(); + m_picture[img_dp_bottom] = EmbeddedImage().Get(); + + m_picture[img_square] = EmbeddedImage().Get(); + m_picture[img_circle] = EmbeddedImage().Get(); + m_picture[img_cross] = EmbeddedImage().Get(); + m_picture[img_triangle] = EmbeddedImage().Get(); + + m_picture[img_l1] = EmbeddedImage().Get(); + m_picture[img_l3] = EmbeddedImage().Get(); + m_picture[img_l2] = EmbeddedImage().Get(); + + m_picture[img_r1] = EmbeddedImage().Get(); + m_picture[img_r3] = EmbeddedImage().Get(); + m_picture[img_r2] = EmbeddedImage().Get(); + + m_picture[img_left_cursor] = EmbeddedImage().Get(); + m_picture[img_right_cursor] = EmbeddedImage().Get(); + + m_picture[img_l_arrow_up] = EmbeddedImage().Get(); + m_picture[img_l_arrow_right] = EmbeddedImage().Get(); + m_picture[img_l_arrow_bottom] = EmbeddedImage().Get(); + m_picture[img_l_arrow_left] = EmbeddedImage().Get(); + + m_picture[img_r_arrow_up] = EmbeddedImage().Get(); + m_picture[img_r_arrow_right] = EmbeddedImage().Get(); + m_picture[img_r_arrow_bottom] = EmbeddedImage().Get(); + m_picture[img_r_arrow_left] = EmbeddedImage().Get(); + + for (int i = 0; i < NB_IMG; ++i) { + m_show_image[i] = false; + HideImg(i); + } + ShowImg(img_background); + m_show_image[img_background] = true; + + m_left_cursor_x = 0; + m_left_cursor_y = 0; + m_right_cursor_x = 0; + m_right_cursor_y = 0; +} + +void opPanel::HideImg(int id) +{ + if (id < NB_IMG) { + m_show_image[id] = false; + Refresh(); + } +} + +void opPanel::ShowImg(int id) +{ + if (id < NB_IMG) { + m_show_image[id] = true; + Refresh(); + } +} + +void opPanel::MoveJoystick(int axe, int value) +{ + if (axe == 0) { + m_left_cursor_x = value * 30 / 40000; + } else if (axe == 1) { + m_left_cursor_y = value * 30 / 40000; + } else if (axe == 2) { + m_right_cursor_x = value * 30 / 40000; + } else { + m_right_cursor_y = value * 30 / 40000; + } +} + +wxBEGIN_EVENT_TABLE(opPanel, wxPanel) +EVT_PAINT(opPanel::OnPaint) +wxEND_EVENT_TABLE() + +void opPanel::OnPaint(wxPaintEvent &event) +{ + wxPaintDC dc(this); + + wxMemoryDC temp_background, temp_start, temp_select, temp_analog, temp_dp_left, + temp_dp_right, temp_dp_up, temp_dp_bottom, temp_l1, temp_r1, temp_L3, temp_l2_2, + temp_R3, temp_r2_2, temp_square, temp_circle, temp_cross, temp_triangle, + temp_left_cursor, temp_right_cursor, temp_l_arrow_up, temp_l_arrow_right, + temp_l_arrow_bottom, temp_l_arrow_left, temp_r_arrow_up, temp_r_arrow_right, + temp_r_arrow_bottom, temp_r_arrow_left; + + temp_background.SelectObject(m_picture[img_background]); + temp_start.SelectObject(m_picture[img_start]); + temp_select.SelectObject(m_picture[img_select]); + temp_analog.SelectObject(m_picture[img_analog]); + temp_dp_left.SelectObject(m_picture[img_dp_left]); + + temp_dp_right.SelectObject(m_picture[img_dp_right]); + temp_dp_up.SelectObject(m_picture[img_dp_up]); + temp_dp_bottom.SelectObject(m_picture[img_dp_bottom]); + temp_l1.SelectObject(m_picture[img_l1]); + temp_r1.SelectObject(m_picture[img_r1]); + temp_L3.SelectObject(m_picture[img_l3]); + temp_l2_2.SelectObject(m_picture[img_l2]); + + temp_R3.SelectObject(m_picture[img_r3]); + temp_r2_2.SelectObject(m_picture[img_r2]); + temp_square.SelectObject(m_picture[img_square]); + temp_circle.SelectObject(m_picture[img_circle]); + temp_cross.SelectObject(m_picture[img_cross]); + temp_triangle.SelectObject(m_picture[img_triangle]); + + temp_left_cursor.SelectObject(m_picture[img_left_cursor]); + temp_right_cursor.SelectObject(m_picture[img_right_cursor]); + + temp_l_arrow_up.SelectObject(m_picture[img_l_arrow_up]); + temp_l_arrow_right.SelectObject(m_picture[img_l_arrow_right]); + temp_l_arrow_bottom.SelectObject(m_picture[img_l_arrow_bottom]); + temp_l_arrow_left.SelectObject(m_picture[img_l_arrow_left]); + + temp_r_arrow_up.SelectObject(m_picture[img_r_arrow_up]); + temp_r_arrow_right.SelectObject(m_picture[img_r_arrow_right]); + temp_r_arrow_bottom.SelectObject(m_picture[img_r_arrow_bottom]); + temp_r_arrow_left.SelectObject(m_picture[img_r_arrow_left]); + + if (m_show_image[img_background]) + dc.Blit(wxPoint(0, 0), temp_background.GetSize(), &temp_background, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_start]) + dc.Blit(wxPoint(526, 296), temp_start.GetSize(), &temp_start, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_select]) + dc.Blit(wxPoint(450, 297), temp_select.GetSize(), &temp_select, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_analog]) + dc.Blit(wxPoint(489, 358), temp_analog.GetSize(), &temp_analog, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_dp_left]) + dc.Blit(wxPoint(334, 292), temp_dp_left.GetSize(), &temp_dp_left, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_dp_right]) + dc.Blit(wxPoint(378, 292), temp_dp_right.GetSize(), &temp_dp_right, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_dp_up]) + dc.Blit(wxPoint(358, 269), temp_dp_up.GetSize(), &temp_dp_up, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_dp_bottom]) + dc.Blit(wxPoint(358, 312), temp_dp_bottom.GetSize(), &temp_dp_bottom, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_l1]) + dc.Blit(wxPoint(343, 186), temp_l1.GetSize(), &temp_l1, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_r1]) + dc.Blit(wxPoint(593, 186), temp_r1.GetSize(), &temp_r1, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_l3]) + dc.Blit(wxPoint(409, 344), temp_L3.GetSize(), &temp_L3, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_l2]) + dc.Blit(wxPoint(346, 158), temp_l2_2.GetSize(), &temp_l2_2, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_r3]) + dc.Blit(wxPoint(525, 344), temp_R3.GetSize(), &temp_R3, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_r2]) + dc.Blit(wxPoint(582, 158), temp_r2_2.GetSize(), &temp_r2_2, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_square]) + dc.Blit(wxPoint(573, 287), temp_square.GetSize(), &temp_square, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_circle]) + dc.Blit(wxPoint(647, 287), temp_circle.GetSize(), &temp_circle, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_cross]) + dc.Blit(wxPoint(610, 324), temp_cross.GetSize(), &temp_cross, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_triangle]) + dc.Blit(wxPoint(610, 250), temp_triangle.GetSize(), &temp_triangle, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_left_cursor]) + dc.Blit(wxPoint(439 + m_left_cursor_x, 374 + m_left_cursor_y), temp_left_cursor.GetSize(), &temp_left_cursor, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_right_cursor]) + dc.Blit(wxPoint(555 + m_right_cursor_x, 374 + m_right_cursor_y), temp_right_cursor.GetSize(), &temp_right_cursor, wxPoint(0, 0), wxCOPY, true); + + if (m_show_image[img_l_arrow_up]) + dc.Blit(wxPoint(433, 357), temp_l_arrow_up.GetSize(), &temp_l_arrow_up, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_l_arrow_right]) + dc.Blit(wxPoint(423, 368), temp_l_arrow_right.GetSize(), &temp_l_arrow_right, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_l_arrow_bottom]) + dc.Blit(wxPoint(433, 357), temp_l_arrow_bottom.GetSize(), &temp_l_arrow_bottom, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_l_arrow_left]) + dc.Blit(wxPoint(423, 368), temp_l_arrow_left.GetSize(), &temp_l_arrow_left, wxPoint(0, 0), wxCOPY, true); + + if (m_show_image[img_r_arrow_up]) + dc.Blit(wxPoint(548, 357), temp_r_arrow_up.GetSize(), &temp_r_arrow_up, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_r_arrow_right]) + dc.Blit(wxPoint(539, 368), temp_r_arrow_right.GetSize(), &temp_r_arrow_right, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_r_arrow_bottom]) + dc.Blit(wxPoint(548, 357), temp_r_arrow_bottom.GetSize(), &temp_r_arrow_bottom, wxPoint(0, 0), wxCOPY, true); + if (m_show_image[img_r_arrow_left]) + dc.Blit(wxPoint(539, 368), temp_r_arrow_left.GetSize(), &temp_r_arrow_left, wxPoint(0, 0), wxCOPY, true); +} diff --git a/pcsx2/PAD/Linux/wx_dialog/opPanel.h b/pcsx2/PAD/Linux/wx_dialog/opPanel.h new file mode 100644 index 0000000000..ba8fa902ea --- /dev/null +++ b/pcsx2/PAD/Linux/wx_dialog/opPanel.h @@ -0,0 +1,77 @@ +/* opPanel.h + * PCSX2 Dev Team + * Copyright (C) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +#ifndef __OPPANEL_H__ +#define __OPPANEL_H__ + +#include + +#include "EmbeddedImage.h" + +enum gui_img { + img_l2, + img_r2, + img_l1, + img_r1, + img_triangle, + img_circle, + img_cross, + img_square, + img_select, + img_l3, + img_r3, + img_start, + img_dp_up, + img_dp_right, + img_dp_bottom, + img_dp_left, + img_left_cursor, + img_right_cursor, + img_analog, + img_background, // background pic + img_l_arrow_up, + img_l_arrow_right, + img_l_arrow_bottom, + img_l_arrow_left, + img_r_arrow_up, + img_r_arrow_right, + img_r_arrow_bottom, + img_r_arrow_left +}; + +#define NB_IMG 28 + +class opPanel : public wxPanel +{ + wxBitmap m_picture[NB_IMG]; + bool m_show_image[NB_IMG]; + int m_left_cursor_x, m_left_cursor_y, m_right_cursor_x, m_right_cursor_y; + wxDECLARE_EVENT_TABLE(); + void OnPaint(wxPaintEvent &event); + +public: + opPanel(wxWindow *, wxWindowID, const wxPoint &, const wxSize &); + void HideImg(int); + void ShowImg(int); + void MoveJoystick(int, int); +}; + +#endif // __OPPANEL_H__