From 04229cbd83aa71f72c322d191bc4210603b3a8c8 Mon Sep 17 00:00:00 2001 From: Xele02 Date: Mon, 4 Feb 2013 00:45:37 +0100 Subject: [PATCH] Add support to gamePad using SDL Add a dialog to config gamepad bindings --- Qt/PPSSPP.pro | 29 +- Qt/gamepaddialog.cpp | 378 ++++++++++++++++++++++ Qt/gamepaddialog.h | 51 +++ Qt/gamepaddialog.ui | 512 ++++++++++++++++++++++++++++++ Qt/mainwindow.cpp | 13 + Qt/mainwindow.h | 5 +- Qt/mainwindow.ui | 8 +- Qt/resources.qrc | 12 + Qt/resources/psp_adown.png | Bin 0 -> 304 bytes Qt/resources/psp_aleft.png | Bin 0 -> 322 bytes Qt/resources/psp_aright.png | Bin 0 -> 321 bytes Qt/resources/psp_aup.png | Bin 0 -> 319 bytes Qt/resources/psp_down_red.png | Bin 0 -> 278 bytes Qt/resources/psp_left_red.png | Bin 0 -> 295 bytes Qt/resources/psp_lt_red.png | Bin 0 -> 349 bytes Qt/resources/psp_right_red.png | Bin 0 -> 312 bytes Qt/resources/psp_rightbtn_red.png | Bin 0 -> 399 bytes Qt/resources/psp_rt_red.png | Bin 0 -> 350 bytes Qt/resources/psp_smallbtn_red.png | Bin 0 -> 290 bytes Qt/resources/psp_up_red.png | Bin 0 -> 292 bytes 20 files changed, 996 insertions(+), 12 deletions(-) create mode 100644 Qt/gamepaddialog.cpp create mode 100644 Qt/gamepaddialog.h create mode 100644 Qt/gamepaddialog.ui create mode 100644 Qt/resources/psp_adown.png create mode 100644 Qt/resources/psp_aleft.png create mode 100644 Qt/resources/psp_aright.png create mode 100644 Qt/resources/psp_aup.png create mode 100644 Qt/resources/psp_down_red.png create mode 100644 Qt/resources/psp_left_red.png create mode 100644 Qt/resources/psp_lt_red.png create mode 100644 Qt/resources/psp_right_red.png create mode 100644 Qt/resources/psp_rightbtn_red.png create mode 100644 Qt/resources/psp_rt_red.png create mode 100644 Qt/resources/psp_smallbtn_red.png create mode 100644 Qt/resources/psp_up_red.png diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index c60866afbf..9c6eaa8d1f 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -3,7 +3,7 @@ QT += core gui opengl include(Settings.pri) linux { - CONFIG += mobility + CONFIG += mobility link_pkgconfig MOBILITY += multimedia } else { @@ -17,14 +17,18 @@ blackberry: LIBS += -L. -lCore -lCommon -lNative -lscreen -lsocket -lstdc++ win32: LIBS += -L. -lCore -lCommon -lNative -lwinmm -lws2_32 -lkernel32 -luser32 -lgdi32 -lshell32 -lcomctl32 -ldsound -lxinput -linux: LIBS += -L. -lCore -lCommon -lNative -linux: PRE_TARGETDEPS += ./libCommon.a ./libCore.a ./libNative.a +linux { + LIBS += -L. -lCore -lCommon -lNative + PRE_TARGETDEPS += ./libCommon.a ./libCore.a ./libNative.a + packagesExist(sdl) { + DEFINES += QT_HAS_SDL + PKGCONFIG += sdl + } +} # Main -SOURCES += ../native/base/QtMain.cpp \ - qkeyedit.cpp -HEADERS += ../native/base/QtMain.h \ - qkeyedit.h +SOURCES += ../native/base/QtMain.cpp +HEADERS += ../native/base/QtMain.h # Native SOURCES += ../android/jni/EmuScreen.cpp \ @@ -44,7 +48,9 @@ linux:!mobile_platform { qtemugl.cpp \ ctrldisasmview.cpp \ ctrlregisterlist.cpp \ - controls.cpp + controls.cpp \ + qkeyedit.cpp \ + gamepaddialog.cpp HEADERS += mainwindow.h \ debugger_disasm.h \ EmuThread.h \ @@ -52,7 +58,9 @@ linux:!mobile_platform { qtemugl.h \ ctrldisasmview.h \ ctrlregisterlist.h \ - controls.h + controls.h \ + qkeyedit.h \ + gamepaddialog.h } else { SOURCES += ../android/jni/NativeApp.cpp } @@ -74,7 +82,8 @@ symbian { linux:!mobile_platform { FORMS += mainwindow.ui \ debugger_disasm.ui \ - controls.ui + controls.ui\ + gamepaddialog.ui RESOURCES += \ resources.qrc diff --git a/Qt/gamepaddialog.cpp b/Qt/gamepaddialog.cpp new file mode 100644 index 0000000000..da657ad470 --- /dev/null +++ b/Qt/gamepaddialog.cpp @@ -0,0 +1,378 @@ +#include "gamepaddialog.h" +#include "ui_gamepaddialog.h" +#include +#include "Core/Config.h" + +// Input +struct GamePadInfo +{ + int mapping_type; // 0 : pad button, 1 : pad axis, 2 : pad Hats + int mapping_in; + int mapping_sign; + QString ViewLabelName; + QString Name; +}; + +// Initial values are PS3 controller +GamePadInfo GamepadPadMapping[] = { + {0, 14, 0, "Prev_X", "Cross"}, //A + {0, 13, 0, "Prev_O", "Circle"}, //B + {0, 15, 0, "Prev_S", "Square"}, //X + {0, 12, 0, "Prev_T", "Triangle"}, //Y + {0, 10, 0, "Prev_LT", "Left Trigger"}, //LBUMPER + {0, 11, 0, "Prev_RT", "Right Trigger"}, //RBUMPER + {0, 3, 0, "Prev_Start", "Start"}, //START + {0, 0, 0, "Prev_Select", "Select"}, //SELECT + {0, 4, 0, "Prev_Up", "Up"}, //UP + {0, 6, 0, "Prev_Down", "Down"}, //DOWN + {0, 7, 0, "Prev_Left", "Left"}, //LEFT + {0, 5, 0, "Prev_Right", "Right"}, //RIGHT + {0, 0, 0, ""}, //MENU (event) + {0, 16, 0, "Prev_Home", "Home"}, //BACK + + // Special case for analog stick + {1, 0, -1, "Prev_ALeft", "Stick left"}, + {1, 0, 1, "Prev_ARight", "Stick right"}, + {1, 1, -1, "Prev_AUp", "Stick up"}, + {1, 1, 1, "Prev_ADown", "Stick bottom"} +}; + +// id for mapping in config start at offset 200 to not get over key mapping +const int configOffset = 200; + +GamePadDialog::GamePadDialog(InputState* state, QWidget *parent) : + QDialog(parent), + ui(new Ui::GamePadDialog), + m_inputState(state), +#if QT_HAS_SDL + m_joystick(0), +#endif + m_isInit(false) +{ + ui->setupUi(this); + SetViewMode(); + +#if QT_HAS_SDL + SDL_Init(SDL_INIT_JOYSTICK); +#endif + m_isInit = true; + + data_timer = new QTimer(); + data_timer->setInterval(50); + connect(data_timer,SIGNAL(timeout()),this,SLOT(pollJoystick())); + data_timer->start(); + + for(int i=0;i<18;i++) + { + QLabel* labelPreview = findChild(GamepadPadMapping[i].ViewLabelName); + if(labelPreview) + { + labelPreview->setVisible(false); + } + + if(g_Config.iMappingMap.find(i+configOffset) != g_Config.iMappingMap.end()) + { + GetMappingFromInt(g_Config.iMappingMap[i+configOffset], + GamepadPadMapping[i].mapping_in, + GamepadPadMapping[i].mapping_type, + GamepadPadMapping[i].mapping_sign); + } + } + + on_refreshListBtn_clicked(); +} + +GamePadDialog::~GamePadDialog() +{ + data_timer->stop(); + delete data_timer; + +#if QT_HAS_SDL + if(m_joystick) + SDL_JoystickClose(m_joystick); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); +#endif + + delete ui; +} + +void GamePadDialog::on_refreshListBtn_clicked() +{ +#if QT_HAS_SDL + if(m_joystick) + { + SDL_JoystickClose(m_joystick); + ui->JoyName->setText("No GamePad"); + m_joystick = 0; + } + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDL_Init(SDL_INIT_JOYSTICK); + + int numJoy = SDL_NumJoysticks(); + ui->GamePadList->clear(); + for(int i = 0; i < numJoy; i++) + { + QListWidgetItem* item = new QListWidgetItem(); + QString padName = SDL_JoystickName(i); + if(padName == "") padName = "Unknown GamePad"; + item->setText(padName); + item->setData(Qt::UserRole,i); + ui->GamePadList->addItem(item); + } + + if(numJoy > 0) + { + ui->GamePadList->setCurrentRow(0); + on_SelectPadBtn_clicked(); + } + +#endif +} + +void GamePadDialog::pollJoystick() +{ +#if QT_HAS_SDL + if(!m_joystick) + return; + SDL_JoystickUpdate(); + + // Update buttons state + for(int i=0;i<14;i++) + { + float val = 0; + if(GamepadPadMapping[i].mapping_type == 0) + val = SDL_JoystickGetButton(m_joystick,GamepadPadMapping[i].mapping_in); + else if(GamepadPadMapping[i].mapping_type == 1) + { + val = SDL_JoystickGetAxis(m_joystick,GamepadPadMapping[i].mapping_in); + if(val*GamepadPadMapping[i].mapping_sign > 16384) val = 1; + else val = 0; + } + else if(GamepadPadMapping[i].mapping_type == 2) + val = SDL_JoystickGetHat(m_joystick,GamepadPadMapping[i].mapping_in); + QLabel* labelPreview = findChild(GamepadPadMapping[i].ViewLabelName); + if(labelPreview) + { + labelPreview->setVisible(val != 0); + } + if(val) + { + m_inputState->pad_buttons |= (1<pad_buttons &= ~(1<pad_lstick_x = 0; + m_inputState->pad_lstick_y = 0; + for(int i = 14; i < 18; i++) + { + float val = 0; + if(GamepadPadMapping[i].mapping_type == 0) + val = SDL_JoystickGetButton(m_joystick,GamepadPadMapping[i].mapping_in); + else if(GamepadPadMapping[i].mapping_type == 1) + { + val = SDL_JoystickGetAxis(m_joystick,GamepadPadMapping[i].mapping_in); + if((val <= 0 && GamepadPadMapping[i].mapping_sign < 0) || (val >= 0 && GamepadPadMapping[i].mapping_sign > 0)) + val = abs(val) * 1.0f / 32767; + else + val = 0; + } + else if(GamepadPadMapping[i].mapping_type == 2) + val = SDL_JoystickGetHat(m_joystick,GamepadPadMapping[i].mapping_in); + QLabel* labelPreview = findChild(GamepadPadMapping[i].ViewLabelName); + if(labelPreview) + { + labelPreview->setVisible(val != 0); + } + switch(i) + { + case 14: + m_inputState->pad_lstick_x -= val; + break; + case 15: + m_inputState->pad_lstick_x += val; + break; + case 16: + m_inputState->pad_lstick_y -= val; + break; + default: + m_inputState->pad_lstick_y += val; + break; + } + } + + if(isVisible()) + { + for(int i = 0; i < ui->padValues->topLevelItemCount(); i++) + { + QTreeWidgetItem* item = ui->padValues->topLevelItem(i); + for(int j = 0; j < item->childCount(); j++) + { + QTreeWidgetItem* item2 = item->child(j); + if(item2->data(0,Qt::UserRole).toInt() == 0) + { + item2->setText(1,QVariant(SDL_JoystickGetButton(m_joystick,item2->data(0,Qt::UserRole+1).toInt())).toString()); + } + else if(item2->data(0,Qt::UserRole).toInt() == 1) + { + int val = SDL_JoystickGetAxis(m_joystick,item2->data(0,Qt::UserRole+1).toInt()); + if((val <= 0 && item2->data(0,Qt::UserRole+2).toInt() < 0) || (val >= 0 && item2->data(0,Qt::UserRole+2).toInt() > 0)) + item2->setText(1,QVariant(val).toString()); + } + else if(item2->data(0,Qt::UserRole).toInt() == 2) + { + item2->setText(1,QVariant(SDL_JoystickGetHat(m_joystick,item2->data(0,Qt::UserRole+1).toInt())).toString()); + } + } + } + } +#endif +} + + +void GamePadDialog::on_SelectPadBtn_clicked() +{ +#if QT_HAS_SDL + int selectedJoy = -1; + if(ui->GamePadList->currentItem() == 0) + { + return; + } + selectedJoy = ui->GamePadList->currentItem()->data(Qt::UserRole).toInt(); + m_joyId = selectedJoy; + m_joystick = SDL_JoystickOpen(selectedJoy); + + ui->padValues->clear(); + ui->padValues->setColumnCount(3); + ui->padValues->setColumnWidth(0,100); + ui->padValues->setColumnWidth(1,50); + ui->padValues->setColumnWidth(2,50); + + ui->comboPadInput->clear(); + ui->comboPSPButton->clear(); + + QTreeWidgetItem* buttonItem = new QTreeWidgetItem(); + buttonItem->setText(0,"Buttons"); + ui->padValues->addTopLevelItem(buttonItem); + + for(int i = 0; i < SDL_JoystickNumButtons(m_joystick); i++) + { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,QVariant(i).toString()); + item->setText(1,QVariant(0).toString()); + item->setData(0, Qt::UserRole,0); + item->setData(0, Qt::UserRole+1,i); + item->setData(0, Qt::UserRole+2,0); + buttonItem->addChild(item); + + int id = i << 8; + ui->comboPadInput->addItem("Button "+QVariant(i).toString(),GetIntFromMapping(i,0,0)); + } + QTreeWidgetItem* axesItem = new QTreeWidgetItem(); + axesItem->setText(0,"Axes"); + ui->padValues->addTopLevelItem(axesItem); + + for(int i = 0; i < SDL_JoystickNumAxes(m_joystick); i++) + { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,QVariant(i).toString()+" Neg"); + item->setText(1,QVariant(0).toString()); + item->setData(0, Qt::UserRole,1); + item->setData(0, Qt::UserRole+1,i); + item->setData(0, Qt::UserRole+2,-1); + axesItem->addChild(item); + + ui->comboPadInput->addItem("Axes "+QVariant(i).toString()+" Neg",GetIntFromMapping(i,1,-1)); + + item = new QTreeWidgetItem(); + item->setText(0,QVariant(i).toString()+" Pos"); + item->setText(1,QVariant(0).toString()); + item->setData(0, Qt::UserRole,1); + item->setData(0, Qt::UserRole+1,i); + item->setData(0, Qt::UserRole+2,1); + axesItem->addChild(item); + + ui->comboPadInput->addItem("Axes "+QVariant(i).toString()+" Pos",GetIntFromMapping(i,1,1)); + } + + QTreeWidgetItem* hatsItem = new QTreeWidgetItem(); + hatsItem->setText(0,"Hats"); + ui->padValues->addTopLevelItem(hatsItem); + + for(int i = 0; i < SDL_JoystickNumHats(m_joystick); i++) + { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0,QVariant(i).toString()); + item->setText(1,QVariant(0).toString()); + item->setData(0, Qt::UserRole,2); + item->setData(0, Qt::UserRole+1,i); + item->setData(0, Qt::UserRole+2,0); + hatsItem->addChild(item); + + ui->comboPadInput->addItem("Button "+QVariant(i).toString(),GetIntFromMapping(i,2,0)); + } + + for(int i = 0; i < 18; i++) + { + if(GamepadPadMapping[i].Name != "") + { + ui->comboPSPButton->addItem(GamepadPadMapping[i].Name,i); + } + } + + SetViewMode(); +#endif +} + +void GamePadDialog::SetViewMode() +{ +#if QT_HAS_SDL + ui->buttonBox->setEnabled(true); + ui->refreshListBtn->setEnabled(true); + ui->SelectPadBtn->setEnabled(true); + if(!m_joystick) + ui->JoyName->setText("No GamePad"); + else + ui->JoyName->setText(QString("Current gamepad : ")+SDL_JoystickName(m_joyId)+""); +#endif +} + +void GamePadDialog::on_AssignBtn_clicked() +{ + int idxPad = ui->comboPadInput->currentIndex(); + int idxPSP = ui->comboPSPButton->currentIndex(); + + int pspButton = ui->comboPSPButton->itemData(idxPSP).toInt(); + int padInfo = ui->comboPadInput->itemData(idxPad).toInt(); + + GetMappingFromInt(padInfo, GamepadPadMapping[pspButton].mapping_in, + GamepadPadMapping[pspButton].mapping_type, + GamepadPadMapping[pspButton].mapping_sign); +} + +int GamePadDialog::GetIntFromMapping(int inputId, int type, int sign) +{ + sign = (sign == -1 ? 1 : (sign == 1 ? 2 : 0)); + return inputId << 8 | sign << 2 | type; +} + +void GamePadDialog::GetMappingFromInt(int padInfo, int& inputId, int& type, int& sign) +{ + inputId = padInfo >> 8; + type = padInfo & 0x3; + sign = (padInfo >> 2) & 0x3; + sign = (sign == 1 ? -1 : (sign == 2 ? 1 : 0)); +} + +void GamePadDialog::on_buttonBox_accepted() +{ + for(int i = 0; i < 18; i++) + { + g_Config.iMappingMap[i+configOffset] = GetIntFromMapping(GamepadPadMapping[i].mapping_in, + GamepadPadMapping[i].mapping_type, + GamepadPadMapping[i].mapping_sign); + } +} diff --git a/Qt/gamepaddialog.h b/Qt/gamepaddialog.h new file mode 100644 index 0000000000..dabae24b4a --- /dev/null +++ b/Qt/gamepaddialog.h @@ -0,0 +1,51 @@ +#ifndef GAMEPADDIALOG_H +#define GAMEPADDIALOG_H + +#include +#if QT_HAS_SDL +#include "SDL/SDL.h" +#endif +#include "native/input/input_state.h" + +namespace Ui { +class GamePadDialog; +} +class QTimer; + +class GamePadDialog : public QDialog +{ + Q_OBJECT + +public: + explicit GamePadDialog(InputState* inputState, QWidget *parent = 0); + ~GamePadDialog(); + + void SetViewMode(); + void SetCalibMode(); + void CalibNextButton(); +private slots: + void on_refreshListBtn_clicked(); + + void on_SelectPadBtn_clicked(); + + void pollJoystick(); + + void on_AssignBtn_clicked(); + + void on_buttonBox_accepted(); + +private: + int GetIntFromMapping(int inputId, int type, int sign); + void GetMappingFromInt(int value, int &inputId, int &type, int &sign); + + Ui::GamePadDialog *ui; +#if QT_HAS_SDL + SDL_Joystick* m_joystick; + int m_joyId; +#endif + InputState* m_inputState; + bool m_isInit; + QTimer *data_timer; +}; + +#endif // GAMEPADDIALOG_H diff --git a/Qt/gamepaddialog.ui b/Qt/gamepaddialog.ui new file mode 100644 index 0000000000..737cca89a5 --- /dev/null +++ b/Qt/gamepaddialog.ui @@ -0,0 +1,512 @@ + + + GamePadDialog + + + + 0 + 0 + 850 + 501 + + + + Gamepad Configuration + + + + + + + + GamePad List + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Refresh + + + + + + + Select + + + + + + + + + Gamepad Values : + + + + + + + false + + + + 1 + + + + + + + + + + + + + TextLabel + + + Qt::AlignCenter + + + + + + + + + Assign Gamepad input + + + + + + + + + + to PSP button/axis + + + + + + + + + + Assign + + + + + + + + + Press buttons on your gamePad to verify mapping : + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 500 + 218 + + + + + + 0 + 0 + 500 + 218 + + + + + + + :/images/resources/psp.png + + + + + + 110 + 78 + 21 + 21 + + + + + + + :/images/resources/psp_up_red.png + + + + + + 92 + 93 + 21 + 20 + + + + + + + :/images/resources/psp_left_red.png + + + + + + 122 + 94 + 20 + 20 + + + + + + + :/images/resources/psp_right_red.png + + + + + + 109 + 105 + 21 + 30 + + + + + + + :/images/resources/psp_down_red.png + + + + + + 141 + 165 + 30 + 21 + + + + + + + :/images/resources/psp_smallbtn_red.png + + + + + + 312 + 166 + 21 + 16 + + + + + + + :/images/resources/psp_smallbtn_red.png + + + + + + 339 + 166 + 21 + 16 + + + + + + + :/images/resources/psp_smallbtn_red.png + + + + + + 351 + 92 + 21 + 21 + + + + + + + :/images/resources/psp_rightbtn_red.png + + + + + + 374 + 114 + 21 + 21 + + + + + + + :/images/resources/psp_rightbtn_red.png + + + + + + 396 + 93 + 21 + 21 + + + + + + + :/images/resources/psp_rightbtn_red.png + + + + + + 374 + 71 + 21 + 21 + + + + + + + :/images/resources/psp_rightbtn_red.png + + + + + + 351 + 32 + 61 + 21 + + + + + + + :/images/resources/psp_rt_red.png + + + + + + 93 + 32 + 60 + 21 + + + + + + + :/images/resources/psp_lt_red.png + + + + + + 107 + 144 + 21 + 21 + + + + + + + :/images/resources/psp_adown.png + + + + + + 107 + 139 + 16 + 21 + + + + + + + :/images/resources/psp_aleft.png + + + + + + 108 + 134 + 21 + 21 + + + + + + + :/images/resources/psp_aup.png + + + + + + 118 + 138 + 21 + 21 + + + + + + + :/images/resources/psp_aright.png + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + GamePadDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + GamePadDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 497a8178c8..36e828bce8 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -32,6 +32,10 @@ MainWindow::MainWindow(QWidget *parent) : qApp->installEventFilter(this); controls = new Controls(this); +#if QT_HAS_SDL + gamePadDlg = new GamePadDialog(&input_state, this); +#endif + host = new QtHost(this); w = ui->widget; w->init(&input_state); @@ -765,3 +769,12 @@ void MainWindow::on_actionLogDefError_triggered() } UpdateMenus(); } + +void MainWindow::on_action_OptionsGamePadControls_triggered() +{ +#if QT_HAS_SDL + gamePadDlg->show(); +#else + QMessageBox::information(this,"Gamepad","You need to compile with SDL to have Gamepad support.", QMessageBox::Ok); +#endif +} diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 4fffe2d1c9..d8a41a0e99 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -7,6 +7,7 @@ #include "input/input_state.h" #include "debugger_disasm.h" #include "controls.h" +#include "gamepaddialog.h" class QtEmuGL; namespace Ui { @@ -132,6 +133,8 @@ private slots: void on_actionLogDefError_triggered(); + void on_action_OptionsGamePadControls_triggered(); + private: Ui::MainWindow *ui; @@ -139,10 +142,10 @@ private: CoreState nextState; InputState input_state; - bool g_bFullScreen; Debugger_Disasm *dialogDisasm; Controls* controls; + GamePadDialog* gamePadDlg; }; #endif // MAINWINDOW_H diff --git a/Qt/mainwindow.ui b/Qt/mainwindow.ui index eda55d0f63..1a563fe407 100644 --- a/Qt/mainwindow.ui +++ b/Qt/mainwindow.ui @@ -136,6 +136,7 @@ + @@ -320,7 +321,7 @@ - &Controls + Keyboard &Controls @@ -556,6 +557,11 @@ Error + + + GamePad Controls + + diff --git a/Qt/resources.qrc b/Qt/resources.qrc index 80d141a427..4bcd4f9d3d 100644 --- a/Qt/resources.qrc +++ b/Qt/resources.qrc @@ -2,5 +2,17 @@ resources/psp.png resources/psp_map.png + resources/psp_rightbtn_red.png + resources/psp_smallbtn_red.png + resources/psp_down_red.png + resources/psp_up_red.png + resources/psp_right_red.png + resources/psp_left_red.png + resources/psp_rt_red.png + resources/psp_lt_red.png + resources/psp_aright.png + resources/psp_adown.png + resources/psp_aleft.png + resources/psp_aup.png diff --git a/Qt/resources/psp_adown.png b/Qt/resources/psp_adown.png new file mode 100644 index 0000000000000000000000000000000000000000..141664b2a46e0a4a26e95fc6d9bc66ae0d3cb78d GIT binary patch literal 304 zcmeAS@N?(olHy`uVBq!ia0vp^VnEEz!3HF&|J2q2DYhhUcNd2LAh=-f^2tCE&H|6f zVxTHv5N2eUHAey{$X?><>&kwYiCIj?f_Y}BE>K9a#5JPCIX^cyHLrxhxhOTUBsE2$ zJhLQ2!QIn0AiR-J9H?l9r;B5V#`(494)QiR2(&(|_vtvsw5GYGTU~pD0RIZ#0_LY) zhGL1TaXsPk%XvKtBo|HI^G413^IL@jGn*HD_*Q*!^8?)p3;v1MyjrMuJ^rDg$rGVg zFVdQ&MBb@0BZSe&;S4c literal 0 HcmV?d00001 diff --git a/Qt/resources/psp_aleft.png b/Qt/resources/psp_aleft.png new file mode 100644 index 0000000000000000000000000000000000000000..60545be238b83c53c1459db4249f140f6c6f710c GIT binary patch literal 322 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eU!3HFY*6?ouQfx`y?k)`fL2$v|<&%LToCO|{ z#S9GG!XV7ZFl&wkP>{XE)7O>#E)%nuj@-p57cKyWBuiW)N}Tg^b5rw57@Uhz6H8K4 z6v{J8G8EiBeFMT9`NV;WR(ZNOhFF|lI@y}b$xy)6UueT7fq78{VLT6PP?Yv2`m3Z-DP7x=(^yJ z@5z>AMt?7kXO$woU)D|&cq8>;MN7hMK_96)L6sd`Z7*(w?%dpw@OZ~xoroJA+4?z7 zLN>MqJ9jj*hkc#yXS+je(gQ=*)#sWOp1uEjOnO0F$D#XzZ%@XX#=d$ud9v?opsN`? MUHx3vIVCg!00H`SCIA2c literal 0 HcmV?d00001 diff --git a/Qt/resources/psp_aright.png b/Qt/resources/psp_aright.png new file mode 100644 index 0000000000000000000000000000000000000000..f951c2bb93b64f64658a52519567766e91ef55ef GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eU!3HFY*6?ouQfx`y?k)`fL2$v|<&%LToCO|{ z#S9GG!XV7ZFl&wkP>{XE)7O>#E)%nuuJAUyxjH~0$r9Iy66gHf+|;}h2Ir#G#FEq$ zh4Rdj3=MI0~;7b zvKQwG4+tM&8qG@}=iN=cp?zfl4N;PV4SYeXeae!-w#iRX}HVx6AjsAX`&vkCwc6x=<11Hv2m#DR*Id%8G=Se(8(ko4h$s(jGXUnDAXqk>y`)OH5#FZQeAow0}GwR+@2dYufD~yp!{r>4T*Y zrZ6tIc|DfK1q~cBjpYvyD&L*zTQ={RLWSk-{aj{c``sT*<#|wa z$aYfT4~Iooo?>xY9;)^aO`GD1J|0-Bu;PuS*@4AR_ROJgl(8&y*u6{1- HoD!M% literal 0 HcmV?d00001 diff --git a/Qt/resources/psp_down_red.png b/Qt/resources/psp_down_red.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec28673b274796326a3548ee2ee416ed45dde5d GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^fjA5L~c#`DCC7XMsm# zF#`j)FbFd;%$g$s6l5>)^mS#w%fuvLE&EYlP8%pBS>hT|;+&tGo0?a`;9QiNSdyBe zP@Y+mq2TW68xY>eCk|9p=jq}YVsZNInYCPp7#LbF9u_zYYe@5(U3%#PI zHv4ImnL*D+Uctk5JMNTaXyzO;p3)|A?V(`M+Be*54*g|*!QPs>!<6Cff(;zg#TLkN zeJ*&%VB(x8{XE)7O>#E)$c00;_ka?{lD#WQl7;iF1B#Zfaf$gL6@8Vo7R> zLV0FMhJw4NZ$Nk>pEyuazo(01h{fr(mpAerG7xBe`2U5FOQ*=C4Q$#QCfc${>NW>l zm|$Y!-WaRkS~g{mdgQ)Czf^9QvppzyKAkNixYqACr^T{gi654TvB&RBYmehh`?84T z^$WHQJ$Wp5AHKbyc`&s^{YQHg+s*mn1-1)LCm5_;Co?r)V(NaGskIVQCJRm39CM^d j{$AL&W5*M8WPdPed)B8Eo-r-~I*q~8)z4*}Q$iB}e1m9% literal 0 HcmV?d00001 diff --git a/Qt/resources/psp_lt_red.png b/Qt/resources/psp_lt_red.png new file mode 100644 index 0000000000000000000000000000000000000000..a44504f1f2322bc47bcd68c198d0e59ea67c53c9 GIT binary patch literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^7C{XE)7O>#E)$c0obrvmm(zhlk|nMYCC>S|xv6<249-QVi6yBi z3gww484B*6z5(HleBwYwM?GB}Ln02py>7_GWGK-3(0=s`K@pMjiRp=H44!mVjEVREvSo{MnpFP}!5SU`njxgN@xNAEjW7Q literal 0 HcmV?d00001 diff --git a/Qt/resources/psp_right_red.png b/Qt/resources/psp_right_red.png new file mode 100644 index 0000000000000000000000000000000000000000..81b809e0555eed023c73582edf60671d6ea4abc4 GIT binary patch literal 312 zcmeAS@N?(olHy`uVBq!ia0vp^qChOf!3HF^2u;-kQfx`y?k)`fL2$v|<&%LToCO|{ z#S9GG!XV7ZFl&wkP>{XE)7O>#E)$c0f?|2uN;9C4WQl7;iF1B#Zfaf$gL6@8Vo7R> zLV0FMhJw4NZ$Nk>pEyv_0#6sm5R21WFFA4@G7xEbXunXqQ1fUNul|I&%Rk8Ju47$) zjeEz+bb*6=&-)5Sdwlkp$9%K3Us1AMiOFFdgVmx)P0(Rwm}A}>%#vcxr_#5q4VH#M(>!MP|ku_QG` zp**uBL&4qCHz2%`PaLS|yQhm|h{fr(SM9x+9Yv0Re7`1wL(wBZOfhzrfY64(*H`2m zKd_ipGZr@|q(7HbS>id}dx=00%Rv#w*!&Nh3)tIIZ`$Ad{ve!(N4`z+o^(b)lkgfZ z0dAp#+Z~$19sft@2>GzS=FvXoWRTTlb+DRq#(BRBYnk_(I@E4!x@=@($@DdnD@M>N zxAB)v<@uk-nSx&32`&99vm|ia4pS$_q#yR02W-nqMGwWdeNbrm-uA(ug}?1XDaU__ zLyrainYP4#;x#hQ5a877-t~T`>MpI>;<+DYuj0J^B+8DZzo~my@lNF(!e?0KTjnTN m2z=4mx5D_KOF>-vfB6n|139^hxFdgVmx)P0&LZfBR5wsavcxr_#5q4VH#M(>!MP|ku_QG` zp**uBL&4qCHz2%`PaLS|n5Tz0md4_4U4m-pv;lFL)$vWzKQ8b;d5Sg|`L%zc`~%BE?-2 ov!k_!u~ed)d8w-LQ})j+k6Ev8Ie9C23D8Fjp00i_>zopr0KasBOaK4? literal 0 HcmV?d00001 diff --git a/Qt/resources/psp_smallbtn_red.png b/Qt/resources/psp_smallbtn_red.png new file mode 100644 index 0000000000000000000000000000000000000000..4239c46fc510d3fdf771d08e879a6dc89af540d8 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^;y}#J!3HF!*oip+DYhhUcNd2LAh=-f^2tCE&H|6f zVxTHv5N2eUHAey{$X?><>&kwYiAg|F?gsZ(FQAZQiEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJh`$gVC=7sn8d^H(qK=41*KXnmNkdmuyDQ230_fo*RNOP#q>QoMQt zS1YTd0JEq}^X@~UW}l@h5)$}~|D0)-Uv#Z_^q}0Q=))ETizeBgs(*~XoA%Ff{dYbguHe(r3wLKTJt!-fzCe#* c{olQDmp8wUtp61G73eAkPgg&ebxsLQ0A~zo^Z)<= literal 0 HcmV?d00001 diff --git a/Qt/resources/psp_up_red.png b/Qt/resources/psp_up_red.png new file mode 100644 index 0000000000000000000000000000000000000000..dd6f718a7965cafc7d830c47721387782d07746f GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^f|gW!U_%O?XxI14-? ziy0WWg+Z8+Vb&Z8pdfpRr>`sfT_z?01;ea^J3&TCmbgZgIOpf)rskC}I2WZRmZYXA zlxLP?D7bt2281{Ai31h&c)B=-Se(9l=`<&kp#a;1e9_&TSa)yW*u6pgqf*88X?r>B z1X+$ZzvhlHOZ%?yPhf`3r-`1+8WLI-Ml&r<_q(z8&323MuS*jO?M-==l5-a{_ZPgA+SjgwE_1+2SE(T9mKbLh*2~7YE2V%Sc literal 0 HcmV?d00001