Merge pull request #16 from shinyquagsire23/hid-sharedmem-impl-start

HID Sharedmem Impl Start
merge-requests/60/head
bunnei 2018-01-15 12:54:54 +07:00 committed by GitHub
commit 325f72aceb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 692 additions and 119 deletions

@ -2,7 +2,10 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <atomic>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core_timing.h"
#include "core/frontend/input.h"
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
@ -13,6 +16,12 @@
namespace Service { namespace Service {
namespace HID { namespace HID {
// Updating period for each HID device.
// TODO(shinyquagsire23): These need better values.
constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 234;
constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 104;
constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 101;
class IAppletResource final : public ServiceFramework<IAppletResource> { class IAppletResource final : public ServiceFramework<IAppletResource> {
public: public:
IAppletResource() : ServiceFramework("IAppletResource") { IAppletResource() : ServiceFramework("IAppletResource") {
@ -24,6 +33,15 @@ public:
shared_mem = Kernel::SharedMemory::Create( shared_mem = Kernel::SharedMemory::Create(
nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read, nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read,
0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
// Register update callbacks
pad_update_event = CoreTiming::RegisterEvent(
"HID::UpdatePadCallback",
[this](u64 userdata, int cycles_late) { UpdatePadCallback(userdata, cycles_late); });
// TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
} }
private: private:
@ -34,8 +52,76 @@ private:
LOG_DEBUG(Service, "called"); LOG_DEBUG(Service, "called");
} }
void LoadInputDevices() {
std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
// TODO(shinyquagsire23): sticks, gyro, touch, mouse, keyboard
}
void UpdatePadCallback(u64 userdata, int cycles_late) {
SharedMemory* mem = reinterpret_cast<SharedMemory*>(shared_mem->GetPointer());
if (is_device_reload_pending.exchange(false))
LoadInputDevices();
// TODO(shinyquagsire23): This is a hack!
ControllerPadState& state =
mem->controllers[Controller_Handheld].layouts[Layout_Default].entries[0].buttons;
using namespace Settings::NativeButton;
state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus());
state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus());
state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus());
state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus());
state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus());
state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus());
state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus());
// TODO(shinyquagsire23): Analog stick vals
// TODO(shinyquagsire23): Update pad info proper, (circular buffers, timestamps, layouts)
// TODO(shinyquagsire23): Update touch info
// TODO(shinyquagsire23): Signal events
// Reschedule recurrent event
CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
}
// Handle to shared memory region designated to HID service // Handle to shared memory region designated to HID service
Kernel::SharedPtr<Kernel::SharedMemory> shared_mem; Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
// CoreTiming update events
CoreTiming::EventType* pad_update_event;
// Stored input state info
std::atomic<bool> is_device_reload_pending{true};
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
buttons;
}; };
class Hid final : public ServiceFramework<Hid> { class Hid final : public ServiceFramework<Hid> {

@ -5,10 +5,322 @@
#pragma once #pragma once
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "core/settings.h"
namespace Service { namespace Service {
namespace HID { namespace HID {
// Begin enums and output structs
enum ControllerType : u32 {
ControllerType_ProController = 1 << 0,
ControllerType_Handheld = 1 << 1,
ControllerType_JoyconPair = 1 << 2,
ControllerType_JoyconLeft = 1 << 3,
ControllerType_JoyconRight = 1 << 4,
};
enum ControllerLayoutType : u32 {
Layout_ProController = 0, // Pro Controller or HID gamepad
Layout_Handheld = 1, // Two Joy-Con docked to rails
Layout_Single = 2, // Horizontal single Joy-Con or pair of Joy-Con, adjusted for orientation
Layout_Left = 3, // Only raw left Joy-Con state, no orientation adjustment
Layout_Right = 4, // Only raw right Joy-Con state, no orientation adjustment
Layout_DefaultDigital = 5, // Same as next, but sticks have 8-direction values only
Layout_Default = 6, // Safe default, single Joy-Con have buttons/sticks rotated for orientation
};
enum ControllerColorDescription {
ColorDesc_ColorsNonexistent = 1 << 1,
};
enum ControllerConnectionState {
ConnectionState_Connected = 1 << 0,
ConnectionState_Wired = 1 << 1,
};
enum ControllerID {
Controller_Player1 = 0,
Controller_Player2 = 1,
Controller_Player3 = 2,
Controller_Player4 = 3,
Controller_Player5 = 4,
Controller_Player6 = 5,
Controller_Player7 = 6,
Controller_Player8 = 7,
Controller_Handheld = 8,
Controller_Unknown = 9,
};
// End enums and output structs
// Begin TouchScreen
struct TouchScreenHeader {
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
u64 timestamp;
};
static_assert(sizeof(TouchScreenHeader) == 0x28,
"HID touch screen header structure has incorrect size");
struct TouchScreenEntryHeader {
u64 timestamp;
u64 numTouches;
};
static_assert(sizeof(TouchScreenEntryHeader) == 0x10,
"HID touch screen entry header structure has incorrect size");
struct TouchScreenEntryTouch {
u64 timestamp;
u32 padding;
u32 touchIndex;
u32 x;
u32 y;
u32 diameterX;
u32 diameterY;
u32 angle;
u32 padding_2;
};
static_assert(sizeof(TouchScreenEntryTouch) == 0x28,
"HID touch screen touch structure has incorrect size");
struct TouchScreenEntry {
TouchScreenEntryHeader header;
std::array<TouchScreenEntryTouch, 16> touches;
u64 unk;
};
static_assert(sizeof(TouchScreenEntry) == 0x298,
"HID touch screen entry structure has incorrect size");
struct TouchScreen {
TouchScreenHeader header;
std::array<TouchScreenEntry, 17> entries;
std::array<u8, 0x3c0> padding;
};
static_assert(sizeof(TouchScreen) == 0x3000, "HID touch screen structure has incorrect size");
// End TouchScreen
// Begin Mouse
struct MouseHeader {
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
};
static_assert(sizeof(MouseHeader) == 0x20, "HID mouse header structure has incorrect size");
struct MouseButtonState {
union {
u64 hex{};
// Buttons
BitField<0, 1, u64> left;
BitField<1, 1, u64> right;
BitField<2, 1, u64> middle;
BitField<3, 1, u64> forward;
BitField<4, 1, u64> back;
};
};
struct MouseEntry {
u64 timestamp;
u64 timestamp_2;
u32 x;
u32 y;
u32 velocityX;
u32 velocityY;
u32 scrollVelocityX;
u32 scrollVelocityY;
MouseButtonState buttons;
};
static_assert(sizeof(MouseEntry) == 0x30, "HID mouse entry structure has incorrect size");
struct Mouse {
MouseHeader header;
std::array<MouseEntry, 17> entries;
std::array<u8, 0xB0> padding;
};
static_assert(sizeof(Mouse) == 0x400, "HID mouse structure has incorrect size");
// End Mouse
// Begin Keyboard
struct KeyboardHeader {
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
};
static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size");
struct KeyboardModifierKeyState {
union {
u64 hex{};
// Buttons
BitField<0, 1, u64> lctrl;
BitField<1, 1, u64> lshift;
BitField<2, 1, u64> lalt;
BitField<3, 1, u64> lmeta;
BitField<4, 1, u64> rctrl;
BitField<5, 1, u64> rshift;
BitField<6, 1, u64> ralt;
BitField<7, 1, u64> rmeta;
BitField<8, 1, u64> capslock;
BitField<9, 1, u64> scrolllock;
BitField<10, 1, u64> numlock;
};
};
struct KeyboardEntry {
u64 timestamp;
u64 timestamp_2;
KeyboardModifierKeyState modifier;
u32 keys[8];
};
static_assert(sizeof(KeyboardEntry) == 0x38, "HID keyboard entry structure has incorrect size");
struct Keyboard {
KeyboardHeader header;
std::array<KeyboardEntry, 17> entries;
std::array<u8, 0x28> padding;
};
static_assert(sizeof(Keyboard) == 0x400, "HID keyboard structure has incorrect size");
// End Keyboard
// Begin Controller
struct ControllerMAC {
u64 timestamp;
std::array<u8, 0x8> mac;
u64 unk;
u64 timestamp_2;
};
static_assert(sizeof(ControllerMAC) == 0x20, "HID controller MAC structure has incorrect size");
struct ControllerHeader {
u32 type;
u32 isHalf;
u32 singleColorsDescriptor;
u32 singleColorBody;
u32 singleColorButtons;
u32 splitColorsDescriptor;
u32 leftColorBody;
u32 leftColorButtons;
u32 rightColorBody;
u32 rightColorbuttons;
};
static_assert(sizeof(ControllerHeader) == 0x28,
"HID controller header structure has incorrect size");
struct ControllerLayoutHeader {
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
};
static_assert(sizeof(ControllerLayoutHeader) == 0x20,
"HID controller layout header structure has incorrect size");
struct ControllerPadState {
union {
u64 hex{};
// Buttons
BitField<0, 1, u64> a;
BitField<1, 1, u64> b;
BitField<2, 1, u64> x;
BitField<3, 1, u64> y;
BitField<4, 1, u64> lstick;
BitField<5, 1, u64> rstick;
BitField<6, 1, u64> l;
BitField<7, 1, u64> r;
BitField<8, 1, u64> zl;
BitField<9, 1, u64> zr;
BitField<10, 1, u64> plus;
BitField<11, 1, u64> minus;
// D-pad buttons
BitField<12, 1, u64> dleft;
BitField<13, 1, u64> dup;
BitField<14, 1, u64> dright;
BitField<15, 1, u64> ddown;
// Left stick directions
BitField<16, 1, u64> lstick_left;
BitField<17, 1, u64> lstick_up;
BitField<18, 1, u64> lstick_right;
BitField<19, 1, u64> lstick_down;
// Right stick directions
BitField<20, 1, u64> rstick_left;
BitField<21, 1, u64> rstick_up;
BitField<22, 1, u64> rstick_right;
BitField<23, 1, u64> rstick_down;
BitField<24, 1, u64> sl;
BitField<25, 1, u64> sr;
};
};
struct ControllerInputEntry {
u64 timestamp;
u64 timestamp_2;
ControllerPadState buttons;
u32 joystickLeftX;
u32 joystickLeftY;
u32 joystickRightX;
u32 joystickRightY;
u64 connectionState;
};
static_assert(sizeof(ControllerInputEntry) == 0x30,
"HID controller input entry structure has incorrect size");
struct ControllerLayout {
ControllerLayoutHeader header;
std::array<ControllerInputEntry, 17> entries;
};
static_assert(sizeof(ControllerLayout) == 0x350,
"HID controller layout structure has incorrect size");
struct Controller {
ControllerHeader header;
std::array<ControllerLayout, 7> layouts;
std::array<u8, 0x2a70> unk_1;
ControllerMAC macLeft;
ControllerMAC macRight;
std::array<u8, 0xdf8> unk_2;
};
static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorrect size");
// End Controller
struct SharedMemory {
std::array<u8, 0x400> header;
TouchScreen touchscreen;
Mouse mouse;
Keyboard keyboard;
std::array<u8, 0x400> unkSection1;
std::array<u8, 0x400> unkSection2;
std::array<u8, 0x400> unkSection3;
std::array<u8, 0x400> unkSection4;
std::array<u8, 0x200> unkSection5;
std::array<u8, 0x200> unkSection6;
std::array<u8, 0x200> unkSection7;
std::array<u8, 0x800> unkSection8;
std::array<u8, 0x4000> controllerSerials;
std::array<Controller, 10> controllers;
std::array<u8, 0x4600> unkSection9;
};
static_assert(sizeof(SharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size");
/// Reload input devices. Used when input configuration changed /// Reload input devices. Used when input configuration changed
void ReloadInputDevices(); void ReloadInputDevices();

@ -16,52 +16,87 @@ enum Values {
B, B,
X, X,
Y, Y,
Up, LStick,
Down, RStick,
Left,
Right,
L, L,
R, R,
Start,
Select,
ZL, ZL,
ZR, ZR,
Plus,
Minus,
DLeft,
DUp,
DRight,
DDown,
LStick_Left,
LStick_Up,
LStick_Right,
LStick_Down,
RStick_Left,
RStick_Up,
RStick_Right,
RStick_Down,
SL,
SR,
Home, Home,
Screenshot,
NumButtons, NumButtons,
}; };
constexpr int BUTTON_HID_BEGIN = A; constexpr int BUTTON_HID_BEGIN = A;
constexpr int BUTTON_IR_BEGIN = ZL;
constexpr int BUTTON_NS_BEGIN = Home; constexpr int BUTTON_NS_BEGIN = Home;
constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN; constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN;
constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN;
constexpr int BUTTON_NS_END = NumButtons; constexpr int BUTTON_NS_END = NumButtons;
constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN;
constexpr int NUM_BUTTONS_IR = BUTTON_IR_END - BUTTON_IR_BEGIN;
constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN;
static const std::array<const char*, NumButtons> mapping = {{ static const std::array<const char*, NumButtons> mapping = {{
"button_a", "button_b", "button_x", "button_y", "button_up", "button_down", "button_left", "button_a",
"button_right", "button_l", "button_r", "button_start", "button_select", "button_zl", "button_b",
"button_zr", "button_home", "button_x",
"button_y",
"button_lstick",
"button_rstick",
"button_l",
"button_r",
"button_zl",
"button_zr",
"button_plus",
"button_minus",
"button_dleft",
"button_dup",
"button_dright",
"button_ddown",
"button_lstick_left",
"button_lstick_up",
"button_lstick_right",
"button_lstick_down",
"button_sl",
"button_sr",
"button_home",
"button_screenshot",
}}; }};
} // namespace NativeButton } // namespace NativeButton
namespace NativeAnalog { namespace NativeAnalog {
enum Values { enum Values {
CirclePad, LStick,
CStick, RStick,
NumAnalogs, NumAnalogs,
}; };
static const std::array<const char*, NumAnalogs> mapping = {{ static const std::array<const char*, NumAnalogs> mapping = {{
"circle_pad", "c_stick", "lstick",
"rstick",
}}; }};
} // namespace NativeAnalog } // namespace NativeAnalog

@ -19,16 +19,18 @@ Config::Config() {
} }
const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, Qt::Key_W,
Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N, Qt::Key_1, Qt::Key_2, Qt::Key_B, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, Qt::Key_H, Qt::Key_G,
Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, Qt::Key_I, Qt::Key_L,
Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V,
}; };
const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{
{ {
Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D, Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_E,
}, },
{ {
Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_D, Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_R,
}, },
}}; }};

@ -54,19 +54,23 @@ ConfigureInput::ConfigureInput(QWidget* parent)
setFocusPolicy(Qt::ClickFocus); setFocusPolicy(Qt::ClickFocus);
button_map = { button_map = {
ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, ui->buttonDpadUp, ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY,
ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight, ui->buttonL, ui->buttonR, ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR,
ui->buttonStart, ui->buttonSelect, ui->buttonZL, ui->buttonZR, ui->buttonHome, ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus,
ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown,
ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown,
ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown,
ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot,
}; };
analog_map = {{ analog_map = {{
{ {
ui->buttonCircleUp, ui->buttonCircleDown, ui->buttonCircleLeft, ui->buttonCircleRight, ui->buttonLStickUp, ui->buttonLStickDown, ui->buttonLStickLeft, ui->buttonLStickRight,
ui->buttonCircleMod, ui->buttonLStickMod,
}, },
{ {
ui->buttonCStickUp, ui->buttonCStickDown, ui->buttonCStickLeft, ui->buttonCStickRight, ui->buttonRStickUp, ui->buttonRStickDown, ui->buttonRStickLeft, ui->buttonRStickRight,
nullptr, ui->buttonRStickMod,
}, },
}}; }};

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>370</width> <width>343</width>
<height>534</height> <height>665</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -190,7 +190,108 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="3" column="1">
<widget class="QGroupBox" name="faceButtons_6">
<property name="title">
<string>Misc.</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_25">
<item>
<widget class="QLabel" name="label_29">
<property name="text">
<string>Plus:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonPlus">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_26">
<item>
<widget class="QLabel" name="label_30">
<property name="text">
<string>Minus:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonMinus">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QVBoxLayout" name="verticalLayout_27">
<item>
<widget class="QLabel" name="label_31">
<property name="text">
<string>Home:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonHome">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_28">
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>Screen
Capture:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonScreenshot">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="faceButtons_3"> <widget class="QGroupBox" name="faceButtons_3">
<property name="title"> <property name="title">
<string>Shoulder Buttons</string> <string>Shoulder Buttons</string>
@ -274,13 +375,49 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>SL:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonSL">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout_29">
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>SR:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonSR">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="0">
<widget class="QGroupBox" name="faceButtons_4"> <widget class="QGroupBox" name="faceButtons_4">
<property name="title"> <property name="title">
<string>Circle Pad</string> <string>Left Stick</string>
</property> </property>
<property name="flat"> <property name="flat">
<bool>false</bool> <bool>false</bool>
@ -299,7 +436,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCircleLeft"> <widget class="QPushButton" name="buttonLStickLeft">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -317,7 +454,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCircleRight"> <widget class="QPushButton" name="buttonLStickRight">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -335,7 +472,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCircleUp"> <widget class="QPushButton" name="buttonLStickUp">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -353,7 +490,43 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCircleDown"> <widget class="QPushButton" name="buttonLStickDown">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,0">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Pressed:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonLStick">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout_31">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Modifier:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonLStickMod">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -364,10 +537,13 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="1" column="1">
<widget class="QGroupBox" name="faceButtons_5"> <widget class="QGroupBox" name="faceButtons_5">
<property name="title"> <property name="title">
<string>C-Stick</string> <string>Right Stick</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property> </property>
<property name="flat"> <property name="flat">
<bool>false</bool> <bool>false</bool>
@ -376,17 +552,17 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0"> <item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_21"> <layout class="QVBoxLayout" name="verticalLayout_24">
<item> <item>
<widget class="QLabel" name="label_25"> <widget class="QLabel" name="label_26">
<property name="text"> <property name="text">
<string>Left:</string> <string>Down:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCStickLeft"> <widget class="QPushButton" name="buttonRStickDown">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -404,7 +580,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCStickRight"> <widget class="QPushButton" name="buttonRStickRight">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -422,7 +598,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCStickUp"> <widget class="QPushButton" name="buttonRStickUp">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -430,50 +606,17 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_24">
<item>
<widget class="QLabel" name="label_26">
<property name="text">
<string>Down:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCStickDown">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="faceButtons_6">
<property name="title">
<string>Misc.</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0"> <item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_25"> <layout class="QVBoxLayout" name="verticalLayout_21">
<item> <item>
<widget class="QLabel" name="label_29"> <widget class="QLabel" name="label_25">
<property name="text"> <property name="text">
<string>Start:</string> <string>Left:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonStart"> <widget class="QPushButton" name="buttonRStickLeft">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -481,17 +624,17 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="0" column="1"> <item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout_26"> <layout class="QVBoxLayout" name="verticalLayout_32">
<item> <item>
<widget class="QLabel" name="label_30"> <widget class="QLabel" name="label_10">
<property name="text"> <property name="text">
<string>Select:</string> <string>Modifier:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonSelect"> <widget class="QPushButton" name="buttonRStickMod">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -499,35 +642,17 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0"> <item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_27"> <layout class="QVBoxLayout" name="verticalLayout_6">
<item> <item>
<widget class="QLabel" name="label_31"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Home:</string> <string>Pressed:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonHome"> <widget class="QPushButton" name="buttonRStick">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_28">
<item>
<widget class="QLabel" name="label_36">
<property name="text">
<string>Circle Mod:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCircleMod">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>

@ -30,17 +30,26 @@ button_a=
button_b= button_b=
button_x= button_x=
button_y= button_y=
button_up= button_lstick=
button_down= button_rstick=
button_left=
button_right=
button_l= button_l=
button_r= button_r=
button_start=
button_select=
button_zl= button_zl=
button_zr= button_zr=
button_plus=
button_minus=
button_dleft=
button_dup=
button_dright=
button_ddown=
button_lstick_left=
button_lstick_up=
button_lstick_right=
button_lstick_down=
button_sl=
button_sr=
button_home= button_home=
button_screenshot=
# for analog input, the following devices are available: # for analog input, the following devices are available:
# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: # - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
@ -53,8 +62,8 @@ button_home=
# - "joystick": the index of the joystick to bind # - "joystick": the index of the joystick to bind
# - "axis_x": the index of the axis to bind as x-axis (default to 0) # - "axis_x": the index of the axis to bind as x-axis (default to 0)
# - "axis_y": the index of the axis to bind as y-axis (default to 1) # - "axis_y": the index of the axis to bind as y-axis (default to 1)
circle_pad= lstick=
c_stick= rstick=
# for motion input, the following devices are available: # for motion input, the following devices are available:
# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: # - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: