mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 19:40:13 +00:00
Merge branch 'experimental' into CheatsModule
This commit is contained in:
commit
61625ba2fa
@ -4,6 +4,7 @@ include_directories(.)
|
|||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(video_core)
|
add_subdirectory(video_core)
|
||||||
|
add_subdirectory(input_core)
|
||||||
add_subdirectory(audio_core)
|
add_subdirectory(audio_core)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
if (ENABLE_SDL2)
|
if (ENABLE_SDL2)
|
||||||
|
@ -16,7 +16,7 @@ create_directory_groups(${SRCS} ${HEADERS})
|
|||||||
include_directories(${SDL2_INCLUDE_DIR})
|
include_directories(${SDL2_INCLUDE_DIR})
|
||||||
|
|
||||||
add_executable(citra ${SRCS} ${HEADERS})
|
add_executable(citra ${SRCS} ${HEADERS})
|
||||||
target_link_libraries(citra core video_core audio_core common)
|
target_link_libraries(citra core video_core audio_core input_core common)
|
||||||
target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad)
|
target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_link_libraries(citra getopt)
|
target_link_libraries(citra getopt)
|
||||||
|
@ -52,17 +52,17 @@ static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = {
|
|||||||
SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L,
|
SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L,
|
||||||
|
|
||||||
// indirectly mapped keys
|
// indirectly mapped keys
|
||||||
SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT,
|
SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT
|
||||||
SDL_SCANCODE_D,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Config::ReadValues() {
|
void Config::ReadValues() {
|
||||||
// Controls
|
// Controls
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
||||||
Settings::values.input_mappings[Settings::NativeInput::All[i]] =
|
Settings::values.input_mappings[Settings::NativeInput::All[i]] =
|
||||||
sdl2_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]);
|
Settings::InputDeviceMapping(sdl2_config->Get("Controls", Settings::NativeInput::Mapping[i], std::to_string(defaults[i])));
|
||||||
}
|
}
|
||||||
Settings::values.pad_circle_modifier_scale = (float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.5);
|
Settings::values.pad_circle_modifier = Settings::InputDeviceMapping(sdl2_config->Get("Controls", "pad_circle_modifier", ""));
|
||||||
|
Settings::values.pad_circle_modifier_scale = (float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.4);
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0);
|
Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0);
|
||||||
|
@ -34,7 +34,7 @@ pad_circle_right =
|
|||||||
pad_circle_modifier =
|
pad_circle_modifier =
|
||||||
|
|
||||||
# The applied modifier scale to circle pad.
|
# The applied modifier scale to circle pad.
|
||||||
# Must be in range of 0.0-1.0. Defaults to 0.5
|
# Must be in range of 0.0-1.0. Defaults to 0.4
|
||||||
pad_circle_modifier_scale =
|
pad_circle_modifier_scale =
|
||||||
|
|
||||||
[Core]
|
[Core]
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
#include "common/key_map.h"
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
@ -19,6 +18,9 @@
|
|||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/hle/service/hid/hid.h"
|
#include "core/hle/service/hid/hid.h"
|
||||||
|
|
||||||
|
#include "input_core/input_core.h"
|
||||||
|
#include "input_core/devices/keyboard.h"
|
||||||
|
|
||||||
#include "citra/emu_window/emu_window_sdl2.h"
|
#include "citra/emu_window/emu_window_sdl2.h"
|
||||||
|
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
@ -38,11 +40,14 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
|
void EmuWindow_SDL2::OnKeyEvent(SDL_Keysym key, u8 state) {
|
||||||
|
auto keyboard = InputCore::GetKeyboard();
|
||||||
|
KeyboardKey param = KeyboardKey(key.sym, SDL_GetKeyName(key.scancode));
|
||||||
|
|
||||||
if (state == SDL_PRESSED) {
|
if (state == SDL_PRESSED) {
|
||||||
KeyMap::PressKey(*this, { key, keyboard_id });
|
keyboard->KeyPressed(param);
|
||||||
} else if (state == SDL_RELEASED) {
|
} else if (state == SDL_RELEASED) {
|
||||||
KeyMap::ReleaseKey(*this, { key, keyboard_id });
|
keyboard->KeyReleased(param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,9 +64,7 @@ void EmuWindow_SDL2::OnResize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EmuWindow_SDL2::EmuWindow_SDL2() {
|
EmuWindow_SDL2::EmuWindow_SDL2() {
|
||||||
keyboard_id = KeyMap::NewDeviceId();
|
keyboard_id = 0;
|
||||||
|
|
||||||
ReloadSetKeymaps();
|
|
||||||
|
|
||||||
SDL_SetMainReady();
|
SDL_SetMainReady();
|
||||||
|
|
||||||
@ -144,7 +147,7 @@ void EmuWindow_SDL2::PollEvents() {
|
|||||||
break;
|
break;
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state);
|
OnKeyEvent(event.key.keysym, event.key.state);
|
||||||
break;
|
break;
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
OnMouseMotion(event.motion.x, event.motion.y);
|
OnMouseMotion(event.motion.x, event.motion.y);
|
||||||
@ -168,13 +171,6 @@ void EmuWindow_SDL2::DoneCurrent() {
|
|||||||
SDL_GL_MakeCurrent(render_window, nullptr);
|
SDL_GL_MakeCurrent(render_window, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_SDL2::ReloadSetKeymaps() {
|
|
||||||
KeyMap::ClearKeyMapping(keyboard_id);
|
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
|
||||||
KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, KeyMap::mapping_targets[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) {
|
void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(const std::pair<unsigned, unsigned>& minimal_size) {
|
||||||
SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
|
SDL_SetWindowMinimumSize(render_window, minimal_size.first, minimal_size.second);
|
||||||
}
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#include "common/emu_window.h"
|
#include "common/emu_window.h"
|
||||||
|
|
||||||
struct SDL_Window;
|
struct SDL_Window;
|
||||||
|
struct SDL_Keysym;
|
||||||
|
|
||||||
class EmuWindow_SDL2 : public EmuWindow {
|
class EmuWindow_SDL2 : public EmuWindow {
|
||||||
public:
|
public:
|
||||||
@ -30,12 +31,9 @@ public:
|
|||||||
/// Whether the window is still open, and a close request hasn't yet been sent
|
/// Whether the window is still open, and a close request hasn't yet been sent
|
||||||
bool IsOpen() const;
|
bool IsOpen() const;
|
||||||
|
|
||||||
/// Load keymap from configuration
|
|
||||||
void ReloadSetKeymaps() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Called by PollEvents when a key is pressed or released.
|
/// Called by PollEvents when a key is pressed or released.
|
||||||
void OnKeyEvent(int key, u8 state);
|
void OnKeyEvent(SDL_Keysym key, u8 state);
|
||||||
|
|
||||||
/// Called by PollEvents when the mouse moves.
|
/// Called by PollEvents when the mouse moves.
|
||||||
void OnMouseMotion(s32 x, s32 y);
|
void OnMouseMotion(s32 x, s32 y);
|
||||||
|
@ -26,8 +26,10 @@ set(SRCS
|
|||||||
configure_graphics.cpp
|
configure_graphics.cpp
|
||||||
configure_system.cpp
|
configure_system.cpp
|
||||||
configure_input.cpp
|
configure_input.cpp
|
||||||
|
configure_system.cpp
|
||||||
game_list.cpp
|
game_list.cpp
|
||||||
hotkeys.cpp
|
hotkeys.cpp
|
||||||
|
keybinding_names.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
ui_settings.cpp
|
ui_settings.cpp
|
||||||
citra-qt.rc
|
citra-qt.rc
|
||||||
@ -60,9 +62,11 @@ set(HEADERS
|
|||||||
configure_graphics.h
|
configure_graphics.h
|
||||||
configure_system.h
|
configure_system.h
|
||||||
configure_input.h
|
configure_input.h
|
||||||
|
configure_system.h
|
||||||
game_list.h
|
game_list.h
|
||||||
game_list_p.h
|
game_list_p.h
|
||||||
hotkeys.h
|
hotkeys.h
|
||||||
|
keybinding_names.h
|
||||||
main.h
|
main.h
|
||||||
ui_settings.h
|
ui_settings.h
|
||||||
version.h
|
version.h
|
||||||
@ -81,6 +85,7 @@ set(UIS
|
|||||||
configure_graphics.ui
|
configure_graphics.ui
|
||||||
configure_system.ui
|
configure_system.ui
|
||||||
configure_input.ui
|
configure_input.ui
|
||||||
|
configure_system.ui
|
||||||
hotkeys.ui
|
hotkeys.ui
|
||||||
main.ui
|
main.ui
|
||||||
)
|
)
|
||||||
@ -101,7 +106,7 @@ if (APPLE)
|
|||||||
else()
|
else()
|
||||||
add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})
|
add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(citra-qt core video_core audio_core common qhexedit)
|
target_link_libraries(citra-qt core video_core audio_core input_core common qhexedit)
|
||||||
target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
|
target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
|
||||||
target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads)
|
target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads)
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include "citra_qt/bootmanager.h"
|
#include "citra_qt/bootmanager.h"
|
||||||
|
|
||||||
#include "common/key_map.h"
|
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
@ -19,6 +18,9 @@
|
|||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
|
|
||||||
|
#include "input_core/input_core.h"
|
||||||
|
#include "input_core/devices/keyboard.h"
|
||||||
|
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
#include "video_core/debug_utils/debug_utils.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
@ -112,8 +114,30 @@ GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) :
|
|||||||
std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
|
std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc);
|
||||||
setWindowTitle(QString::fromStdString(window_title));
|
setWindowTitle(QString::fromStdString(window_title));
|
||||||
|
|
||||||
keyboard_id = KeyMap::NewDeviceId();
|
keyboard_id = 0;
|
||||||
ReloadSetKeymaps();
|
|
||||||
|
// TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose
|
||||||
|
QGLFormat fmt;
|
||||||
|
fmt.setVersion(3,3);
|
||||||
|
fmt.setProfile(QGLFormat::CoreProfile);
|
||||||
|
// Requests a forward-compatible context, which is required to get a 3.2+ context on OS X
|
||||||
|
fmt.setOption(QGL::NoDeprecatedFunctions);
|
||||||
|
|
||||||
|
child = new GGLWidgetInternal(fmt, this);
|
||||||
|
QBoxLayout* layout = new QHBoxLayout(this);
|
||||||
|
|
||||||
|
resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight);
|
||||||
|
layout->addWidget(child);
|
||||||
|
layout->setMargin(0);
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
|
||||||
|
|
||||||
|
OnFramebufferSizeChanged();
|
||||||
|
NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(child->width(), child->height()));
|
||||||
|
|
||||||
|
BackupGeometry();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::moveContext()
|
void GRenderWindow::moveContext()
|
||||||
@ -212,12 +236,16 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
|
|||||||
|
|
||||||
void GRenderWindow::keyPressEvent(QKeyEvent* event)
|
void GRenderWindow::keyPressEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
KeyMap::PressKey(*this, { event->key(), keyboard_id });
|
auto keyboard = InputCore::GetKeyboard();
|
||||||
|
KeyboardKey param = KeyboardKey(event->key(), QKeySequence(event->key()).toString().toStdString());
|
||||||
|
keyboard->KeyPressed(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::keyReleaseEvent(QKeyEvent* event)
|
void GRenderWindow::keyReleaseEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
KeyMap::ReleaseKey(*this, { event->key(), keyboard_id });
|
auto keyboard = InputCore::GetKeyboard();
|
||||||
|
KeyboardKey param = KeyboardKey(event->key(), QKeySequence(event->key()).toString().toStdString());
|
||||||
|
keyboard->KeyReleased(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::mousePressEvent(QMouseEvent *event)
|
void GRenderWindow::mousePressEvent(QMouseEvent *event)
|
||||||
@ -245,14 +273,6 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent *event)
|
|||||||
this->TouchReleased();
|
this->TouchReleased();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::ReloadSetKeymaps()
|
|
||||||
{
|
|
||||||
KeyMap::ClearKeyMapping(keyboard_id);
|
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
|
||||||
KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, KeyMap::mapping_targets[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height)
|
void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height)
|
||||||
{
|
{
|
||||||
NotifyClientAreaSizeChanged(std::make_pair(width, height));
|
NotifyClientAreaSizeChanged(std::make_pair(width, height));
|
||||||
|
@ -121,9 +121,6 @@ public:
|
|||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
void ReloadSetKeymaps() override;
|
|
||||||
|
|
||||||
void OnClientAreaResized(unsigned width, unsigned height);
|
void OnClientAreaResized(unsigned width, unsigned height);
|
||||||
|
|
||||||
void InitRenderTarget();
|
void InitRenderTarget();
|
||||||
|
@ -27,17 +27,17 @@ const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> Config::defaults =
|
|||||||
Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L,
|
Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L,
|
||||||
|
|
||||||
// indirectly mapped keys
|
// indirectly mapped keys
|
||||||
Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right,
|
Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right
|
||||||
Qt::Key_D,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Config::ReadValues() {
|
void Config::ReadValues() {
|
||||||
qt_config->beginGroup("Controls");
|
qt_config->beginGroup("Controls");
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
||||||
Settings::values.input_mappings[Settings::NativeInput::All[i]] =
|
Settings::values.input_mappings[Settings::NativeInput::All[i]] =
|
||||||
qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i]).toInt();
|
Settings::InputDeviceMapping(qt_config->value(Settings::NativeInput::Mapping[i], defaults[i]).toString().toStdString());
|
||||||
}
|
}
|
||||||
Settings::values.pad_circle_modifier_scale = qt_config->value("pad_circle_modifier_scale", 0.5).toFloat();
|
Settings::values.pad_circle_modifier = Settings::InputDeviceMapping(qt_config->value("pad_circle_modifier", 0).toString().toStdString());
|
||||||
|
Settings::values.pad_circle_modifier_scale = qt_config->value("pad_circle_modifier_scale", 0.4).toFloat();
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
|
||||||
qt_config->beginGroup("Core");
|
qt_config->beginGroup("Core");
|
||||||
@ -128,8 +128,9 @@ void Config::SaveValues() {
|
|||||||
qt_config->beginGroup("Controls");
|
qt_config->beginGroup("Controls");
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
||||||
qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]),
|
qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]),
|
||||||
Settings::values.input_mappings[Settings::NativeInput::All[i]]);
|
QString::fromStdString(Settings::values.input_mappings[Settings::NativeInput::All[i]].ToString()));
|
||||||
}
|
}
|
||||||
|
qt_config->setValue("pad_circle_modifier", QString::fromStdString(Settings::values.pad_circle_modifier.ToString()));
|
||||||
qt_config->setValue("pad_circle_modifier_scale", (double)Settings::values.pad_circle_modifier_scale);
|
qt_config->setValue("pad_circle_modifier_scale", (double)Settings::values.pad_circle_modifier_scale);
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
// Copyright 2016 Citra Emulator Project
|
// Copyright 2016 Citra Emulator Project
|
||||||
// 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 <memory>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include "citra_qt/configure_input.h"
|
#include "citra_qt/configure_input.h"
|
||||||
|
#include "citra_qt/keybinding_names.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
|
|
||||||
|
#include "input_core/input_core.h"
|
||||||
|
#include "input_core/devices/keyboard.h"
|
||||||
|
|
||||||
|
|
||||||
ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
|
ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
// Initialize mapping of input enum to UI button.
|
// Initialize mapping of input enum to UI button.
|
||||||
input_mapping = {
|
qt_buttons = {
|
||||||
{ std::make_pair(Settings::NativeInput::Values::A, ui->buttonA) },
|
{ std::make_pair(Settings::NativeInput::Values::A, ui->buttonA) },
|
||||||
{ std::make_pair(Settings::NativeInput::Values::B, ui->buttonB) },
|
{ std::make_pair(Settings::NativeInput::Values::B, ui->buttonB) },
|
||||||
{ std::make_pair(Settings::NativeInput::Values::X, ui->buttonX) },
|
{ std::make_pair(Settings::NativeInput::Values::X, ui->buttonX) },
|
||||||
@ -35,19 +39,18 @@ ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_
|
|||||||
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_UP, ui->buttonCircleUp) },
|
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_UP, ui->buttonCircleUp) },
|
||||||
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_DOWN, ui->buttonCircleDown) },
|
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_DOWN, ui->buttonCircleDown) },
|
||||||
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_LEFT, ui->buttonCircleLeft) },
|
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_LEFT, ui->buttonCircleLeft) },
|
||||||
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_RIGHT, ui->buttonCircleRight) },
|
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_RIGHT, ui->buttonCircleRight) }
|
||||||
{ std::make_pair(Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Attach handle click method to each button click.
|
// Attach handle click method to each button click.
|
||||||
for (const auto& entry : input_mapping) {
|
for (const auto& entry : qt_buttons) {
|
||||||
connect(entry.second, SIGNAL(released()), this, SLOT(handleClick()));
|
connect(entry.second, SIGNAL(released()), this, SLOT(handleClick()));
|
||||||
}
|
}
|
||||||
|
connect(ui->buttonCircleMod, SIGNAL(released()), this, SLOT(handleClick()));
|
||||||
connect(ui->buttonRestoreDefaults, SIGNAL(released()), this, SLOT(restoreDefaults()));
|
connect(ui->buttonRestoreDefaults, SIGNAL(released()), this, SLOT(restoreDefaults()));
|
||||||
|
|
||||||
setFocusPolicy(Qt::ClickFocus);
|
setFocusPolicy(Qt::ClickFocus);
|
||||||
timer = new QTimer(this);
|
|
||||||
timer->setSingleShot(true);
|
|
||||||
connect(timer, &QTimer::timeout, this, [&]() { key_pressed = Qt::Key_Escape; setKey(); });
|
|
||||||
this->setConfiguration();
|
this->setConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,22 +62,12 @@ void ConfigureInput::handleClick() {
|
|||||||
grabKeyboard();
|
grabKeyboard();
|
||||||
grabMouse();
|
grabMouse();
|
||||||
changing_button = sender;
|
changing_button = sender;
|
||||||
timer->start(5000); //Cancel after 5 seconds
|
auto update = []() {
|
||||||
}
|
QCoreApplication::processEvents();
|
||||||
|
};
|
||||||
|
auto input_device = InputCore::DetectInput(5000, update);
|
||||||
|
|
||||||
void ConfigureInput::applyConfiguration() {
|
setKey(input_device);
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
|
||||||
int value = getKeyValue(input_mapping[Settings::NativeInput::Values(i)]->text());
|
|
||||||
Settings::values.input_mappings[Settings::NativeInput::All[i]] = value;
|
|
||||||
}
|
|
||||||
Settings::Apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureInput::setConfiguration() {
|
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
|
||||||
QString keyValue = getKeyName(Settings::values.input_mappings[i]);
|
|
||||||
input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInput::keyPressEvent(QKeyEvent* event) {
|
void ConfigureInput::keyPressEvent(QKeyEvent* event) {
|
||||||
@ -82,26 +75,57 @@ void ConfigureInput::keyPressEvent(QKeyEvent* event) {
|
|||||||
return;
|
return;
|
||||||
if (!event || event->key() == Qt::Key_unknown)
|
if (!event || event->key() == Qt::Key_unknown)
|
||||||
return;
|
return;
|
||||||
key_pressed = event->key();
|
|
||||||
timer->stop();
|
auto keyboard = InputCore::GetKeyboard();
|
||||||
setKey();
|
KeyboardKey param = KeyboardKey(event->key(), QKeySequence(event->key()).toString().toStdString());
|
||||||
|
keyboard->KeyPressed(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInput::setKey() {
|
void ConfigureInput::applyConfiguration() {
|
||||||
const QString key_value = getKeyName(key_pressed);
|
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
||||||
if (key_pressed == Qt::Key_Escape)
|
Settings::values.input_mappings[Settings::NativeInput::All[i]] = button_mapping[qt_buttons[Settings::NativeInput::Values(i)]];
|
||||||
|
}
|
||||||
|
Settings::values.pad_circle_modifier = button_mapping[ui->buttonCircleMod];
|
||||||
|
Settings::Apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureInput::setConfiguration() {
|
||||||
|
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
||||||
|
Settings::InputDeviceMapping mapping = Settings::values.input_mappings[i];
|
||||||
|
button_mapping[qt_buttons[Settings::NativeInput::Values(i)]] = mapping;
|
||||||
|
|
||||||
|
qt_buttons[Settings::NativeInput::Values(i)]->setText(getKeyName(mapping));
|
||||||
|
}
|
||||||
|
button_mapping[ui->buttonCircleMod] = Settings::values.pad_circle_modifier;
|
||||||
|
ui->buttonCircleMod->setText(getKeyName(Settings::values.pad_circle_modifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureInput::setKey(Settings::InputDeviceMapping keyPressed) {
|
||||||
|
if (keyPressed.key == "" || keyPressed.key == std::to_string(Qt::Key_Escape))
|
||||||
changing_button->setText(previous_mapping);
|
changing_button->setText(previous_mapping);
|
||||||
else
|
else {
|
||||||
changing_button->setText(key_value);
|
changing_button->setText(getKeyName(keyPressed));
|
||||||
removeDuplicates(key_value);
|
button_mapping[changing_button] = keyPressed;
|
||||||
key_pressed = Qt::Key_unknown;
|
removeDuplicates(keyPressed);
|
||||||
|
}
|
||||||
releaseKeyboard();
|
releaseKeyboard();
|
||||||
releaseMouse();
|
releaseMouse();
|
||||||
changing_button = nullptr;
|
changing_button = nullptr;
|
||||||
previous_mapping = nullptr;
|
previous_mapping = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ConfigureInput::getKeyName(int key_code) const {
|
QString ConfigureInput::getKeyName(Settings::InputDeviceMapping mapping) const {
|
||||||
|
if (mapping.key.empty())
|
||||||
|
return "";
|
||||||
|
int key_code;
|
||||||
|
if (!Common::TryParse(mapping.key, &key_code))
|
||||||
|
key_code = -1;
|
||||||
|
if (mapping.device == Settings::Device::Gamepad) {
|
||||||
|
if (KeyBindingNames::sdl_gamepad_names.size() > key_code && key_code >= 0)
|
||||||
|
return KeyBindingNames::sdl_gamepad_names[key_code];
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
if (key_code == Qt::Key_Shift)
|
if (key_code == Qt::Key_Shift)
|
||||||
return tr("Shift");
|
return tr("Shift");
|
||||||
if (key_code == Qt::Key_Control)
|
if (key_code == Qt::Key_Control)
|
||||||
@ -110,40 +134,30 @@ QString ConfigureInput::getKeyName(int key_code) const {
|
|||||||
return tr("Alt");
|
return tr("Alt");
|
||||||
if (key_code == Qt::Key_Meta)
|
if (key_code == Qt::Key_Meta)
|
||||||
return "";
|
return "";
|
||||||
if (key_code == -1)
|
if (key_code < 0)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
return QKeySequence(key_code).toString();
|
return QKeySequence(key_code).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::Key ConfigureInput::getKeyValue(const QString& text) const {
|
void ConfigureInput::removeDuplicates(const Settings::InputDeviceMapping newValue) {
|
||||||
if (text == "Shift")
|
for (auto& entry : button_mapping) {
|
||||||
return Qt::Key_Shift;
|
if (changing_button != entry.first) {
|
||||||
if (text == "Ctrl")
|
if (newValue == entry.second && newValue.key == entry.second.key) {
|
||||||
return Qt::Key_Control;
|
entry.first->setText("");
|
||||||
if (text == "Alt")
|
entry.second = Settings::InputDeviceMapping();
|
||||||
return Qt::Key_Alt;
|
}
|
||||||
if (text == "Meta")
|
|
||||||
return Qt::Key_unknown;
|
|
||||||
if (text == "")
|
|
||||||
return Qt::Key_unknown;
|
|
||||||
|
|
||||||
return Qt::Key(QKeySequence(text)[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureInput::removeDuplicates(const QString& newValue) {
|
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
|
||||||
if (changing_button != input_mapping[Settings::NativeInput::Values(i)]) {
|
|
||||||
const QString oldValue = input_mapping[Settings::NativeInput::Values(i)]->text();
|
|
||||||
if (newValue == oldValue)
|
|
||||||
input_mapping[Settings::NativeInput::Values(i)]->setText("");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInput::restoreDefaults() {
|
void ConfigureInput::restoreDefaults() {
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
||||||
const QString keyValue = getKeyName(Config::defaults[i].toInt());
|
Settings::InputDeviceMapping mapping = Settings::InputDeviceMapping(Config::defaults[i].toInt());
|
||||||
input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue);
|
button_mapping[qt_buttons[Settings::NativeInput::Values(i)]] = mapping;
|
||||||
|
const QString keyValue = getKeyName(Settings::InputDeviceMapping(Config::defaults[i].toInt()));
|
||||||
|
qt_buttons[Settings::NativeInput::Values(i)]->setText(keyValue);
|
||||||
}
|
}
|
||||||
|
button_mapping[ui->buttonCircleMod] = Settings::InputDeviceMapping(Qt::Key_F);
|
||||||
|
ui->buttonCircleMod->setText(getKeyName(Settings::InputDeviceMapping(Qt::Key_F)));
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,17 @@
|
|||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
#include "citra_qt/config.h"
|
#include "citra_qt/config.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
#include "input_core/devices/device.h"
|
||||||
#include "ui_configure_input.h"
|
#include "ui_configure_input.h"
|
||||||
|
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QString;
|
class QString;
|
||||||
class QTimer;
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class ConfigureInput;
|
class ConfigureInput;
|
||||||
@ -30,29 +30,25 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Ui::ConfigureInput> ui;
|
std::unique_ptr<Ui::ConfigureInput> ui;
|
||||||
std::map<Settings::NativeInput::Values, QPushButton*> input_mapping;
|
std::map<Settings::NativeInput::Values, QPushButton*> qt_buttons;
|
||||||
int key_pressed;
|
std::map<QPushButton*, Settings::InputDeviceMapping> button_mapping;
|
||||||
QPushButton* changing_button = nullptr; ///< button currently waiting for key press.
|
QPushButton* changing_button = nullptr; ///< button currently waiting for key press.
|
||||||
QString previous_mapping;
|
QString previous_mapping;
|
||||||
QTimer* timer;
|
|
||||||
|
|
||||||
/// Load configuration settings into button text
|
/// Load configuration settings into button text
|
||||||
void setConfiguration();
|
void setConfiguration();
|
||||||
|
|
||||||
/// Check all inputs for duplicate keys. Clears out any other button with the same value as this button's new value.
|
/// Check all inputs for duplicate keys. Clears out any other button with the same value as this button's new value.
|
||||||
void removeDuplicates(const QString& newValue);
|
void removeDuplicates(const Settings::InputDeviceMapping newValue);
|
||||||
|
|
||||||
/// Handle key press event for input tab when a button is 'waiting'.
|
/// Handle keykoard key press event for input tab when a button is 'waiting'.
|
||||||
void keyPressEvent(QKeyEvent* event) override;
|
void keyPressEvent(QKeyEvent* event) override;
|
||||||
|
|
||||||
/// Convert key ASCII value to its' letter/name
|
/// Convert key ASCII value to its' letter/name
|
||||||
QString getKeyName(int key_code) const;
|
QString getKeyName(Settings::InputDeviceMapping mapping) const;
|
||||||
|
|
||||||
/// Convert letter/name of key to its ASCII value.
|
|
||||||
Qt::Key getKeyValue(const QString& text) const;
|
|
||||||
|
|
||||||
/// Set button text to name of key pressed.
|
/// Set button text to name of key pressed.
|
||||||
void setKey();
|
void setKey(Settings::InputDeviceMapping keyPressed);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
/// Event handler for all button released() event.
|
/// Event handler for all button released() event.
|
||||||
|
34
src/citra_qt/keybinding_names.cpp
Normal file
34
src/citra_qt/keybinding_names.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "citra_qt/keybinding_names.h"
|
||||||
|
|
||||||
|
const std::array <QString, static_cast<int>(SDLGamepad::GamepadInputs::MAX)> KeyBindingNames::sdl_gamepad_names = {
|
||||||
|
{
|
||||||
|
tr("Button A"),
|
||||||
|
tr("Button B"),
|
||||||
|
tr("Button X"),
|
||||||
|
tr("Button Y"),
|
||||||
|
tr("Left Shoulder"),
|
||||||
|
tr("Right Shoulder"),
|
||||||
|
tr("Start"),
|
||||||
|
tr("Back"),
|
||||||
|
tr("Dpad Up"),
|
||||||
|
tr("Dpad Down"),
|
||||||
|
tr("Dpad Left"),
|
||||||
|
tr("Dpad Right"),
|
||||||
|
tr("L3"),
|
||||||
|
tr("R3"),
|
||||||
|
tr("Left Trigger"),
|
||||||
|
tr("Right Trigger"),
|
||||||
|
tr("Left Y+"),
|
||||||
|
tr("Left Y-"),
|
||||||
|
tr("Left X+"),
|
||||||
|
tr("Left X-"),
|
||||||
|
tr("Right Y+"),
|
||||||
|
tr("Right Y-"),
|
||||||
|
tr("Right X+"),
|
||||||
|
tr("Right X-")
|
||||||
|
}
|
||||||
|
};
|
17
src/citra_qt/keybinding_names.h
Normal file
17
src/citra_qt/keybinding_names.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include "input_core/devices/sdl_gamepad.h"
|
||||||
|
|
||||||
|
///Map translatable, user-friendly names to input device buttons for use in the Qt input configuration GUI.
|
||||||
|
class KeyBindingNames {
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(KeyBindingNames)
|
||||||
|
public:
|
||||||
|
static const std::array<QString, static_cast<int>(SDLGamepad::GamepadInputs::MAX)> sdl_gamepad_names;
|
||||||
|
};
|
@ -520,7 +520,6 @@ void GMainWindow::OnConfigure() {
|
|||||||
if (result == QDialog::Accepted)
|
if (result == QDialog::Accepted)
|
||||||
{
|
{
|
||||||
configureDialog.applyConfiguration();
|
configureDialog.applyConfiguration();
|
||||||
render_window->ReloadSetKeymaps();
|
|
||||||
config->Save();
|
config->Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ set(SRCS
|
|||||||
emu_window.cpp
|
emu_window.cpp
|
||||||
file_util.cpp
|
file_util.cpp
|
||||||
hash.cpp
|
hash.cpp
|
||||||
key_map.cpp
|
|
||||||
logging/filter.cpp
|
logging/filter.cpp
|
||||||
logging/text_formatter.cpp
|
logging/text_formatter.cpp
|
||||||
logging/backend.cpp
|
logging/backend.cpp
|
||||||
@ -36,7 +35,6 @@ set(HEADERS
|
|||||||
emu_window.h
|
emu_window.h
|
||||||
file_util.h
|
file_util.h
|
||||||
hash.h
|
hash.h
|
||||||
key_map.h
|
|
||||||
linear_disk_cache.h
|
linear_disk_cache.h
|
||||||
logging/text_formatter.h
|
logging/text_formatter.h
|
||||||
logging/filter.h
|
logging/filter.h
|
||||||
|
@ -6,35 +6,11 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/key_map.h"
|
|
||||||
|
|
||||||
#include "emu_window.h"
|
#include "emu_window.h"
|
||||||
|
#include "input_core/input_core.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
void EmuWindow::ButtonPressed(Service::HID::PadState pad) {
|
|
||||||
pad_state.hex |= pad.hex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuWindow::ButtonReleased(Service::HID::PadState pad) {
|
|
||||||
pad_state.hex &= ~pad.hex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuWindow::CirclePadUpdated(float x, float y) {
|
|
||||||
constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position
|
|
||||||
|
|
||||||
// Make sure the coordinates are in the unit circle,
|
|
||||||
// otherwise normalize it.
|
|
||||||
float r = x * x + y * y;
|
|
||||||
if (r > 1) {
|
|
||||||
r = std::sqrt(r);
|
|
||||||
x /= r;
|
|
||||||
y /= r;
|
|
||||||
}
|
|
||||||
|
|
||||||
circle_pad_x = static_cast<s16>(x * MAX_CIRCLEPAD_POS);
|
|
||||||
circle_pad_y = static_cast<s16>(y * MAX_CIRCLEPAD_POS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout
|
* Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout
|
||||||
* @param layout FramebufferLayout object describing the framebuffer size and screen positions
|
* @param layout FramebufferLayout object describing the framebuffer size and screen positions
|
||||||
@ -64,20 +40,23 @@ void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) {
|
|||||||
if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y))
|
if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
touch_x = VideoCore::kScreenBottomWidth * (framebuffer_x - framebuffer_layout.bottom_screen.left) /
|
int touch_x = VideoCore::kScreenBottomWidth * (framebuffer_x - framebuffer_layout.bottom_screen.left) /
|
||||||
(framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left);
|
(framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left);
|
||||||
touch_y = VideoCore::kScreenBottomHeight * (framebuffer_y - framebuffer_layout.bottom_screen.top) /
|
int touch_y = VideoCore::kScreenBottomHeight * (framebuffer_y - framebuffer_layout.bottom_screen.top) /
|
||||||
(framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top);
|
(framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top);
|
||||||
|
|
||||||
touch_pressed = true;
|
touch_pressed = true;
|
||||||
|
InputCore::SetTouchState(std::make_tuple(touch_x, touch_y, true));
|
||||||
|
auto pad_state = InputCore::GetPadState();
|
||||||
pad_state.touch.Assign(1);
|
pad_state.touch.Assign(1);
|
||||||
|
InputCore::SetPadState(pad_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow::TouchReleased() {
|
void EmuWindow::TouchReleased() {
|
||||||
touch_pressed = false;
|
touch_pressed = false;
|
||||||
touch_x = 0;
|
InputCore::SetTouchState(std::make_tuple(0, 0, false));
|
||||||
touch_y = 0;
|
auto pad_state = InputCore::GetPadState();
|
||||||
pad_state.touch.Assign(0);
|
pad_state.touch.Assign(0);
|
||||||
|
InputCore::SetPadState(pad_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
|
void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) {
|
||||||
|
@ -70,30 +70,6 @@ public:
|
|||||||
/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
|
/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
|
||||||
virtual void DoneCurrent() = 0;
|
virtual void DoneCurrent() = 0;
|
||||||
|
|
||||||
virtual void ReloadSetKeymaps() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals a button press action to the HID module.
|
|
||||||
* @param pad_state indicates which button to press
|
|
||||||
* @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad.
|
|
||||||
*/
|
|
||||||
void ButtonPressed(Service::HID::PadState pad_state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals a button release action to the HID module.
|
|
||||||
* @param pad_state indicates which button to press
|
|
||||||
* @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad.
|
|
||||||
*/
|
|
||||||
void ButtonReleased(Service::HID::PadState pad_state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals a circle pad change action to the HID module.
|
|
||||||
* @param x new x-coordinate of the circle pad, in the range [-1.0, 1.0]
|
|
||||||
* @param y new y-coordinate of the circle pad, in the range [-1.0, 1.0]
|
|
||||||
* @note the coordinates will be normalized if the radius is larger than 1
|
|
||||||
*/
|
|
||||||
void CirclePadUpdated(float x, float y);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signal that a touch pressed event has occurred (e.g. mouse click pressed)
|
* Signal that a touch pressed event has occurred (e.g. mouse click pressed)
|
||||||
* @param framebuffer_x Framebuffer x-coordinate that was pressed
|
* @param framebuffer_x Framebuffer x-coordinate that was pressed
|
||||||
@ -111,38 +87,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y);
|
void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y);
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current pad state (which buttons are pressed).
|
|
||||||
* @note This should be called by the core emu thread to get a state set by the window thread.
|
|
||||||
* @note This doesn't include analog input like circle pad direction
|
|
||||||
* @todo Fix this function to be thread-safe.
|
|
||||||
* @return PadState object indicating the current pad state
|
|
||||||
*/
|
|
||||||
Service::HID::PadState GetPadState() const {
|
|
||||||
return pad_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current circle pad state.
|
|
||||||
* @note This should be called by the core emu thread to get a state set by the window thread.
|
|
||||||
* @todo Fix this function to be thread-safe.
|
|
||||||
* @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates
|
|
||||||
*/
|
|
||||||
std::tuple<s16, s16> GetCirclePadState() const {
|
|
||||||
return std::make_tuple(circle_pad_x, circle_pad_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed).
|
|
||||||
* @note This should be called by the core emu thread to get a state set by the window thread.
|
|
||||||
* @todo Fix this function to be thread-safe.
|
|
||||||
* @return std::tuple of (x, y, pressed) where `x` and `y` are the touch coordinates and
|
|
||||||
* `pressed` is true if the touch screen is currently being pressed
|
|
||||||
*/
|
|
||||||
std::tuple<u16, u16, bool> GetTouchState() const {
|
|
||||||
return std::make_tuple(touch_x, touch_y, touch_pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current accelerometer state (acceleration along each three axis).
|
* Gets the current accelerometer state (acceleration along each three axis).
|
||||||
* Axis explained:
|
* Axis explained:
|
||||||
@ -220,12 +164,6 @@ protected:
|
|||||||
// TODO: Find a better place to set this.
|
// TODO: Find a better place to set this.
|
||||||
config.min_client_area_size = std::make_pair(400u, 480u);
|
config.min_client_area_size = std::make_pair(400u, 480u);
|
||||||
active_config = config;
|
active_config = config;
|
||||||
pad_state.hex = 0;
|
|
||||||
touch_x = 0;
|
|
||||||
touch_y = 0;
|
|
||||||
circle_pad_x = 0;
|
|
||||||
circle_pad_y = 0;
|
|
||||||
touch_pressed = false;
|
|
||||||
}
|
}
|
||||||
virtual ~EmuWindow() {}
|
virtual ~EmuWindow() {}
|
||||||
|
|
||||||
@ -282,16 +220,8 @@ private:
|
|||||||
|
|
||||||
bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false
|
bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false
|
||||||
|
|
||||||
u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320)
|
|
||||||
u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240)
|
|
||||||
|
|
||||||
s16 circle_pad_x; ///< Circle pad X-position in native 3DS pixel coordinates (-156 - 156)
|
|
||||||
s16 circle_pad_y; ///< Circle pad Y-position in native 3DS pixel coordinates (-156 - 156)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clip the provided coordinates to be inside the touchscreen area.
|
* Clip the provided coordinates to be inside the touchscreen area.
|
||||||
*/
|
*/
|
||||||
std::tuple<unsigned,unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y);
|
std::tuple<unsigned,unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y);
|
||||||
|
|
||||||
Service::HID::PadState pad_state;
|
|
||||||
};
|
};
|
||||||
|
@ -1,139 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "common/emu_window.h"
|
|
||||||
#include "common/key_map.h"
|
|
||||||
|
|
||||||
namespace KeyMap {
|
|
||||||
|
|
||||||
// TODO (wwylele): currently we treat c-stick as four direction buttons
|
|
||||||
// and map it directly to EmuWindow::ButtonPressed.
|
|
||||||
// It should go the analog input way like circle pad does.
|
|
||||||
const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets = {{
|
|
||||||
Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y,
|
|
||||||
Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR,
|
|
||||||
Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE,
|
|
||||||
Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT,
|
|
||||||
Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT,
|
|
||||||
|
|
||||||
IndirectTarget::CirclePadUp,
|
|
||||||
IndirectTarget::CirclePadDown,
|
|
||||||
IndirectTarget::CirclePadLeft,
|
|
||||||
IndirectTarget::CirclePadRight,
|
|
||||||
IndirectTarget::CirclePadModifier,
|
|
||||||
}};
|
|
||||||
|
|
||||||
static std::map<HostDeviceKey, KeyTarget> key_map;
|
|
||||||
static int next_device_id = 0;
|
|
||||||
|
|
||||||
static bool circle_pad_up = false;
|
|
||||||
static bool circle_pad_down = false;
|
|
||||||
static bool circle_pad_left = false;
|
|
||||||
static bool circle_pad_right = false;
|
|
||||||
static bool circle_pad_modifier = false;
|
|
||||||
|
|
||||||
static void UpdateCirclePad(EmuWindow& emu_window) {
|
|
||||||
constexpr float SQRT_HALF = 0.707106781;
|
|
||||||
int x = 0, y = 0;
|
|
||||||
|
|
||||||
if (circle_pad_right)
|
|
||||||
++x;
|
|
||||||
if (circle_pad_left)
|
|
||||||
--x;
|
|
||||||
if (circle_pad_up)
|
|
||||||
++y;
|
|
||||||
if (circle_pad_down)
|
|
||||||
--y;
|
|
||||||
|
|
||||||
float modifier = circle_pad_modifier ? Settings::values.pad_circle_modifier_scale : 1.0;
|
|
||||||
emu_window.CirclePadUpdated(x * modifier * (y == 0 ? 1.0 : SQRT_HALF), y * modifier * (x == 0 ? 1.0 : SQRT_HALF));
|
|
||||||
}
|
|
||||||
|
|
||||||
int NewDeviceId() {
|
|
||||||
return next_device_id++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetKeyMapping(HostDeviceKey key, KeyTarget target) {
|
|
||||||
key_map[key] = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearKeyMapping(int device_id) {
|
|
||||||
auto iter = key_map.begin();
|
|
||||||
while (iter != key_map.end()) {
|
|
||||||
if (iter->first.device_id == device_id)
|
|
||||||
key_map.erase(iter++);
|
|
||||||
else
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PressKey(EmuWindow& emu_window, HostDeviceKey key) {
|
|
||||||
auto target = key_map.find(key);
|
|
||||||
if (target == key_map.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (target->second.direct) {
|
|
||||||
emu_window.ButtonPressed({{target->second.target.direct_target_hex}});
|
|
||||||
} else {
|
|
||||||
switch (target->second.target.indirect_target) {
|
|
||||||
case IndirectTarget::CirclePadUp:
|
|
||||||
circle_pad_up = true;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadDown:
|
|
||||||
circle_pad_down = true;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadLeft:
|
|
||||||
circle_pad_left = true;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadRight:
|
|
||||||
circle_pad_right = true;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadModifier:
|
|
||||||
circle_pad_modifier = true;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReleaseKey(EmuWindow& emu_window,HostDeviceKey key) {
|
|
||||||
auto target = key_map.find(key);
|
|
||||||
if (target == key_map.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (target->second.direct) {
|
|
||||||
emu_window.ButtonReleased({{target->second.target.direct_target_hex}});
|
|
||||||
} else {
|
|
||||||
switch (target->second.target.indirect_target) {
|
|
||||||
case IndirectTarget::CirclePadUp:
|
|
||||||
circle_pad_up = false;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadDown:
|
|
||||||
circle_pad_down = false;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadLeft:
|
|
||||||
circle_pad_left = false;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadRight:
|
|
||||||
circle_pad_right = false;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
case IndirectTarget::CirclePadModifier:
|
|
||||||
circle_pad_modifier = false;
|
|
||||||
UpdateCirclePad(emu_window);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <tuple>
|
|
||||||
#include "core/hle/service/hid/hid.h"
|
|
||||||
|
|
||||||
class EmuWindow;
|
|
||||||
|
|
||||||
namespace KeyMap {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents key mapping targets that are not real 3DS buttons.
|
|
||||||
* They will be handled by KeyMap and translated to 3DS input.
|
|
||||||
*/
|
|
||||||
enum class IndirectTarget {
|
|
||||||
CirclePadUp,
|
|
||||||
CirclePadDown,
|
|
||||||
CirclePadLeft,
|
|
||||||
CirclePadRight,
|
|
||||||
CirclePadModifier,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a key mapping target. It can be a PadState that represents real 3DS buttons,
|
|
||||||
* or an IndirectTarget.
|
|
||||||
*/
|
|
||||||
struct KeyTarget {
|
|
||||||
bool direct;
|
|
||||||
union {
|
|
||||||
u32 direct_target_hex;
|
|
||||||
IndirectTarget indirect_target;
|
|
||||||
} target;
|
|
||||||
|
|
||||||
KeyTarget() : direct(true) {
|
|
||||||
target.direct_target_hex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyTarget(Service::HID::PadState pad) : direct(true) {
|
|
||||||
target.direct_target_hex = pad.hex;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyTarget(IndirectTarget i) : direct(false) {
|
|
||||||
target.indirect_target = i;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a key for a specific host device.
|
|
||||||
*/
|
|
||||||
struct HostDeviceKey {
|
|
||||||
int key_code;
|
|
||||||
int device_id; ///< Uniquely identifies a host device
|
|
||||||
|
|
||||||
bool operator<(const HostDeviceKey &other) const {
|
|
||||||
return std::tie(key_code, device_id) <
|
|
||||||
std::tie(other.key_code, other.device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const HostDeviceKey &other) const {
|
|
||||||
return std::tie(key_code, device_id) ==
|
|
||||||
std::tie(other.key_code, other.device_id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
extern const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a new device id, which uniquely identifies a host device within KeyMap.
|
|
||||||
*/
|
|
||||||
int NewDeviceId();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a device-specific key to a target (a PadState or an IndirectTarget).
|
|
||||||
*/
|
|
||||||
void SetKeyMapping(HostDeviceKey key, KeyTarget target);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears all key mappings belonging to one device.
|
|
||||||
*/
|
|
||||||
void ClearKeyMapping(int device_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a key press action and call the corresponding function in EmuWindow
|
|
||||||
*/
|
|
||||||
void PressKey(EmuWindow& emu_window, HostDeviceKey key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a key release action and call the corresponding function in EmuWindow
|
|
||||||
*/
|
|
||||||
void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key);
|
|
||||||
|
|
||||||
}
|
|
@ -66,7 +66,8 @@ namespace Log {
|
|||||||
CLS(Audio) \
|
CLS(Audio) \
|
||||||
SUB(Audio, DSP) \
|
SUB(Audio, DSP) \
|
||||||
SUB(Audio, Sink) \
|
SUB(Audio, Sink) \
|
||||||
CLS(Loader)
|
CLS(Loader) \
|
||||||
|
CLS(Input)
|
||||||
|
|
||||||
// GetClassName is a macro defined by Windows.h, grrr...
|
// GetClassName is a macro defined by Windows.h, grrr...
|
||||||
const char* GetLogClassName(Class log_class) {
|
const char* GetLogClassName(Class log_class) {
|
||||||
|
@ -82,6 +82,7 @@ enum class Class : ClassType {
|
|||||||
Audio_DSP, ///< The HLE implementation of the DSP
|
Audio_DSP, ///< The HLE implementation of the DSP
|
||||||
Audio_Sink, ///< Emulator audio output backend
|
Audio_Sink, ///< Emulator audio output backend
|
||||||
Loader, ///< ROM loader
|
Loader, ///< ROM loader
|
||||||
|
Input, ///< Input backend
|
||||||
|
|
||||||
Count ///< Total number of logging classes
|
Count ///< Total number of logging classes
|
||||||
};
|
};
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include "core/hle/service/hid/hid_spvr.h"
|
#include "core/hle/service/hid/hid_spvr.h"
|
||||||
#include "core/hle/service/hid/hid_user.h"
|
#include "core/hle/service/hid/hid_user.h"
|
||||||
|
|
||||||
|
#include "input_core/input_core.h"
|
||||||
|
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/kernel/event.h"
|
#include "core/hle/kernel/event.h"
|
||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
@ -74,11 +76,10 @@ void Update() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PadState state = VideoCore::g_emu_window->GetPadState();
|
PadState state = InputCore::GetPadState();
|
||||||
|
|
||||||
// Get current circle pad position and update circle pad direction
|
// Get current circle pad position and update circle pad direction
|
||||||
s16 circle_pad_x, circle_pad_y;
|
s16 circle_pad_x, circle_pad_y;
|
||||||
std::tie(circle_pad_x, circle_pad_y) = VideoCore::g_emu_window->GetCirclePadState();
|
std::tie(circle_pad_x, circle_pad_y) = InputCore::GetCirclePad();
|
||||||
state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex;
|
state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex;
|
||||||
|
|
||||||
mem->pad.current_state.hex = state.hex;
|
mem->pad.current_state.hex = state.hex;
|
||||||
@ -115,7 +116,7 @@ void Update() {
|
|||||||
TouchDataEntry& touch_entry = mem->touch.entries[mem->touch.index];
|
TouchDataEntry& touch_entry = mem->touch.entries[mem->touch.index];
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
|
|
||||||
std::tie(touch_entry.x, touch_entry.y, pressed) = VideoCore::g_emu_window->GetTouchState();
|
std::tie(touch_entry.x, touch_entry.y, pressed) = InputCore::GetTouchState();
|
||||||
touch_entry.valid.Assign(pressed ? 1 : 0);
|
touch_entry.valid.Assign(pressed ? 1 : 0);
|
||||||
|
|
||||||
// TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
|
// TODO(bunnei): We're not doing anything with offset 0xA8 + 0x18 of HID SharedMemory, which
|
||||||
|
@ -24,6 +24,7 @@ namespace HID {
|
|||||||
* Structure of a Pad controller state.
|
* Structure of a Pad controller state.
|
||||||
*/
|
*/
|
||||||
struct PadState {
|
struct PadState {
|
||||||
|
PadState() = default;
|
||||||
union {
|
union {
|
||||||
u32 hex;
|
u32 hex;
|
||||||
|
|
||||||
@ -54,6 +55,13 @@ struct PadState {
|
|||||||
BitField<30, 1, u32> circle_up;
|
BitField<30, 1, u32> circle_up;
|
||||||
BitField<31, 1, u32> circle_down;
|
BitField<31, 1, u32> circle_down;
|
||||||
};
|
};
|
||||||
|
bool operator==(const PadState& other) const {
|
||||||
|
return hex == other.hex;
|
||||||
|
}
|
||||||
|
PadState& operator=(const PadState& other) {
|
||||||
|
hex = other.hex;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -430,9 +430,6 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
|
|||||||
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0);
|
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0);
|
||||||
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1);
|
GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1);
|
||||||
|
|
||||||
// Check for user input updates
|
|
||||||
Service::HID::Update();
|
|
||||||
|
|
||||||
// Reschedule recurrent event
|
// Reschedule recurrent event
|
||||||
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
|
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "audio_core/audio_core.h"
|
#include "audio_core/audio_core.h"
|
||||||
|
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
|
#include "input_core/input_core.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
@ -26,6 +26,7 @@ void Apply() {
|
|||||||
AudioCore::SelectSink(values.sink_id);
|
AudioCore::SelectSink(values.sink_id);
|
||||||
AudioCore::EnableStretching(values.enable_audio_stretching);
|
AudioCore::EnableStretching(values.enable_audio_stretching);
|
||||||
|
|
||||||
|
InputCore::ReloadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -4,13 +4,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
|
||||||
namespace NativeInput {
|
namespace NativeInput {
|
||||||
enum Values {
|
enum Values {
|
||||||
// directly mapped keys
|
// directly mapped keys
|
||||||
@ -22,12 +24,10 @@ enum Values {
|
|||||||
|
|
||||||
// indirectly mapped keys
|
// indirectly mapped keys
|
||||||
CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT,
|
CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT,
|
||||||
CIRCLE_MODIFIER,
|
|
||||||
|
|
||||||
NUM_INPUTS
|
NUM_INPUTS
|
||||||
};
|
};
|
||||||
|
static const std::array<const char*, NUM_INPUTS> Mapping = { {
|
||||||
static const std::array<const char*, NUM_INPUTS> Mapping = {{
|
|
||||||
// directly mapped keys
|
// directly mapped keys
|
||||||
"pad_a", "pad_b", "pad_x", "pad_y",
|
"pad_a", "pad_b", "pad_x", "pad_y",
|
||||||
"pad_l", "pad_r", "pad_zl", "pad_zr",
|
"pad_l", "pad_r", "pad_zl", "pad_zr",
|
||||||
@ -36,27 +36,89 @@ static const std::array<const char*, NUM_INPUTS> Mapping = {{
|
|||||||
"pad_cup", "pad_cdown", "pad_cleft", "pad_cright",
|
"pad_cup", "pad_cdown", "pad_cleft", "pad_cright",
|
||||||
|
|
||||||
// indirectly mapped keys
|
// indirectly mapped keys
|
||||||
"pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right",
|
"pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right"
|
||||||
"pad_circle_modifier",
|
} };
|
||||||
}};
|
static const std::array<Values, NUM_INPUTS> All = { {
|
||||||
static const std::array<Values, NUM_INPUTS> All = {{
|
|
||||||
A, B, X, Y,
|
A, B, X, Y,
|
||||||
L, R, ZL, ZR,
|
L, R, ZL, ZR,
|
||||||
START, SELECT, HOME,
|
START, SELECT, HOME,
|
||||||
DUP, DDOWN, DLEFT, DRIGHT,
|
DUP, DDOWN, DLEFT, DRIGHT,
|
||||||
CUP, CDOWN, CLEFT, CRIGHT,
|
CUP, CDOWN, CLEFT, CRIGHT,
|
||||||
CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT,
|
CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT
|
||||||
CIRCLE_MODIFIER,
|
} };
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class DeviceFramework {
|
||||||
|
Qt, SDL
|
||||||
|
};
|
||||||
|
enum class Device {
|
||||||
|
Keyboard, Gamepad
|
||||||
|
};
|
||||||
|
struct InputDeviceMapping {
|
||||||
|
DeviceFramework framework = DeviceFramework::Qt;
|
||||||
|
int number = 0;
|
||||||
|
Device device = Device::Keyboard;
|
||||||
|
std::string key;
|
||||||
|
|
||||||
|
InputDeviceMapping() = default;
|
||||||
|
explicit InputDeviceMapping(int keyboardKey) {
|
||||||
|
key = std::to_string(keyboardKey);
|
||||||
|
}
|
||||||
|
explicit InputDeviceMapping(const std::string& input) {
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
Common::SplitString(input, '/', parts);
|
||||||
|
if (parts.size() != 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (parts[0] == "Qt")
|
||||||
|
framework = DeviceFramework::Qt;
|
||||||
|
else if (parts[0] == "SDL")
|
||||||
|
framework = DeviceFramework::SDL;
|
||||||
|
|
||||||
|
number = std::stoi(parts[1]);
|
||||||
|
|
||||||
|
if (parts[2] == "Keyboard")
|
||||||
|
device = Device::Keyboard;
|
||||||
|
else if (parts[2] == "Gamepad")
|
||||||
|
device = Device::Gamepad;
|
||||||
|
key = parts[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const InputDeviceMapping& rhs) const {
|
||||||
|
return std::tie(device, framework, number) == std::tie(rhs.device, rhs.framework, rhs.number);
|
||||||
|
}
|
||||||
|
bool operator==(const std::string& rhs) const {
|
||||||
|
return ToString() == rhs;
|
||||||
|
}
|
||||||
|
std::string ToString() const {
|
||||||
|
std::string result;
|
||||||
|
if (framework == DeviceFramework::Qt)
|
||||||
|
result = "Qt";
|
||||||
|
else if (framework == DeviceFramework::SDL)
|
||||||
|
result = "SDL";
|
||||||
|
|
||||||
|
result += "/";
|
||||||
|
result += std::to_string(this->number);
|
||||||
|
result += "/";
|
||||||
|
|
||||||
|
if (device == Device::Keyboard)
|
||||||
|
result += "Keyboard";
|
||||||
|
else if (device == Device::Gamepad)
|
||||||
|
result += "Gamepad";
|
||||||
|
|
||||||
|
result += "/";
|
||||||
|
result += key;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Values {
|
struct Values {
|
||||||
// CheckNew3DS
|
// CheckNew3DS
|
||||||
bool is_new_3ds;
|
bool is_new_3ds;
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
std::array<int, NativeInput::NUM_INPUTS> input_mappings;
|
std::array<InputDeviceMapping, NativeInput::NUM_INPUTS> input_mappings;
|
||||||
|
InputDeviceMapping pad_circle_modifier;
|
||||||
float pad_circle_modifier_scale;
|
float pad_circle_modifier_scale;
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
@ -87,8 +149,8 @@ struct Values {
|
|||||||
// Debugging
|
// Debugging
|
||||||
bool use_gdbstub;
|
bool use_gdbstub;
|
||||||
u16 gdbstub_port;
|
u16 gdbstub_port;
|
||||||
} extern values;
|
};
|
||||||
|
extern Values values;
|
||||||
|
|
||||||
void Apply();
|
void Apply();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/memory.h"
|
#include "core/hle/kernel/memory.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
#include "input_core/input_core.h"
|
||||||
|
|
||||||
namespace System {
|
namespace System {
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ Result Init(EmuWindow* emu_window) {
|
|||||||
}
|
}
|
||||||
AudioCore::Init();
|
AudioCore::Init();
|
||||||
CheatCore::Init();
|
CheatCore::Init();
|
||||||
|
InputCore::Init();
|
||||||
GDBStub::Init();
|
GDBStub::Init();
|
||||||
|
|
||||||
is_powered_on = true;
|
is_powered_on = true;
|
||||||
@ -45,6 +47,7 @@ bool IsPoweredOn() {
|
|||||||
void Shutdown() {
|
void Shutdown() {
|
||||||
GDBStub::Shutdown();
|
GDBStub::Shutdown();
|
||||||
CheatCore::Shutdown();
|
CheatCore::Shutdown();
|
||||||
|
InputCore::Shutdown();
|
||||||
AudioCore::Shutdown();
|
AudioCore::Shutdown();
|
||||||
VideoCore::Shutdown();
|
VideoCore::Shutdown();
|
||||||
HLE::Shutdown();
|
HLE::Shutdown();
|
||||||
|
30
src/input_core/CMakeLists.txt
Normal file
30
src/input_core/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
set(SRCS
|
||||||
|
input_core.cpp
|
||||||
|
devices/device.cpp
|
||||||
|
devices/keyboard.cpp
|
||||||
|
devices/sdl_gamepad.cpp
|
||||||
|
key_map.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
input_core.h
|
||||||
|
key_map.h
|
||||||
|
devices/device.h
|
||||||
|
devices/gamecontrollerdb.h
|
||||||
|
devices/keyboard.h
|
||||||
|
devices/sdl_gamepad.h
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if(SDL2_FOUND)
|
||||||
|
include_directories(${SDL2_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
create_directory_groups(${SRCS} ${HEADERS})
|
||||||
|
|
||||||
|
add_library(input_core STATIC ${SRCS} ${HEADERS})
|
||||||
|
|
||||||
|
if(SDL2_FOUND)
|
||||||
|
target_link_libraries(input_core ${SDL2_LIBRARY})
|
||||||
|
set_property(TARGET input_core APPEND PROPERTY COMPILE_DEFINITIONS HAVE_SDL2)
|
||||||
|
endif()
|
7
src/input_core/devices/device.cpp
Normal file
7
src/input_core/devices/device.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "input_core/devices/device.h"
|
||||||
|
|
||||||
|
IDevice::~IDevice() = default;
|
48
src/input_core/devices/device.h
Normal file
48
src/input_core/devices/device.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "core/hle/service/hid/hid.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
#include "input_core/key_map.h"
|
||||||
|
|
||||||
|
class IDevice {
|
||||||
|
public:
|
||||||
|
virtual ~IDevice();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize IDevice object with device's index and the map of keys that it will listen to.
|
||||||
|
* @param number: device number as ordered connected to computer.
|
||||||
|
* @param keymap: vector of PadStates for device to listen for
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
virtual bool InitDevice(int number, const std::map<std::string, std::vector<Service::HID::PadState>>& keyMap) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process inputs that were pressed since last frame
|
||||||
|
*/
|
||||||
|
virtual void ProcessInput() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close connection to device
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
virtual bool CloseDevice() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets Input for a single frame. Used only in Qt gui for key binding.
|
||||||
|
* @return Settings::InputDeviceMapping instance that captures what button was pressed
|
||||||
|
*/
|
||||||
|
virtual Settings::InputDeviceMapping GetInput() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears info from last frame.
|
||||||
|
*/
|
||||||
|
virtual void Clear() = 0;
|
||||||
|
protected:
|
||||||
|
std::map<std::string, std::vector<Service::HID::PadState>> key_mapping; ///< Maps the string in the settings file to the HID Padstate object
|
||||||
|
};
|
167
src/input_core/devices/gamecontrollerdb.h
Normal file
167
src/input_core/devices/gamecontrollerdb.h
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
// Community sourced database of controllers, from https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt. Taken 8/27/2016
|
||||||
|
#pragma once
|
||||||
|
namespace SDLGameControllerDB {
|
||||||
|
|
||||||
|
const char* db_file1 = R"(
|
||||||
|
# Windows - DINPUT
|
||||||
|
8f0e1200000000000000504944564944, Acme, platform:Windows, x : b2, a : b0, b : b1, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b5, rightshoulder : b6, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a2,
|
||||||
|
341a3608000000000000504944564944, Afterglow PS3 Controller, a : b1, b : b2, back : b8, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, guide : b12, leftshoulder : b4, leftstick : b10, lefttrigger : b6, leftx : a0, lefty : a1, rightshoulder : b5, rightstick : b11, righttrigger : b7, rightx : a2, righty : a3, start : b9, x : b0, y : b3, platform : Windows,
|
||||||
|
ffff0000000000000000504944564944, GameStop Gamepad, a : b0, b : b1, back : b8, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, guide : , leftshoulder : b4, leftstick : b10, lefttrigger : b6, leftx : a0, lefty : a1, rightshoulder : b5, rightstick : b11, righttrigger : b7, rightx : a2, righty : a3, start : b9, x : b2, y : b3, platform : Windows,
|
||||||
|
6d0416c2000000000000504944564944, Generic DirectInput Controller, a : b1, b : b2, back : b8, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, leftshoulder : b4, leftstick : b10, lefttrigger : b6, leftx : a0, lefty : a1, rightshoulder : b5, rightstick : b11, righttrigger : b7, rightx : a2, righty : a3, start : b9, x : b0, y : b3, platform : Windows,
|
||||||
|
0d0f6e00000000000000504944564944, HORIPAD 4, a : b1, b : b2, y : b3, x : b0, start : b9, guide : b12, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, platform : Windows,
|
||||||
|
6d0419c2000000000000504944564944, Logitech F710 Gamepad, a : b1, b : b2, back : b8, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, leftshoulder : b4, leftstick : b10, lefttrigger : b6, leftx : a0, lefty : a1, rightshoulder : b5, rightstick : b11, righttrigger : b7, rightx : a2, righty : a3, start : b9, x : b0, y : b3, platform : Windows,
|
||||||
|
88880803000000000000504944564944, PS3 Controller, a : b2, b : b1, back : b8, dpdown : h0.8, dpleft : h0.4, dpright : h0.2, dpup : h0.1, guide : b12, leftshoulder : b4, leftstick : b9, lefttrigger : b6, leftx : a0, lefty : a1, rightshoulder : b5, rightstick : b10, righttrigger : b7, rightx : a3, righty : a4, start : b11, x : b0, y : b3, platform : Windows,
|
||||||
|
4c056802000000000000504944564944, PS3 Controller, a : b14, b : b13, back : b0, dpdown : b6, dpleft : b7, dpright : b5, dpup : b4, guide : b16, leftshoulder : b10, leftstick : b1, lefttrigger : b8, leftx : a0, lefty : a1, rightshoulder : b11, rightstick : b2, righttrigger : b9, rightx : a2, righty : a3, start : b3, x : b15, y : b12, platform : Windows,
|
||||||
|
25090500000000000000504944564944, PS3 DualShock, a : b2, b : b1, back : b9, dpdown : h0.8, dpleft : h0.4, dpright : h0.2, dpup : h0.1, guide : , leftshoulder : b6, leftstick : b10, lefttrigger : b4, leftx : a0, lefty : a1, rightshoulder : b7, rightstick : b11, righttrigger : b5, rightx : a2, righty : a3, start : b8, x : b0, y : b3, platform : Windows,
|
||||||
|
4c05c405000000000000504944564944, 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 : Windows,
|
||||||
|
6d0418c2000000000000504944564944, Logitech RumblePad 2 USB, platform : Windows, x : b0, a : b1, b : b2, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
36280100000000000000504944564944, OUYA Controller, platform : Windows, a : b0, b : b3, y : b2, x : b1, start : b14, guide : b15, leftstick : b6, rightstick : b7, leftshoulder : b4, rightshoulder : b5, dpup : b8, dpleft : b10, dpdown : b9, dpright : b11, leftx : a0, lefty : a1, rightx : a3, righty : a4, lefttrigger : b12, righttrigger : b13,
|
||||||
|
4f0400b3000000000000504944564944, Thrustmaster Firestorm Dual Power, a : b0, b : b2, y : b3, x : b1, start : b10, guide : b8, back : b9, leftstick : b11, rightstick : b12, leftshoulder : b4, rightshoulder : b6, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b5, righttrigger : b7, platform : Windows,
|
||||||
|
00f00300000000000000504944564944, RetroUSB.com RetroPad, a : b1, b : b5, x : b0, y : b4, back : b2, start : b3, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1, platform : Windows,
|
||||||
|
00f0f100000000000000504944564944, RetroUSB.com Super RetroPort, a : b1, b : b5, x : b0, y : b4, back : b2, start : b3, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1, platform : Windows,
|
||||||
|
28040140000000000000504944564944, GamePad Pro USB, platform : Windows, a : b1, b : b2, x : b0, y : b3, back : b8, start : b9, leftshoulder : b4, rightshoulder : b5, leftx : a0, lefty : a1, lefttrigger : b6, righttrigger : b7,
|
||||||
|
ff113133000000000000504944564944, SVEN X - PAD, platform : Windows, a : b2, b : b3, y : b1, x : b0, start : b5, back : b4, leftshoulder : b6, rightshoulder : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a4, lefttrigger : b8, righttrigger : b9,
|
||||||
|
8f0e0300000000000000504944564944, Piranha xtreme, platform : Windows, x : b3, a : b2, b : b1, y : b0, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b6, lefttrigger : b4, rightshoulder : b7, righttrigger : b5, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a2,
|
||||||
|
8f0e0d31000000000000504944564944, Multilaser JS071 USB, platform : Windows, a : b1, b : b2, y : b3, x : b0, start : b9, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7,
|
||||||
|
10080300000000000000504944564944, PS2 USB, platform : Windows, a : b2, b : b1, y : b0, x : b3, start : b9, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b6, rightshoulder : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a4, righty : a2, lefttrigger : b4, righttrigger : b5,
|
||||||
|
79000600000000000000504944564944, G - Shark GS - GP702, 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 : a4, lefttrigger : b6, righttrigger : b7, platform : Windows,
|
||||||
|
4b12014d000000000000504944564944, NYKO AIRFLO, a : b0, b : b1, x : b2, y : b3, back : b8, guide : b10, start : b9, leftstick : a0, rightstick : a2, leftshoulder : a3, rightshoulder : b5, dpup : h0.1, dpdown : h0.0, dpleft : h0.8, dpright : h0.2, leftx : h0.6, lefty : h0.12, rightx : h0.9, righty : h0.4, lefttrigger : b6, righttrigger : b7, platform : Windows,
|
||||||
|
d6206dca000000000000504944564944, PowerA Pro Ex, 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.0, dpleft : h0.8, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, platform : Windows,
|
||||||
|
a3060cff000000000000504944564944, Saitek P2500, a : b2, b : b3, y : b1, x : b0, start : b4, guide : b10, back : b5, leftstick : b8, rightstick : b9, leftshoulder : b6, rightshoulder : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, platform : Windows,
|
||||||
|
4f0415b3000000000000504944564944, Thrustmaster Dual Analog 3.2, platform : Windows, x : b1, a : b0, b : b2, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b5, rightshoulder : b6, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
6f0e1e01000000000000504944564944, Rock Candy Gamepad for PS3, platform : Windows, a : b1, b : b2, x : b0, y : b3, back : b8, start : b9, guide : b12, leftshoulder : b4, rightshoulder : b5, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2,
|
||||||
|
83056020000000000000504944564944, iBuffalo USB 2 - axis 8 - button Gamepad, a : b1, b : b0, y : b2, x : b3, start : b7, back : b6, leftshoulder : b4, rightshoulder : b5, leftx : a0, lefty : a1, platform : Windows,
|
||||||
|
10080100000000000000504944564944, PS1 USB, platform : Windows, a : b2, b : b1, x : b3, y : b0, back : b8, start : b9, leftshoulder : b6, rightshoulder : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a2, lefttrigger : b4, righttrigger : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2,
|
||||||
|
49190204000000000000504944564944, Ipega PG - 9023, a : b0, b : b1, x : b3, y : b4, back : b10, 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 : a3, righty : a4, lefttrigger : b8, righttrigger : b9, platform : Windows,
|
||||||
|
4f0423b3000000000000504944564944, Dual Trigger 3 - in - 1, a : b1, b : b2, x : b0, y : b3, 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 : a5, lefttrigger : b6, righttrigger : b7, platform : Windows,
|
||||||
|
0d0f4900000000000000504944564944, Hatsune Miku Sho Controller, 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 : Windows,
|
||||||
|
79004318000000000000504944564944, Mayflash GameCube Controller Adapter, platform : Windows, a : b1, b : b2, x : b0, y : b3, back : b0, start : b9, guide : b0, leftshoulder : b4, rightshoulder : b7, leftstick : b0, rightstick : b0, leftx : a0, lefty : a1, rightx : a5, righty : a2, lefttrigger : a3, righttrigger : a4, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2,
|
||||||
|
79000018000000000000504944564944, Mayflash WiiU Pro Game Controller Adapter(DInput), a : b1, b : b2, x : b0, y : b3, 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 : Windows,
|
||||||
|
2509e803000000000000504944564944, Mayflash Wii Classic Controller, a : b1, b : b0, x : b3, y : b2, back : b8, guide : b10, start : b9, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : b11, dpdown : b13, dpleft : b12, dpright : b14, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, platform : Windows,
|
||||||
|
300f1001000000000000504944564944, Saitek P480 Rumble Pad, a : b2, b : b3, x : b0, y : b1, back : b8, start : b9, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b6, dpup : h0.1, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, leftx : a0, lefty : a1, rightx : a3, righty : a2, lefttrigger : b5, righttrigger : b7, platform : Windows,
|
||||||
|
10280900000000000000504944564944, 8Bitdo SFC30 GamePad, a : b1, b : b0, y : b3, x : b4, start : b11, back : b10, leftshoulder : b6, leftx : a0, lefty : a1, rightshoulder : b7, platform : Windows,
|
||||||
|
63252305000000000000504944564944, USB Vibration Joystick(BM), platform : Windows, x : b3, a : b2, b : b1, y : b0, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
20380900000000000000504944564944, 8Bitdo NES30 PRO Wireless, platform : Windows, a : b0, b : b1, x : b3, y : b4, leftshoulder : b6, rightshoulder : b7, lefttrigger : b8, righttrigger : b9, back : b10, start : b11, leftstick : b13, rightstick : b14, leftx : a0, lefty : a1, rightx : a3, righty : a4, dpup : h0.1, dpright : h0.2, dpdown : h0.4, dpleft : h0.8,
|
||||||
|
02200090000000000000504944564944, 8Bitdo NES30 PRO USB, platform:Windows, a : b0, b : b1, x : b3, y : b4, leftshoulder : b6, rightshoulder : b7, lefttrigger : b8, righttrigger : b9, back : b10, start : b11, leftstick : b13, rightstick : b14, leftx : a0, lefty : a1, rightx : a3, righty : a4, dpup : h0.1, dpright : h0.2, dpdown : h0.4, dpleft : h0.8,
|
||||||
|
ff113133000000000000504944564944, Gembird JPD - DualForce, platform : Windows, a : b2, b : b3, x : b0, y : b1, start : b9, back : b8, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a4, lefttrigger : b6, righttrigger : b7, leftstick : b10, rightstick : b11,
|
||||||
|
341a0108000000000000504944564944, EXEQ RF USB Gamepad 8206, a : b0, b : b1, x : b2, y : b3, leftshoulder : b4, rightshoulder : b5, leftstick : b8, rightstick : b7, back : b8, start : b9, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, leftx : a0, lefty : a1, rightx : a2, righty : a3, platform : Windows,
|
||||||
|
c0111352000000000000504944564944, Battalife Joystick, platform : Windows, x : b4, a : b6, b : b7, y : b5, back : b2, start : b3, leftshoulder : b0, rightshoulder : b1, leftx : a0, lefty : a1,
|
||||||
|
)";
|
||||||
|
const char* db_file2 = R"(
|
||||||
|
# OS X
|
||||||
|
0500000047532047616d657061640000, GameStop Gamepad, a:b0, b : b1, back : b8, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, guide : , 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,
|
||||||
|
6d0400000000000016c2000000000000, 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,
|
||||||
|
6d0400000000000018c2000000000000, 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,
|
||||||
|
6d040000000000001fc2000000000000, 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,
|
||||||
|
6d0400000000000019c2000000000000, 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,
|
||||||
|
4c050000000000006802000000000000, 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,
|
||||||
|
4c05000000000000c405000000000000, 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,
|
||||||
|
5e040000000000008e02000000000000, 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,
|
||||||
|
891600000000000000fd000000000000, Razer Onza Tournament, a : b0, b : b1, y : b3, x : b2, start : b8, guide : b10, back : b9, leftstick : b6, rightstick : b7, leftshoulder : b4, rightshoulder : b5, dpup : b11, dpleft : b13, dpdown : b12, dpright : b14, leftx : a0, lefty : a1, rightx : a3, righty : a4, lefttrigger : a2, righttrigger : a5, platform : Mac OS X,
|
||||||
|
4f0400000000000000b3000000000000, Thrustmaster Firestorm Dual Power, a : b0, b : b2, y : b3, x : b1, start : b10, guide : b8, back : b9, leftstick : b11, rightstick : , leftshoulder : b4, rightshoulder : b6, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b5, righttrigger : b7, platform : Mac OS X,
|
||||||
|
8f0e0000000000000300000000000000, Piranha xtreme, platform : Mac OS X, x : b3, a : b2, b : b1, y : b0, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b6, lefttrigger : b4, rightshoulder : b7, righttrigger : b5, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a2,
|
||||||
|
0d0f0000000000004d00000000000000, HORI Gem Pad 3, platform : Mac OS X, a : b1, b : b2, y : b3, x : b0, start : b9, guide : b12, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7,
|
||||||
|
79000000000000000600000000000000, G - Shark GP - 702, 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 : a3, righty : a4, lefttrigger : b6, righttrigger : b7, platform : Mac OS X,
|
||||||
|
4f0400000000000015b3000000000000, Thrustmaster Dual Analog 3.2, platform : Mac OS X, x : b1, a : b0, b : b2, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b5, rightshoulder : b6, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
AD1B00000000000001F9000000000000, 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,
|
||||||
|
050000005769696d6f74652028303000, Wii Remote, a:b4, b : b5, y : b9, x : b10, start : b6, guide : b8, back : b7, dpup : b2, dpleft : b0, dpdown : b3, dpright : b1, leftx : a0, lefty : a1, lefttrigger : b12, righttrigger : , leftshoulder : b11, platform : Mac OS X,
|
||||||
|
83050000000000006020000000000000, iBuffalo USB 2 - axis 8 - button Gamepad, a : b1, b : b0, x : b3, y : b2, back : b6, start : b7, leftshoulder : b4, rightshoulder : b5, leftx : a0, lefty : a1, platform : Mac OS X,
|
||||||
|
5e04000000000000dd02000000000000, Xbox One Wired Controller, platform : Mac OS X, x : b2, a : b0, b : b1, y : b3, back : b9, guide : b10, start : b8, dpleft : b13, dpdown : b12, dpright : b14, dpup : b11, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b6, rightstick : b7, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
050000005769696d6f74652028313800, Wii U Pro Controller, a:b16, b : b15, x : b18, y : b17, back : b7, guide : b8, start : b6, leftstick : b23, rightstick : b24, leftshoulder : b19, rightshoulder : b20, dpup : b11, dpdown : b12, dpleft : b13, dpright : b14, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b21, righttrigger : b22, platform : Mac OS X,
|
||||||
|
79000000000000000018000000000000, Mayflash WiiU Pro Game Controller Adapter(DInput), a : b4, b : b8, x : b0, y : b12, back : b32, start : b36, leftstick : b40, rightstick : b44, leftshoulder : b16, rightshoulder : b20, dpup : h0.1, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, leftx : a0, lefty : a4, rightx : a8, righty : a12, lefttrigger : b24, righttrigger : b28, platform : Mac OS X,
|
||||||
|
2509000000000000e803000000000000, Mayflash Wii Classic Controller, a : b1, b : b0, x : b3, y : b2, back : b8, guide : b10, start : b9, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : b11, dpdown : b13, dpleft : b12, dpright : b14, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, platform : Mac OS X,
|
||||||
|
351200000000000021ab000000000000, SFC30 Joystick, a : b1, b : b0, x : b4, y : b3, back : b10, start : b11, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1, platform : Mac OS X,
|
||||||
|
b4040000000000000a01000000000000, Sega Saturn USB Gamepad, a : b0, b : b1, x : b3, y : b4, back : b5, guide : b2, start : b8, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1, platform : Mac OS X,
|
||||||
|
10280000000000000900000000000000, 8Bitdo SFC30 GamePad, a : b1, b : b0, x : b4, y : b3, back : b10, start : b11, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1, platform : Mac OS X,
|
||||||
|
d814000000000000cecf000000000000, MC Cthulhu, platform : Mac OS X, leftx : , lefty : , rightx : , righty : , lefttrigger : b6, a : b1, b : b2, y : b3, x : b0, start : b9, back : b8, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, righttrigger : b7,
|
||||||
|
0d0f0000000000006600000000000000, HORIPAD FPS PLUS 4, platform : Mac OS X, a : b1, b : b2, y : b3, x : b0, start : b9, guide : b12, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a5, lefttrigger : b6, righttrigger : a4,\
|
||||||
|
)";
|
||||||
|
const char* db_file3 = R"(
|
||||||
|
# Linux
|
||||||
|
0500000047532047616d657061640000, GameStop Gamepad, a:b0, b : b1, back : b8, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, guide : , 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,
|
||||||
|
03000000ba2200002010000001010000, Jess Technology USB Game Controller, a : b2, b : b1, back : b8, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, dpup : h0.1, guide : , leftshoulder : b4, lefttrigger : b6, leftx : a0, lefty : a1, rightshoulder : b5, righttrigger : b7, rightx : a3, righty : a2, start : b9, x : b3, y : b0, 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, guide : , 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,
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
030000004c050000c405000011010000, Sony DualShock 4, a : b1, b : b2, y : b3, x : b0, start : b9, guide : b12, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a5, lefttrigger : b6, righttrigger : b7, platform : Linux,
|
||||||
|
030000006f0e00003001000001010000, EA Sports PS3 Controller, platform : Linux, a : b1, b : b2, y : b3, x : b0, start : b9, guide : b12, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7,
|
||||||
|
03000000de280000ff11000001000000, Valve Streaming 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,
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
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,
|
||||||
|
03000000100800000100000010010000, Twin USB PS2 Adapter, a:b2, b : b1, y : b0, x : b3, start : b9, guide : , back : b8, leftstick : b10, rightstick : b11, leftshoulder : b6, rightshoulder : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a3, righty : a2, lefttrigger : b4, righttrigger : b5, platform : Linux,
|
||||||
|
03000000a306000023f6000011010000, Saitek Cyborg V.1 Game Pad, a : b1, b : b2, y : b3, x : b0, start : b9, guide : b12, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a4, lefttrigger : b6, righttrigger : b7, platform : Linux,
|
||||||
|
030000004f04000020b3000010010000, Thrustmaster 2 in 1 DT, a : b0, b : b2, y : b3, x : b1, start : b9, guide : , back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b6, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b5, righttrigger : b7, platform : Linux,
|
||||||
|
030000004f04000023b3000000010000, Thrustmaster Dual Trigger 3 - in - 1, platform : Linux, x : b0, a : b1, b : b2, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a5,
|
||||||
|
030000008f0e00000300000010010000, GreenAsia Inc.USB Joystick, platform:Linux, x : b3, a : b2, b : b1, y : b0, back : b8, start : b9, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b6, lefttrigger : b4, rightshoulder : b7, righttrigger : b5, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a2,
|
||||||
|
030000008f0e00001200000010010000, GreenAsia Inc.USB Joystick, platform:Linux, x : b2, a : b0, b : b1, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b5, rightshoulder : b6, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a2,
|
||||||
|
030000005e0400009102000007010000, X360 Wireless Controller, a : b0, b : b1, y : b3, x : b2, start : b7, guide : b8, back : b6, leftstick : b9, rightstick : b10, leftshoulder : b4, rightshoulder : b5, dpup : b13, dpleft : b11, dpdown : b14, dpright : b12, leftx : a0, lefty : a1, rightx : a3, righty : a4, lefttrigger : a2, righttrigger : a5, platform : Linux,
|
||||||
|
030000006d04000016c2000010010000, Logitech Logitech Dual Action, platform : Linux, x : b0, a : b1, b : b2, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
03000000260900008888000000010000, GameCube{ WiseGroup USB box }, a:b0, b : b2, y : b3, x : b1, start : b7, leftshoulder : , rightshoulder : b6, dpup : h0.1, dpleft : h0.8, rightstick : , dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : a4, righttrigger : a5, platform : Linux,
|
||||||
|
030000006d04000011c2000010010000, Logitech WingMan Cordless RumblePad, a : b0, b : b1, y : b4, x : b3, start : b8, guide : b5, back : b2, leftshoulder : b6, rightshoulder : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a3, righty : a4, lefttrigger : b9, righttrigger : b10, platform : Linux,
|
||||||
|
030000006d04000018c2000010010000, Logitech Logitech RumblePad 2 USB, platform : Linux, x : b0, a : b1, b : b2, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
05000000d6200000ad0d000001000000, Moga Pro, platform : Linux, a : b0, b : b1, y : b3, x : b2, start : b6, leftstick : b7, rightstick : b8, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : a5, righttrigger : a4,
|
||||||
|
030000004f04000009d0000000010000, Thrustmaster Run N Drive Wireless PS3, platform : Linux, a : b1, b : b2, x : b0, y : b3, start : b9, guide : b12, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7,
|
||||||
|
030000004f04000008d0000000010000, Thrustmaster Run N Drive Wireless, platform : Linux, a : b1, b : b2, x : b0, y : b3, start : b9, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a5, lefttrigger : b6, righttrigger : b7,
|
||||||
|
0300000000f000000300000000010000, RetroUSB.com RetroPad, a : b1, b : b5, x : b0, y : b4, back : b2, start : b3, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1, platform : Linux,
|
||||||
|
0300000000f00000f100000000010000, RetroUSB.com Super RetroPort, a : b1, b : b5, x : b0, y : b4, back : b2, start : b3, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1, platform : Linux,
|
||||||
|
030000006f0e00001f01000000010000, Generic X - Box pad, platform : Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
03000000280400000140000000010000, Gravis GamePad Pro USB, platform:Linux, x : b0, a : b1, b : b2, y : b3, back : b8, start : b9, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftx : a0, lefty : a1,
|
||||||
|
030000005e0400008902000021010000, Microsoft X - Box pad v2(US), platform : Linux, x : b3, a : b0, b : b1, y : b4, back : b6, start : b7, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b5, lefttrigger : a2, rightshoulder : b2, righttrigger : a5, leftstick : b8, rightstick : b9, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
030000005e0400008502000000010000, Microsoft X - Box pad(Japan), platform : Linux, x : b3, a : b0, b : b1, y : b4, back : b6, start : b7, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b5, lefttrigger : a2, rightshoulder : b2, righttrigger : a5, leftstick : b8, rightstick : b9, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
030000006f0e00001e01000011010000, Rock Candy Gamepad for PS3, platform : Linux, a : b1, b : b2, x : b0, y : b3, back : b8, start : b9, guide : b12, leftshoulder : b4, rightshoulder : b5, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2,
|
||||||
|
03000000250900000500000000010000, Sony PS2 pad with SmartJoy adapter, platform:Linux, a : b2, b : b1, y : b0, x : b3, start : b8, back : b9, leftstick : b10, rightstick : b11, leftshoulder : b6, rightshoulder : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b4, righttrigger : b5,
|
||||||
|
030000008916000000fd000024010000, Razer Onza Tournament, a:b0, b : b1, y : b3, x : b2, start : b7, guide : b8, back : b6, leftstick : b9, rightstick : b10, leftshoulder : b4, rightshoulder : b5, dpup : b13, dpleft : b11, dpdown : b14, dpright : b12, leftx : a0, lefty : a1, rightx : a3, righty : a4, lefttrigger : a2, righttrigger : a5, platform : Linux,
|
||||||
|
030000004f04000000b3000010010000, Thrustmaster Firestorm Dual Power, a : b0, b : b2, y : b3, x : b1, start : b10, guide : b8, back : b9, leftstick : b11, rightstick : b12, leftshoulder : b4, rightshoulder : b6, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b5, righttrigger : b7, platform : Linux,
|
||||||
|
03000000ad1b000001f5000033050000, Hori Pad EX Turbo 2, 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,
|
||||||
|
050000004c050000c405000000010000, PS4 Controller(Bluetooth), a : 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,
|
||||||
|
060000004c0500006802000000010000, PS3 Controller(Bluetooth), a : b14, b : b13, y : b12, x : b15, start : b3, guide : b16, back : b0, leftstick : b1, rightstick : b2, leftshoulder : b10, rightshoulder : b11, dpup : b4, dpleft : b7, dpdown : b6, dpright : b5, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b8, righttrigger : b9, platform : Linux,
|
||||||
|
050000004c0500006802000000010000, PS3 Controller(Bluetooth), a : b14, b : b13, y : b12, x : b15, start : b3, guide : b16, back : b0, leftstick : b1, rightstick : b2, leftshoulder : b10, rightshoulder : b11, dpup : b4, dpleft : b7, dpdown : b6, dpright : b5, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b8, righttrigger : b9, platform : Linux,
|
||||||
|
03000000790000000600000010010000, DragonRise Inc.Generic USB Joystick, platform:Linux, x : b3, a : b2, b : b1, y : b0, back : b8, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
03000000666600000488000000010000, Super Joy Box 5 Pro, platform:Linux, a : b2, b : b1, x : b3, y : b0, back : b9, start : b8, leftshoulder : b6, rightshoulder : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b4, righttrigger : b5, dpup : b12, dpleft : b15, dpdown : b14, dpright : b13,
|
||||||
|
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, platform : Linux, rightshoulder : b5, rightstick : b7, righttrigger : a5, rightx : a3, righty : a4, x : b1, y : b2,
|
||||||
|
)";
|
||||||
|
const char* db_file4 = R"(
|
||||||
|
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, platform : Linux, rightshoulder : b5, rightstick : b7, righttrigger : a5, rightx : a3, righty : a4, x : b1, y : b2,
|
||||||
|
030000008916000001fd000024010000, Razer Onza Classic Edition, platform:Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : b11, dpdown : b14, dpright : b12, dpup : b13, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
030000005e040000d102000001010000, Microsoft X - Box One pad, platform : Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
030000005e040000dd02000003020000, Microsoft X - Box One pad v2, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4, platform : Linux,
|
||||||
|
03000000790000001100000010010000, RetroLink Saturn Classic Controller, platform:Linux, x : b3, a : b0, b : b1, y : b4, back : b5, guide : b2, start : b8, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1,
|
||||||
|
050000007e0500003003000001000000, Nintendo Wii U Pro Controller, platform : Linux, a : b0, b : b1, x : b3, y : b2, back : b8, start : b9, guide : b10, leftshoulder : b4, rightshoulder : b5, leftstick : b11, rightstick : b12, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, dpup : b13, dpleft : b15, dpdown : b14, dpright : b16,
|
||||||
|
030000005e0400008e02000004010000, Microsoft X - Box 360 pad, platform : Linux, a : b0, b : b1, x : b2, y : b3, back : b6, start : b7, guide : b8, leftshoulder : b4, rightshoulder : b5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4, lefttrigger : a2, righttrigger : a5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2,
|
||||||
|
030000000d0f00002200000011010000, HORI CO.LTD.REAL ARCADE Pro.V3, platform : Linux, x : b0, a : b1, b : b2, y : b3, back : b8, guide : b12, start : b9, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1,
|
||||||
|
030000000d0f00001000000011010000, HORI CO.LTD.FIGHTING STICK 3, platform : Linux, x : b0, a : b1, b : b2, y : b3, back : b8, guide : b12, start : b9, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7
|
||||||
|
03000000f0250000c183000010010000, Goodbetterbest Ltd USB Controller, platform : Linux, x : b0, a : b1, b : b2, y : b3, back : b8, guide : b12, start : b9, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
0000000058626f782047616d65706100, Xbox Gamepad(userspace driver), platform:Linux, a : b0, b : b1, x : b2, y : b3, start : b7, back : b6, guide : b8, dpup : h0.1, dpdown : h0.4, dpleft : h0.8, dpright : h0.2, leftshoulder : b4, rightshoulder : b5, lefttrigger : a5, righttrigger : a4, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
03000000ff1100003133000010010000, PC Game Controller, a : b2, b : b1, y : b0, x : b3, start : b9, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7, platform : Linux,
|
||||||
|
030000005e0400008e02000020200000, SpeedLink XEOX Pro Analog Gamepad pad, platform : Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
030000006f0e00001304000000010000, Generic X - Box pad, platform : Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : a0, rightstick : a3, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
03000000a306000018f5000010010000, Saitek PLC Saitek P3200 Rumble Pad, platform : Linux, x : b0, a : b1, b : b2, y : b3, back : b8, start : b9, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : a2, rightshoulder : b6, rightshoulder : b5, righttrigger : b7, leftstick : b10, rightstick : b11, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
03000000830500006020000010010000, iBuffalo USB 2 - axis 8 - button Gamepad, a:b1, b : b0, x : b3, y : b2, back : b6, start : b7, leftshoulder : b4, rightshoulder : b5, leftx : a0, lefty : a1, platform : Linux,
|
||||||
|
03000000c9110000f055000011010000, HJC Game GAMEPAD, leftx : a0, lefty : a1, dpdown : h0.4, rightstick : b11, rightshoulder : b5, rightx : a2, start : b9, righty : a3, dpleft : h0.8, lefttrigger : b6, x : b2, dpup : h0.1, back : b8, leftstick : b10, leftshoulder : b4, y : b3, a : b0, dpright : h0.2, righttrigger : b7, b : b1, platform : Linux,
|
||||||
|
03000000a30600000c04000011010000, Saitek P2900 Wireless Pad, a : b1, b : b2, y : b3, x : b0, start : b12, guide : b9, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b6, rightshoulder : b7, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a3, righty : a2, lefttrigger : b4, righttrigger : b5, platform : Linux,
|
||||||
|
03000000341a000005f7000010010000, GameCube{ HuiJia USB box }, a : b1, b : b2, y : b3, x : b0, start : b9, guide : , back : , leftstick : , rightstick : , leftshoulder : , dpleft : b15, dpdown : b14, dpright : b13, leftx : a0, lefty : a1, rightx : a5, righty : a2, lefttrigger : a3, righttrigger : a4, rightshoulder : b7, dpup : b12, platform : Linux,
|
||||||
|
030000006e0500000320000010010000, JC - U3613M - DirectInput Mode, platform : Linux, x : b0, a : b2, b : b3, y : b1, back : b10, guide : b12, start : b11, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : b6, rightshoulder : b5, righttrigger : b7, leftstick : b8, rightstick : b9, leftx : a0, lefty : a1, rightx : a2, righty : a3,
|
||||||
|
030000006f0e00004601000001010000, Rock Candy Wired Controller for Xbox One, platform : Linux, a : b0, b : b1, x : b2, y : b3, leftshoulder : b4, rightshoulder : b5, back : b6, start : b7, guide : b8, leftstick : b9, rightstick : b10, lefttrigger : a2, righttrigger : a5, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
03000000380700001647000010040000, Mad Catz Wired Xbox 360 Controller, platform:Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
030000006f0e00003901000020060000, Afterglow Wired Controller for Xbox One, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4, platform : Linux,
|
||||||
|
030000004f04000015b3000010010000, Thrustmaster Dual Analog 4, platform : Linux, a : b0, b : b2, x : b1, y : b3, start : b9, back : b8, leftstick : b10, rightstick : b11, leftshoulder : b4, rightshoulder : b6, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b5, righttrigger : b7,
|
||||||
|
05000000102800000900000000010000, 8Bitdo SFC30 GamePad, platform:Linux, x : b4, a : b1, b : b0, y : b3, back : b10, start : b11, leftshoulder : b6, rightshoulder : b7, leftx : a0, lefty : a1,
|
||||||
|
03000000d81400000862000011010000, HitBox(PS3 / PC) Analog Mode, platform : Linux, a : b1, b : b2, y : b3, x : b0, start : b12, guide : b9, back : b8, leftshoulder : b4, rightshoulder : b5, lefttrigger : b6, righttrigger : b7, leftx : a0, lefty : a1,
|
||||||
|
030000000d0f00000d00000000010000, hori, platform : Linux, a : b0, b : b6, y : b2, x : b1, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, start : b9, guide : b10, back : b8, leftshoulder : b3, rightshoulder : b7, leftx : b4, lefty : b5,
|
||||||
|
03000000ad1b000016f0000090040000, Mad Catz Xbox 360 Controller, platform : Linux, 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,
|
||||||
|
03000000d814000007cd000011010000, Toodles 2008 Chimp PC / PS3, platform : Linux, a : b0, b : b1, y : b2, x : b3, start : b9, back : b8, leftshoulder : b4, rightshoulder : b5, leftx : a0, lefty : a1, lefttrigger : b6, righttrigger : b7,
|
||||||
|
03000000fd0500000030000000010000, InterAct GoPad I - 73000 (Fighting Game Layout), platform : Linux, a : b3, b : b4, y : b1, x : b0, start : b7, back : b6, leftx : a0, lefty : a1, rightshoulder : b2, righttrigger : b5,
|
||||||
|
05000000010000000100000003000000, Nintendo Wiimote, platform : Linux, a : b0, b : b1, y : b3, x : b2, start : b9, guide : b10, back : b8, leftstick : b11, rightstick : b12, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a2, righty : a3, lefttrigger : b6, righttrigger : b7,
|
||||||
|
030000005e0400008e02000062230000, Microsoft X - Box 360 pad, platform : Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, dpup : h0.1, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
03000000a30600000901000000010000, Saitek P880, a : b2, b : b3, y : b1, x : b0, leftstick : b8, rightstick : b9, leftshoulder : b4, rightshoulder : b5, dpup : h0.1, dpleft : h0.8, dpdown : h0.4, dpright : h0.2, leftx : a0, lefty : a1, rightx : a3, righty : a2, lefttrigger : b6, righttrigger : b7, platform : Linux,
|
||||||
|
030000006f0e00000103000000020000, Logic3 Controller, platform : Linux, x : b2, a : b0, b : b1, y : b3, back : b6, guide : b8, start : b7, dpleft : h0.8, dpdown : h0.0, dpdown : h0.4, dpright : h0.0, dpright : h0.2, dpup : h0.0, dpup : h0.1, leftshoulder : h0.0, leftshoulder : b4, lefttrigger : a2, rightshoulder : b5, righttrigger : a5, leftstick : b9, rightstick : b10, leftx : a0, lefty : a1, rightx : a3, righty : a4,
|
||||||
|
)";
|
||||||
|
}
|
105
src/input_core/devices/keyboard.cpp
Normal file
105
src/input_core/devices/keyboard.cpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <SDL_keyboard.h>
|
||||||
|
|
||||||
|
#include "input_core/devices/keyboard.h"
|
||||||
|
|
||||||
|
Keyboard::Keyboard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Keyboard::~Keyboard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Keyboard::InitDevice(int number, const std::map<std::string, std::vector<Service::HID::PadState>>& keyMap) {
|
||||||
|
key_mapping = keyMap;
|
||||||
|
|
||||||
|
//Check if keyboard is mapped for circle up or left. if so, set modifier to -1
|
||||||
|
for (const auto& entry : key_mapping) {
|
||||||
|
if (entry.first == "")
|
||||||
|
continue;
|
||||||
|
for (const auto& padstate : entry.second) {
|
||||||
|
if (padstate == Service::HID::PAD_CIRCLE_UP || padstate == Service::HID::PAD_CIRCLE_LEFT) {
|
||||||
|
circle_pad_directions[stoi(entry.first)] = -1.0;
|
||||||
|
}
|
||||||
|
else if (padstate == Service::HID::PAD_CIRCLE_DOWN || padstate == Service::HID::PAD_CIRCLE_RIGHT) {
|
||||||
|
circle_pad_directions[stoi(entry.first)] = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Check if responsible for circle pad modifier
|
||||||
|
auto mapping = Settings::values.pad_circle_modifier;
|
||||||
|
if (mapping.device == Settings::Device::Keyboard && mapping.key != "")
|
||||||
|
circle_pad_modifier = KeyboardKey(stoi(mapping.key),"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard::ProcessInput() {
|
||||||
|
std::map<KeyboardKey, bool> keysPressedCopy;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
keysPressedCopy = keys_pressed;
|
||||||
|
}
|
||||||
|
bool circlePadModPressed = keysPressedCopy[circle_pad_modifier];
|
||||||
|
for (const auto& entry : key_mapping) {
|
||||||
|
if (entry.first == "")
|
||||||
|
continue;
|
||||||
|
int keycode = std::stoi(entry.first);
|
||||||
|
KeyboardKey proxy = KeyboardKey(keycode, "");
|
||||||
|
|
||||||
|
//if key is pressed when prev state is unpressed, or if key pressed and is a circle pad direction
|
||||||
|
if ((keysPressedCopy[proxy] == true && keys_pressed_last[keycode] == false) || (keysPressedCopy[proxy] == true && circle_pad_directions.count(keycode))) {
|
||||||
|
for (const auto& key : entry.second) {
|
||||||
|
if (circle_pad_directions.count(keycode)) { //If is analog key press
|
||||||
|
float modifier = (circlePadModPressed) ? Settings::values.pad_circle_modifier_scale : 1;
|
||||||
|
KeyMap::PressKey(key, circle_pad_directions[keycode] * modifier);
|
||||||
|
}
|
||||||
|
else // Is digital key press
|
||||||
|
KeyMap::PressKey(key, 1.0);
|
||||||
|
}
|
||||||
|
keys_pressed_last[keycode] = true;
|
||||||
|
}
|
||||||
|
else if (keysPressedCopy[proxy] == false && keys_pressed_last[keycode] == true) {
|
||||||
|
for (const auto& key : entry.second) {
|
||||||
|
KeyMap::ReleaseKey(key);
|
||||||
|
}
|
||||||
|
keys_pressed_last[keycode] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Keyboard::CloseDevice() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard::KeyPressed(KeyboardKey key) {
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
keys_pressed[key] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard::KeyReleased(KeyboardKey key) {
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
keys_pressed[key] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard::Clear() {
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
keys_pressed.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::InputDeviceMapping Keyboard::GetInput() {
|
||||||
|
std::map<KeyboardKey, bool> keysPressedCopy;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m);
|
||||||
|
keysPressedCopy = keys_pressed;
|
||||||
|
}
|
||||||
|
for (const auto& entry : keysPressedCopy) {
|
||||||
|
int keycode = entry.first.key;
|
||||||
|
if (keysPressedCopy[entry.first] == true && keys_pressed_last[keycode] == false) {
|
||||||
|
return Settings::InputDeviceMapping("QT/0/Keyboard/" + std::to_string(keycode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Settings::InputDeviceMapping("");
|
||||||
|
}
|
48
src/input_core/devices/keyboard.h
Normal file
48
src/input_core/devices/keyboard.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "input_core/devices/device.h"
|
||||||
|
|
||||||
|
struct KeyboardKey {
|
||||||
|
uint32_t key;
|
||||||
|
std::string character;
|
||||||
|
|
||||||
|
KeyboardKey() = default;
|
||||||
|
KeyboardKey(uint32_t key_, std::string character_)
|
||||||
|
: key(key_), character(std::move(character_)) {
|
||||||
|
}
|
||||||
|
bool operator==(const KeyboardKey& other) const {
|
||||||
|
return key == other.key;
|
||||||
|
}
|
||||||
|
bool operator==(uint32_t other) const {
|
||||||
|
return key == other;
|
||||||
|
}
|
||||||
|
bool operator<(const KeyboardKey& other) const {
|
||||||
|
return key < other.key;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class Keyboard : public IDevice {
|
||||||
|
public:
|
||||||
|
Keyboard();
|
||||||
|
~Keyboard();
|
||||||
|
bool InitDevice(int number, const std::map<std::string, std::vector<Service::HID::PadState>>& keyMap) override;
|
||||||
|
void ProcessInput() override;
|
||||||
|
bool CloseDevice() override;
|
||||||
|
void KeyPressed(KeyboardKey key);
|
||||||
|
void KeyReleased(KeyboardKey key);
|
||||||
|
void Clear() override;
|
||||||
|
Settings::InputDeviceMapping GetInput() override;
|
||||||
|
private:
|
||||||
|
std::map<KeyboardKey, bool> keys_pressed;
|
||||||
|
std::map<int, bool> keys_pressed_last;
|
||||||
|
std::mutex m; ///< Keys pressed from frontend is on a separate thread.
|
||||||
|
std::map<int, float> circle_pad_directions; ///< Inverts the strength of key press if it is a circle pad direction that needs it.
|
||||||
|
KeyboardKey circle_pad_modifier;
|
||||||
|
};
|
184
src/input_core/devices/sdl_gamepad.cpp
Normal file
184
src/input_core/devices/sdl_gamepad.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_gamecontroller.h>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
|
|
||||||
|
#include "input_core/devices/sdl_gamepad.h"
|
||||||
|
#include "input_core/devices/gamecontrollerdb.h"
|
||||||
|
|
||||||
|
bool SDLGamepad::SDLInitialized = false;
|
||||||
|
|
||||||
|
SDLGamepad::SDLGamepad() {
|
||||||
|
}
|
||||||
|
SDLGamepad::SDLGamepad(int number_, _SDL_GameController* gamepad_)
|
||||||
|
: number(number_), gamepad(gamepad_) {
|
||||||
|
|
||||||
|
}
|
||||||
|
SDLGamepad::~SDLGamepad() {
|
||||||
|
CloseDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLGamepad::InitDevice(int number, const std::map<std::string, std::vector<Service::HID::PadState>>& keyMap) {
|
||||||
|
if (!SDLGamepad::SDLInitialized && SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) {
|
||||||
|
LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_GAMECONTROLLER) failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SDL_GameControllerEventState(SDL_IGNORE);
|
||||||
|
SDLGamepad::SDLInitialized = true;
|
||||||
|
LoadGameControllerDB();
|
||||||
|
|
||||||
|
if (SDL_IsGameController(number)) {
|
||||||
|
gamepad = SDL_GameControllerOpen(number);
|
||||||
|
if (gamepad == nullptr) {
|
||||||
|
LOG_INFO(Input, "Controller found but unable to open connection.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key_mapping = keyMap;
|
||||||
|
for (const auto& entry : key_mapping) {
|
||||||
|
keys_pressed[entry.first] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLGamepad::ProcessInput() {
|
||||||
|
if (gamepad == nullptr)
|
||||||
|
return;
|
||||||
|
SDL_GameControllerUpdate();
|
||||||
|
for (const auto& entry : key_mapping) {
|
||||||
|
SDL_GameControllerButton button = SDL_GameControllerGetButtonFromString(gamepadinput_to_sdlname_mapping[static_cast<GamepadInputs>(stoi(entry.first))].c_str());
|
||||||
|
if (button != SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_INVALID) {
|
||||||
|
Uint8 pressed = SDL_GameControllerGetButton(gamepad, button);
|
||||||
|
if (pressed == 1 && keys_pressed[entry.first] == false) {
|
||||||
|
for (const auto& padstate : entry.second) {
|
||||||
|
KeyMap::PressKey(padstate, 1.0);
|
||||||
|
keys_pressed[entry.first] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pressed == 0 && keys_pressed[entry.first] == true) {
|
||||||
|
for (const auto& padstate : entry.second) {
|
||||||
|
KeyMap::ReleaseKey(padstate);
|
||||||
|
keys_pressed[entry.first] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Try axis if button isn't valid
|
||||||
|
SDL_GameControllerAxis axis = SDL_GameControllerGetAxisFromString(gamepadinput_to_sdlname_mapping[static_cast<GamepadInputs>(stoi(entry.first))].c_str());
|
||||||
|
if (axis != SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_INVALID) {
|
||||||
|
Sint16 value = SDL_GameControllerGetAxis(gamepad, axis);
|
||||||
|
for (const auto& padstate : entry.second) {
|
||||||
|
// TODO: calculate deadzone by radial field rather than axial field. (sqrt(x^2 + y^2) > deadzone)
|
||||||
|
// dont process if in deadzone. Replace later with settings for deadzone.
|
||||||
|
if (abs(value) < 0.2 * 32767.0)
|
||||||
|
KeyMap::ReleaseKey(padstate);
|
||||||
|
else
|
||||||
|
KeyMap::PressKey(padstate, (float)value / 32767.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLGamepad::CloseDevice() {
|
||||||
|
if (gamepad != nullptr) {
|
||||||
|
SDL_GameControllerClose(gamepad);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<IDevice>> SDLGamepad::GetAllDevices() {
|
||||||
|
std::vector<std::shared_ptr<IDevice>> devices;
|
||||||
|
if (!SDLGamepad::SDLInitialized && SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) {
|
||||||
|
LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_GAMECONTROLLER) failed");
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
LoadGameControllerDB();
|
||||||
|
SDL_GameControllerEventState(SDL_IGNORE);
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
SDL_GameController* gamecontroller;
|
||||||
|
if (SDL_IsGameController(i)) {
|
||||||
|
gamecontroller = SDL_GameControllerOpen(i);
|
||||||
|
if (gamecontroller != nullptr) {
|
||||||
|
devices.push_back(std::make_shared<SDLGamepad>(i, gamecontroller));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLGamepad::LoadGameControllerDB() {
|
||||||
|
std::vector<std::string> lines1,lines2,lines3,lines4;
|
||||||
|
Common::SplitString(SDLGameControllerDB::db_file1, '\n', lines1);
|
||||||
|
Common::SplitString(SDLGameControllerDB::db_file2, '\n', lines2);
|
||||||
|
Common::SplitString(SDLGameControllerDB::db_file3, '\n', lines3);
|
||||||
|
Common::SplitString(SDLGameControllerDB::db_file4, '\n', lines4);
|
||||||
|
lines1.insert(lines1.end(), lines2.begin(), lines2.end());
|
||||||
|
lines1.insert(lines1.end(), lines3.begin(), lines3.end());
|
||||||
|
lines1.insert(lines1.end(), lines4.begin(), lines4.end());
|
||||||
|
for (std::string s : lines1) {
|
||||||
|
SDL_GameControllerAddMapping(s.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::InputDeviceMapping SDLGamepad::GetInput() {
|
||||||
|
if (gamepad == nullptr)
|
||||||
|
return Settings::InputDeviceMapping("");
|
||||||
|
SDL_GameControllerUpdate();
|
||||||
|
for (int i = 0; i < SDL_GameControllerButton::SDL_CONTROLLER_BUTTON_MAX; i++)
|
||||||
|
{
|
||||||
|
Uint8 pressed = SDL_GameControllerGetButton(gamepad, SDL_GameControllerButton(i));
|
||||||
|
if (pressed == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto buttonName = SDL_GameControllerGetStringForButton(SDL_GameControllerButton(i));
|
||||||
|
for (const auto& mapping : gamepadinput_to_sdlname_mapping) {
|
||||||
|
if (mapping.second == buttonName) {
|
||||||
|
return Settings::InputDeviceMapping("SDL/" + std::to_string(number) + "/" + "Gamepad/" + std::to_string(static_cast<int>(mapping.first)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < SDL_GameControllerAxis::SDL_CONTROLLER_AXIS_MAX; i++) {
|
||||||
|
Sint16 value = SDL_GameControllerGetAxis(gamepad, SDL_GameControllerAxis(i));
|
||||||
|
// TODO: calculate deadzone by radial field rather than axial field. (sqrt(x^2 + y^2) > deadzone)
|
||||||
|
// dont process if in deadzone. Replace later with settings for deadzone.
|
||||||
|
if (abs(value) < 0.2 * 32767.0)
|
||||||
|
continue;
|
||||||
|
std::string modifier;
|
||||||
|
if (value > 0)
|
||||||
|
modifier = "+";
|
||||||
|
else
|
||||||
|
modifier = "-";
|
||||||
|
std::string axisName = SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis(i));
|
||||||
|
for (const auto& mapping : gamepadinput_to_sdlname_mapping) {
|
||||||
|
if (mapping.second == axisName) {
|
||||||
|
if ((mapping.first == GamepadInputs::LeftXMinus ||
|
||||||
|
mapping.first == GamepadInputs::LeftYMinus ||
|
||||||
|
mapping.first == GamepadInputs::RightXMinus ||
|
||||||
|
mapping.first == GamepadInputs::RightYMinus) && modifier == "+") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ((mapping.first == GamepadInputs::LeftXPlus ||
|
||||||
|
mapping.first == GamepadInputs::LeftYPlus ||
|
||||||
|
mapping.first == GamepadInputs::RightXPlus ||
|
||||||
|
mapping.first == GamepadInputs::RightYPlus) && modifier == "-") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return Settings::InputDeviceMapping("SDL/" + std::to_string(this->number) + "/" + "Gamepad/" + std::to_string(static_cast<int>(mapping.first)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Settings::InputDeviceMapping("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLGamepad::Clear() {
|
||||||
|
}
|
64
src/input_core/devices/sdl_gamepad.h
Normal file
64
src/input_core/devices/sdl_gamepad.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "input_core/devices/device.h"
|
||||||
|
|
||||||
|
struct _SDL_GameController;
|
||||||
|
class SDLGamepad : public IDevice {
|
||||||
|
public:
|
||||||
|
SDLGamepad();
|
||||||
|
SDLGamepad(int number_, _SDL_GameController* gamepad_);
|
||||||
|
~SDLGamepad();
|
||||||
|
|
||||||
|
bool InitDevice(int number, const std::map<std::string, std::vector<Service::HID::PadState>>& keyMap) override;
|
||||||
|
void ProcessInput() override;
|
||||||
|
bool CloseDevice() override;
|
||||||
|
Settings::InputDeviceMapping GetInput() override;
|
||||||
|
void Clear() override;
|
||||||
|
|
||||||
|
///Returns vector of all gamepads connected to computer. Used for keybinding setup
|
||||||
|
static std::vector<std::shared_ptr<IDevice>> GetAllDevices();
|
||||||
|
enum class GamepadInputs {
|
||||||
|
ButtonA,ButtonB,ButtonX,ButtonY,LeftShoulder,RightShoulder,
|
||||||
|
Start,Back,DPadUp,DpadDown,DpadLeft,DpadRight,L3,R3,LeftTrigger,RightTrigger,
|
||||||
|
LeftYPlus,LeftYMinus,LeftXPlus,LeftXMinus,RightYPlus,RightYMinus,
|
||||||
|
RightXPlus,RightXMinus, MAX
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
/// Maps the friendly name shown on GUI with the string name for getting the SDL button instance.
|
||||||
|
std::map<GamepadInputs, std::string> gamepadinput_to_sdlname_mapping = {
|
||||||
|
{ GamepadInputs::ButtonA, "a" },
|
||||||
|
{ GamepadInputs::ButtonB, "b" },
|
||||||
|
{ GamepadInputs::ButtonX, "x" },
|
||||||
|
{ GamepadInputs::ButtonY, "y" },
|
||||||
|
{ GamepadInputs::LeftShoulder, "leftshoulder" },
|
||||||
|
{ GamepadInputs::RightShoulder, "rightshoulder" },
|
||||||
|
{ GamepadInputs::Start, "start" },
|
||||||
|
{ GamepadInputs::Back, "back" },
|
||||||
|
{ GamepadInputs::DPadUp, "dpup" },
|
||||||
|
{ GamepadInputs::DpadDown, "dpdown" },
|
||||||
|
{ GamepadInputs::DpadLeft, "dpleft" },
|
||||||
|
{ GamepadInputs::DpadRight, "dpright" },
|
||||||
|
{ GamepadInputs::L3, "leftstick" },
|
||||||
|
{ GamepadInputs::R3, "rightstick" },
|
||||||
|
{ GamepadInputs::LeftTrigger, "lefttrigger" },
|
||||||
|
{ GamepadInputs::RightTrigger, "righttrigger" },
|
||||||
|
{ GamepadInputs::LeftYPlus, "lefty" },
|
||||||
|
{ GamepadInputs::LeftYMinus, "lefty" },
|
||||||
|
{ GamepadInputs::LeftXPlus, "leftx" },
|
||||||
|
{ GamepadInputs::LeftXMinus, "leftx" },
|
||||||
|
{ GamepadInputs::RightYPlus, "righty" },
|
||||||
|
{ GamepadInputs::RightYMinus, "righty" },
|
||||||
|
{ GamepadInputs::RightXPlus, "rightx" },
|
||||||
|
{ GamepadInputs::RightXMinus, "rightx" },
|
||||||
|
};
|
||||||
|
static bool SDLInitialized;
|
||||||
|
std::map<std::string, bool> keys_pressed; ///< Map of keys that were pressed on previous iteration
|
||||||
|
_SDL_GameController* gamepad = nullptr;
|
||||||
|
int number; ///< Index of gamepad connection
|
||||||
|
|
||||||
|
static void LoadGameControllerDB();
|
||||||
|
};
|
192
src/input_core/input_core.cpp
Normal file
192
src/input_core/input_core.cpp
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "core/core_timing.h"
|
||||||
|
|
||||||
|
#include "input_core/input_core.h"
|
||||||
|
#include "input_core/devices/keyboard.h"
|
||||||
|
#include "input_core/devices/sdl_gamepad.h"
|
||||||
|
|
||||||
|
namespace InputCore {
|
||||||
|
constexpr u64 frame_ticks = 268123480ull / 60;
|
||||||
|
static int tick_event;
|
||||||
|
static Service::HID::PadState pad_state;
|
||||||
|
static std::tuple<s16, s16> circle_pad = { 0,0 };
|
||||||
|
static std::shared_ptr<Keyboard> main_keyboard; ///< Keyboard is always active for Citra
|
||||||
|
static std::vector<std::shared_ptr<IDevice>> devices; ///< Devices that are handling input for the game
|
||||||
|
static std::mutex pad_state_mutex;
|
||||||
|
static std::mutex touch_mutex;
|
||||||
|
static u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320)
|
||||||
|
static u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240)
|
||||||
|
static bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false
|
||||||
|
|
||||||
|
static void InputTickCallback(u64, int cycles_late) {
|
||||||
|
for (auto& device : devices)
|
||||||
|
device->ProcessInput();
|
||||||
|
|
||||||
|
Service::HID::Update();
|
||||||
|
|
||||||
|
// Reschedule recurrent event
|
||||||
|
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, tick_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service::HID::PadState GetPadState() {
|
||||||
|
std::lock_guard<std::mutex> lock(pad_state_mutex);
|
||||||
|
return pad_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPadState(const Service::HID::PadState& state) {
|
||||||
|
std::lock_guard<std::mutex> lock(pad_state_mutex);
|
||||||
|
pad_state.hex = state.hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<s16, s16> GetCirclePad() {
|
||||||
|
return circle_pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCirclePad(std::tuple<s16, s16> pad) {
|
||||||
|
circle_pad = pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Keyboard> GetKeyboard() {
|
||||||
|
if (main_keyboard == nullptr)
|
||||||
|
main_keyboard = std::make_shared<Keyboard>();
|
||||||
|
return main_keyboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<u16, u16, bool> GetTouchState() {
|
||||||
|
std::lock_guard<std::mutex> lock(touch_mutex);
|
||||||
|
return std::make_tuple(touch_x, touch_y, touch_pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTouchState(std::tuple<u16, u16, bool> value) {
|
||||||
|
std::lock_guard<std::mutex> lock(touch_mutex);
|
||||||
|
std::tie(touch_x, touch_y, touch_pressed) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper method to check if device was already initialized
|
||||||
|
bool CheckIfMappingExists(const std::vector<Settings::InputDeviceMapping>& uniqueMapping, Settings::InputDeviceMapping mappingToCheck) {
|
||||||
|
return std::any_of(uniqueMapping.begin(), uniqueMapping.end(), [mappingToCheck](const auto& mapping) {
|
||||||
|
return mapping == mappingToCheck;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get Unique input mappings from settings
|
||||||
|
static std::vector<Settings::InputDeviceMapping> GatherUniqueMappings() {
|
||||||
|
std::vector<Settings::InputDeviceMapping> uniqueMappings;
|
||||||
|
|
||||||
|
for (const auto& mapping : Settings::values.input_mappings) {
|
||||||
|
if (!CheckIfMappingExists(uniqueMappings, mapping)) {
|
||||||
|
uniqueMappings.push_back(mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uniqueMappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds map of input keys to 3ds buttons for unique device
|
||||||
|
static std::map<std::string, std::vector<Service::HID::PadState>> BuildKeyMapping(Settings::InputDeviceMapping mapping) {
|
||||||
|
std::map<std::string, std::vector<Service::HID::PadState>> keyMapping;
|
||||||
|
for (size_t i = 0; i < Settings::values.input_mappings.size(); i++) {
|
||||||
|
Service::HID::PadState val = KeyMap::mapping_targets[i];
|
||||||
|
std::string key = Settings::values.input_mappings[i].key;
|
||||||
|
if (Settings::values.input_mappings[i] == mapping) {
|
||||||
|
keyMapping[key].push_back(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a device for each unique mapping
|
||||||
|
static void GenerateUniqueDevices(const std::vector<Settings::InputDeviceMapping>& uniqueMappings) {
|
||||||
|
devices.clear();
|
||||||
|
std::shared_ptr<IDevice> input;
|
||||||
|
for (const auto& mapping : uniqueMappings) {
|
||||||
|
switch (mapping.framework) {
|
||||||
|
case Settings::DeviceFramework::Qt:
|
||||||
|
{
|
||||||
|
main_keyboard = std::make_shared<Keyboard>();
|
||||||
|
input = main_keyboard;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Settings::DeviceFramework::SDL:
|
||||||
|
{
|
||||||
|
if (mapping.device == Settings::Device::Keyboard) {
|
||||||
|
main_keyboard = std::make_shared<Keyboard>();
|
||||||
|
input = main_keyboard;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (mapping.device == Settings::Device::Gamepad) {
|
||||||
|
input = std::make_shared<SDLGamepad>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
devices.push_back(input);
|
||||||
|
|
||||||
|
// Build map of inputs to listen for, for this device
|
||||||
|
auto keyMapping = BuildKeyMapping(mapping);
|
||||||
|
|
||||||
|
input->InitDevice(mapping.number, keyMapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read settings to initialize devices
|
||||||
|
void ParseSettings() {
|
||||||
|
auto uniqueMappings = GatherUniqueMappings();
|
||||||
|
GenerateUniqueDevices(uniqueMappings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReloadSettings() {
|
||||||
|
if (devices.empty())
|
||||||
|
return;
|
||||||
|
devices.clear();
|
||||||
|
ParseSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all available input devices. Used for key binding in GUI
|
||||||
|
std::vector<std::shared_ptr<IDevice>> GetAllDevices() {
|
||||||
|
auto all_devices = SDLGamepad::GetAllDevices();
|
||||||
|
all_devices.push_back(InputCore::GetKeyboard());
|
||||||
|
|
||||||
|
return all_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::InputDeviceMapping DetectInput(int max_time, std::function<void(void)> update_GUI) {
|
||||||
|
auto devices = GetAllDevices();
|
||||||
|
for (auto& device : devices) {
|
||||||
|
device->Clear();
|
||||||
|
}
|
||||||
|
Settings::InputDeviceMapping input_device;
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
while (input_device.key == "") {
|
||||||
|
update_GUI();
|
||||||
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start).count();
|
||||||
|
if (duration >= max_time) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (auto& device : devices) {
|
||||||
|
input_device = device->GetInput();
|
||||||
|
if (input_device.key != "")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return input_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
ParseSettings();
|
||||||
|
tick_event = CoreTiming::RegisterEvent("InputCore::tick_event", InputTickCallback);
|
||||||
|
CoreTiming::ScheduleEvent(frame_ticks, tick_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown() {
|
||||||
|
CoreTiming::UnscheduleEvent(tick_event, 0);
|
||||||
|
devices.clear();
|
||||||
|
}
|
||||||
|
}
|
78
src/input_core/input_core.h
Normal file
78
src/input_core/input_core.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "core/hle/service/hid/hid.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
#include "input_core/devices/device.h"
|
||||||
|
|
||||||
|
class Keyboard;
|
||||||
|
|
||||||
|
namespace InputCore {
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Threadsafe getter to the current PadState
|
||||||
|
* @return Service::HID::PadState instance
|
||||||
|
*/
|
||||||
|
Service::HID::PadState GetPadState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Threadsafe setter for the current PadState
|
||||||
|
* @param state New PadState to overwrite current PadState.
|
||||||
|
*/
|
||||||
|
void SetPadState(const Service::HID::PadState& state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for current CirclePad
|
||||||
|
* @return std::tuple<s16, s16> CirclePad state
|
||||||
|
*/
|
||||||
|
std::tuple<s16, s16> GetCirclePad();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for current CirclePad
|
||||||
|
* @param circle New CirclePad state
|
||||||
|
*/
|
||||||
|
void SetCirclePad(std::tuple<s16, s16> circle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for Citra's main keyboard input handler
|
||||||
|
* @return std::shared_ptr<Keyboard> Device Keyboard instance
|
||||||
|
*/
|
||||||
|
std::shared_ptr<Keyboard> GetKeyboard();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). Threadsafe.
|
||||||
|
* @note This should be called by the core emu thread to get a state set by the window thread.
|
||||||
|
* @return std::tuple of (x, y, pressed) where `x` and `y` are the touch coordinates and
|
||||||
|
* `pressed` is true if the touch screen is currently being pressed
|
||||||
|
*/
|
||||||
|
std::tuple<u16, u16, bool> GetTouchState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Threadsafe setter for the current touch screen state.
|
||||||
|
* @param value New Touch State
|
||||||
|
*/
|
||||||
|
void SetTouchState(std::tuple<u16, u16, bool> value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload input key mapping settings during game-play
|
||||||
|
*/
|
||||||
|
void ReloadSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loops through all devices and detects the first device that produces an input
|
||||||
|
* @param max_time: maximum amount of time to wait until input detected, in milliseconds.
|
||||||
|
* @param update_GUI: function to run in while loop to process any gui events.
|
||||||
|
* @return Settings::InputDeviceMapping of input device
|
||||||
|
*/
|
||||||
|
Settings::InputDeviceMapping DetectInput(int max_time, std::function<void(void)> update_GUI);
|
||||||
|
}
|
73
src/input_core/key_map.cpp
Normal file
73
src/input_core/key_map.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "common/emu_window.h"
|
||||||
|
|
||||||
|
#include "input_core/input_core.h"
|
||||||
|
#include "input_core/key_map.h"
|
||||||
|
|
||||||
|
namespace KeyMap {
|
||||||
|
constexpr int MAX_CIRCLEPAD_POS = 0x9C; /// Max value for a circle pad position
|
||||||
|
const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> mapping_targets = { {
|
||||||
|
Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y,
|
||||||
|
Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR,
|
||||||
|
Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_TOUCH,
|
||||||
|
Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT,
|
||||||
|
Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT,
|
||||||
|
|
||||||
|
Service::HID::PAD_CIRCLE_UP,
|
||||||
|
Service::HID::PAD_CIRCLE_DOWN,
|
||||||
|
Service::HID::PAD_CIRCLE_LEFT,
|
||||||
|
Service::HID::PAD_CIRCLE_RIGHT,
|
||||||
|
} };
|
||||||
|
///Array of inputs that are analog only, and require a strength when set
|
||||||
|
const std::array<Service::HID::PadState, 4> analog_inputs = {
|
||||||
|
Service::HID::PAD_CIRCLE_UP,
|
||||||
|
Service::HID::PAD_CIRCLE_DOWN,
|
||||||
|
Service::HID::PAD_CIRCLE_LEFT,
|
||||||
|
Service::HID::PAD_CIRCLE_RIGHT
|
||||||
|
};
|
||||||
|
|
||||||
|
void PressKey(const Service::HID::PadState target, const float strength) {
|
||||||
|
auto pad_state = InputCore::GetPadState();
|
||||||
|
// If is digital keytarget
|
||||||
|
if (std::find(std::begin(analog_inputs), std::end(analog_inputs), target) == std::end(analog_inputs)) {
|
||||||
|
pad_state.hex |= target.hex;
|
||||||
|
InputCore::SetPadState(pad_state);
|
||||||
|
}
|
||||||
|
else { // it is analog input
|
||||||
|
auto circle_pad = InputCore::GetCirclePad();
|
||||||
|
if (target == Service::HID::PAD_CIRCLE_UP || target == Service::HID::PAD_CIRCLE_DOWN) {
|
||||||
|
std::get<1>(circle_pad) = MAX_CIRCLEPAD_POS * strength * -1;
|
||||||
|
}
|
||||||
|
else if (target == Service::HID::PAD_CIRCLE_LEFT || target == Service::HID::PAD_CIRCLE_RIGHT) {
|
||||||
|
std::get<0>(circle_pad) = MAX_CIRCLEPAD_POS * strength;
|
||||||
|
}
|
||||||
|
InputCore::SetCirclePad(circle_pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseKey(const Service::HID::PadState target) {
|
||||||
|
auto pad_state = InputCore::GetPadState();
|
||||||
|
// If is digital keytarget
|
||||||
|
if (std::find(std::begin(analog_inputs), std::end(analog_inputs), target) == std::end(analog_inputs)) {
|
||||||
|
pad_state.hex &= ~target.hex;
|
||||||
|
InputCore::SetPadState(pad_state);
|
||||||
|
}
|
||||||
|
else { // it is analog input
|
||||||
|
auto circle_pad = InputCore::GetCirclePad();
|
||||||
|
if (target == Service::HID::PAD_CIRCLE_UP || target == Service::HID::PAD_CIRCLE_DOWN) {
|
||||||
|
std::get<1>(circle_pad) = 0;
|
||||||
|
}
|
||||||
|
else if (target == Service::HID::PAD_CIRCLE_LEFT || target == Service::HID::PAD_CIRCLE_RIGHT) {
|
||||||
|
std::get<0>(circle_pad) = 0;
|
||||||
|
}
|
||||||
|
InputCore::SetCirclePad(circle_pad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
src/input_core/key_map.h
Normal file
23
src/input_core/key_map.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "core/hle/service/hid/hid.h"
|
||||||
|
|
||||||
|
class EmuWindow;
|
||||||
|
|
||||||
|
namespace KeyMap {
|
||||||
|
extern const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> mapping_targets;
|
||||||
|
extern const std::array<Service::HID::PadState, 4> analog_inputs;
|
||||||
|
|
||||||
|
///Handles the pressing of a key and modifies InputCore state
|
||||||
|
void PressKey(Service::HID::PadState target, float strength);
|
||||||
|
|
||||||
|
///Handles the releasing of a key and modifies InputCore state
|
||||||
|
void ReleaseKey(Service::HID::PadState target);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user