]> Shamusworld >> Repos - virtualjaguar/commitdiff
More gamepad work.
authorShamus Hammons <jlhamm@acm.org>
Sun, 13 Jan 2013 04:15:25 +0000 (22:15 -0600)
committerShamus Hammons <jlhamm@acm.org>
Sun, 13 Jan 2013 04:15:25 +0000 (22:15 -0600)
Gamepad configuration and usability is now working, though there are
some limitations: you must be careful to configure the pads you want to
be pad 1 & 2. You can mix keyboard keys, but not have multiply defined
keys (yet). There is no joypad specific configuration, though that may
come in the future if there is demand for it.

src/gui/app.cpp
src/gui/controllertab.cpp
src/gui/controllerwidget.cpp
src/gui/controllerwidget.h
src/gui/debug/cpubrowser.cpp
src/gui/gamepad.cpp
src/gui/gamepad.h
src/gui/keygrabber.cpp
src/gui/keygrabber.h
src/gui/mainwin.cpp
src/gui/mainwin.h

index cbe605125ed4aa9d359f7bc5caaa67dd9b5a2fb3..3961d31aaef3c92b7aba18b2790623fa79e7c11f 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <SDL.h>
 #include <QApplication>
+#include "gamepad.h"
 #include "log.h"
 #include "mainwin.h"
 #include "settings.h"
@@ -97,7 +98,9 @@ int main(int argc, char * argv[])
        {
                WriteLog("VJ: SDL (joystick, audio) successfully initialized.\n");
                App app(argc, argv);                                    // Declare an instance of the application
+               Gamepad::AllocateJoysticks();
                retVal = app.exec();                                    // And run it!
+               Gamepad::DeallocateJoysticks();
 
                // Free SDL components last...!
                SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_AUDIO);
index 957e568b1d7a32144ae219ce19fbc5283ed6c3d0..ce09270ff86b53fd2e186b42260d9ec95b9d389d 100644 (file)
@@ -33,10 +33,12 @@ ControllerTab::ControllerTab(QWidget * parent/*= 0*/): QWidget(parent)
        connect(redefineAll, SIGNAL(clicked()), this, SLOT(DefineAllKeys()));
 }
 
+
 ControllerTab::~ControllerTab()
 {
 }
 
+
 void ControllerTab::DefineAllKeys(void)
 {
 //     char jagButtonName[21][10] = { "Up", "Down", "Left", "Right",
@@ -60,3 +62,4 @@ void ControllerTab::DefineAllKeys(void)
                controllerWidget->update();
        }
 }
+
index 25fb8b1b8206bef1baa4f6b2059379b567644803..79e91b602859c25b345b4fe1405db8535e624f8d 100644 (file)
 #include "controllerwidget.h"
 
 #include "joystick.h"
+#include "gamepad.h"
 #include "keygrabber.h"
 
+
 // These tables are used to convert Qt keycodes into human readable form. Note that
 // a lot of these are just filler.
 char ControllerWidget::keyName1[96][16] = {
@@ -40,6 +42,8 @@ char ControllerWidget::keyName2[64][16] = {
        "F14", "F15", "F16"
 };
 
+char ControllerWidget::hatName[4][16] = { "Up", "Rt", "Dn", "Lf" };
+
 // This is hard-coded crap. It's crap-tastic!
 // These are the positions to draw the button names at, ordered by the BUTTON_* sequence
 // found in joystick.h.
@@ -50,6 +54,7 @@ int ControllerWidget::buttonPos[21][2] = { { 74, 32 }, { 71, 67 }, { 53, 49 }, {
        { 234, 31 }, { 216, 51 }, { 199, 71 }, { 164-11, 101-30 }, { 141-11, 108+13-30 }
 };
 
+
 ControllerWidget::ControllerWidget(QWidget * parent/*= 0*/): QWidget(parent),
        controllerPic(":/res/controller.png"), widgetSize(controllerPic.size()),
        keyToHighlight(-1), mouseDown(false)
@@ -60,20 +65,24 @@ ControllerWidget::ControllerWidget(QWidget * parent/*= 0*/): QWidget(parent),
        setMouseTracking(true);
 }
 
+
 ControllerWidget::~ControllerWidget()
 {
 }
 
+
 QSize ControllerWidget::sizeHint(void) const
 {
        return widgetSize;
 }
 
+
 QSizePolicy ControllerWidget::sizePolicy(void) const
 {
        return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 }
 
+
 void ControllerWidget::paintEvent(QPaintEvent * /*event*/)
 {
        QPainter painter(this);
@@ -127,17 +136,31 @@ void ControllerWidget::paintEvent(QPaintEvent * /*event*/)
                        DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1],
                                QString(keyName2[keys[i] & 0x3F]));
                }
+#if 1
+               else if (keys[i] & JOY_BUTTON)
+               {
+                       DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1],
+                               QString("JB%1").arg(keys[i] & JOY_BUTTON_MASK));
+               }
+               else if (keys[i] & JOY_HAT)
+               {
+                       DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1],
+                               QString("j%1").arg(hatName[keys[i] & JOY_BUTTON_MASK]));
+               }
+#endif
                else
                        DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], QString("???"));
        }
 }
 
+
 void ControllerWidget::mousePressEvent(QMouseEvent * /*event*/)
 {
        mouseDown = true;
        update();
 }
 
+
 void ControllerWidget::mouseReleaseEvent(QMouseEvent * /*event*/)
 {
        mouseDown = false;
@@ -156,6 +179,7 @@ void ControllerWidget::mouseReleaseEvent(QMouseEvent * /*event*/)
        update();
 }
 
+
 void ControllerWidget::mouseMoveEvent(QMouseEvent * event)
 {
        if (mouseDown)
@@ -184,12 +208,14 @@ void ControllerWidget::mouseMoveEvent(QMouseEvent * event)
                update();
 }
 
+
 void ControllerWidget::leaveEvent(QEvent * /*event*/)
 {
        keyToHighlight = -1;
        update();
 }
 
+
 void ControllerWidget::DrawBorderedText(QPainter & painter, int x, int y, QString text)
 {
        // Text is drawn centered at (x, y) as well, using a bounding rect for the purpose.
@@ -210,3 +236,4 @@ void ControllerWidget::DrawBorderedText(QPainter & painter, int x, int y, QStrin
        rect.moveCenter(QPoint(x, y));
        painter.drawText(rect, Qt::AlignCenter, text);
 }
+
index cf42469c7a9d54b5e710da6d812d571869dc9549..eada2d642a53908c97c729bb65624f014c2d91c2 100644 (file)
@@ -36,6 +36,7 @@ class ControllerWidget: public QWidget
                // Class data
                static char keyName1[96][16];
                static char keyName2[64][16];
+               static char hatName[4][16];
                static int buttonPos[21][2];
 };
 
index 8df187886b9f97e8d4b2f9c7d4d7d0717256453e..3871dbca671dff6e41f20e3e890d43378f5e82cf 100644 (file)
@@ -32,7 +32,7 @@ CPUBrowserWindow::CPUBrowserWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt:
        // Need to set the size as well...
 //     resize(560, 480);
 
-       QFont fixedFont("Lucida Console", 10, QFont::Normal);
+       QFont fixedFont("Lucida Console", 8, QFont::Normal);
        text->setFont(fixedFont);
 ////   layout->setSizeConstraint(QLayout::SetFixedSize);
        setLayout(layout);
index ba8a551037b044ec7b0239ab6dd0248ed63fd976..6ca2329a02cf20ab737bdca253cdc37bb7552f43 100644 (file)
 //
 
 #include "gamepad.h"
+#include "log.h"
+
+
+// Class member initialization
+/*static*/ int Gamepad::numJoysticks = 0;
+/*static*/ SDL_Joystick * Gamepad::pad[8];
+/*static*/ int Gamepad::numButtons[8];
+/*static*/ int Gamepad::numHats[8];
+/*static*/ bool Gamepad::button[8][256];
+/*static*/ uint8_t Gamepad::hat[8][32];
+
+
+Gamepad::Gamepad(void)//: numJoysticks(0)
+{
+       AllocateJoysticks();
+}
+
+
+Gamepad::~Gamepad(void)
+{
+       DeallocateJoysticks();
+}
+
+
+void Gamepad::AllocateJoysticks(void)
+{
+//     DeallocateJoysticks();
+       numJoysticks = SDL_NumJoysticks();
+
+       // Sanity check
+       if (numJoysticks > 8)
+               numJoysticks = 8;
+
+       for(int i=0; i<numJoysticks; i++)
+       {
+               pad[i] = SDL_JoystickOpen(i);
+               numButtons[i] = numHats[i] = 0;
+
+               if (pad[i])
+               {
+                       numButtons[i] = SDL_JoystickNumButtons(pad[i]);
+                       numHats[i] = SDL_JoystickNumHats(pad[i]);
+               }
+       }
+
+       WriteLog("Gamepad: Found %u joystick%s.\n", numJoysticks, (numJoysticks == 1 ? "" : "s"));
+}
+
+
+void Gamepad::DeallocateJoysticks(void)
+{
+       for(int i=0; i<numJoysticks; i++)
+               SDL_JoystickClose(pad[i]);
+}
 
 
 bool Gamepad::GetState(int joystickID, int buttonID)
 {
+       uint8_t hatMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
        if (buttonID & JOY_BUTTON)
        {
                // Handle SDL button
+               int buttonNum = (buttonID & JOY_BUTTON_MASK);
+//             SDL_JoystickGetButton(pad[joystickID]);
+               return button[joystickID][buttonNum];
        }
        else if (buttonID & JOY_HAT)
        {
                // Handle SDL hats
                int hatNumber = (buttonID & JOY_HATNUM_MASK) >> 3;
-               int hatDirection = hatMask[buttonID & JOY_HATBUT_MASK];
+               uint8_t hatDirection = hatMask[buttonID & JOY_HATBUT_MASK];
+//             uint8 direction = SDL_JoystickGetHat(pad[joystickID], hatNumber);
+//             return (
+               return (hat[joystickID][hatNumber] & hatDirection ? true : false);
        }
 
        // Default == failure
@@ -32,14 +94,77 @@ bool Gamepad::GetState(int joystickID, int buttonID)
 }
 
 
+int Gamepad::CheckButtonPressed(void)
+{
+       // This translates the hat direction to a mask index.
+       int hatNum[16] = { -1, 0, 1, -1, 2, -1, -1, -1,
+               3, -1, -1, -1, -1, -1, -1, -1 };
+
+       // Return single button ID being pressed (if any)
+       for(int i=0; i<numJoysticks; i++)
+       {
+               for(int j=0; j<numButtons[i]; j++)
+               {
+                       if (button[i][j])
+                               return (JOY_BUTTON | j);
+               }
+
+               for(int j=0; j<numHats[i]; j++)
+               {
+                       if (hat[i][j])
+                               return (JOY_HAT | hatNum[hat[i][j]]);
+               }
+       }
+
+       return -1;
+}
+
+
 int Gamepad::GetButtonID(void)
 {
        // Return single button ID being pressed (if any)
+       return -1;
 }
 
 
 int Gamepad::GetJoystickID(void)
 {
        // Return joystick ID of button being pressed (if any)
+       return -1;
+}
+
+
+void Gamepad::Update(void)
+{
+//     SDL_PollEvent(&event);
+       SDL_JoystickUpdate();
+
+       for(int i=0; i<numJoysticks; i++)
+       {
+               for(int j=0; j<numButtons[i]; j++)
+                       button[i][j] = SDL_JoystickGetButton(pad[i], j);
+
+               for(int j=0; j<numHats[i]; j++)
+                       hat[i][j] = SDL_JoystickGetHat(pad[i], j);
+       }
+}
+
+
+#if 0
+// Need to test this. It may be that the only time joysticks are detected is
+// when the program is first run. That would suck.
+void Gamepad::CheckConsistency(void)
+{
+       int currentNumJoysticks = SDL_NumJoysticks();
+
+       // Check to see if the # of joysticks reported by SDL changed
+       if (currentNumJoysticks == numJoysticks)
+               return;
+
+       // Either one or more joysticks were plugged in, or removed. Fix up our
+       // internal states to reflect this.
+
+       
 }
+#endif
 
index 350a91393c1b26b7035ad9d931cf2f120509bd54..6b4993a8d163be76ad7ae92f2c4d2e4dbdae3f7f 100644 (file)
@@ -8,16 +8,17 @@
 #ifndef __GAMEPAD_H__
 #define __GAMEPAD_H__
 
-#define JOY_BUTTON             0x0100
-#define JOY_HAT                        0x0200
+#define JOY_KEY                        0x000000
+#define JOY_BUTTON             0x010000
+#define JOY_HAT                        0x020000
 
-#define        JOY_TYPE_MASK   0xFF00
-#define JOY_HATNUM_MASK        0x00F8
-#define JOY_HATBUT_MASK        0x0007
+#define        JOY_TYPE_MASK   0xFF0000
+#define JOY_BUTTON_MASK 0x00FFFF
+#define JOY_HATNUM_MASK        0x0000F8
+#define JOY_HATBUT_MASK        0x000007
 
 #include <stdint.h>
-
-uint8_t hatMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+#include "SDL.h"
 
 // buttonID is the combination of the type (BUTTON, HAT) and the button #
 // (0-255 for buttons, 0-31 for hats). Hats also have 0-7 for a button #
@@ -31,9 +32,22 @@ class Gamepad
                Gamepad();
                ~Gamepad();
 
-               bool GetState(int joystickID, int buttonID);
-               int GetButtonID(void);
-               int GetJoystickID(void);
+               // Class methods...
+               static void AllocateJoysticks(void);
+               static void DeallocateJoysticks(void);
+               static bool GetState(int joystickID, int buttonID);
+               static int CheckButtonPressed(void);
+               static int GetButtonID(void);
+               static int GetJoystickID(void);
+               static void Update(void);
+
+               // Support up to 8 gamepads
+               static int numJoysticks;
+               static SDL_Joystick * pad[8];
+               static int numButtons[8];
+               static int numHats[8];
+               static bool button[8][256];
+               static uint8_t hat[8][32];
 };
 
 #endif // __GAMEPAD_H__
index 694be3cb5d20439e78edc2c7e5536d544b9d2998..7efe537b1f9a0ecb8e0b12aab446b7a6b00aee3d 100644 (file)
 //
 
 #include "keygrabber.h"
+#include "gamepad.h"
 
 
-KeyGrabber::KeyGrabber(QWidget * parent/*= 0*/): QDialog(parent)
+KeyGrabber::KeyGrabber(QWidget * parent/*= 0*/): QDialog(parent),
+       label(new QLabel), timer(new QTimer), buttonDown(false)
 {
-       label = new QLabel(this);
+//     label = new QLabel(this);
        QVBoxLayout * mainLayout = new QVBoxLayout;
        mainLayout->addWidget(label);
        setLayout(mainLayout);
        setWindowTitle(tr("Grab"));
+       connect(timer, SIGNAL(timeout()), this, SLOT(CheckGamepad()));
+       timer->setInterval(100);
+       timer->start();
 
        // Will this make Mac OSX work???
        setFocusPolicy(Qt::StrongFocus);
 }
 
+
 KeyGrabber::~KeyGrabber()
 {
+       timer->stop();
 }
 
-//void KeyGrabber::SetText(QString keyText)
+
 void KeyGrabber::SetKeyText(int keyNum)
 {
        char jagButtonName[21][10] = { "Up", "Down", "Left", "Right",
@@ -42,6 +49,7 @@ void KeyGrabber::SetKeyText(int keyNum)
        label->setText(text);
 }
 
+
 void KeyGrabber::keyPressEvent(QKeyEvent * e)
 {
        key = e->key();
@@ -50,3 +58,31 @@ void KeyGrabber::keyPressEvent(QKeyEvent * e)
        if (key != Qt::Key_Alt)
                accept();
 }
+
+
+void KeyGrabber::CheckGamepad(void)
+{
+       // How do we determine which joystick it is, if more than one?
+       // Possibly by a combobox selecting the stick you want to configure...
+       Gamepad::Update();
+
+       if (!buttonDown)
+       {
+               button = Gamepad::CheckButtonPressed();
+
+               if  (button == -1)
+                       return;
+
+               buttonDown = true;
+       }
+       else
+       {
+               if (Gamepad::CheckButtonPressed() == button)
+                       return;
+
+               key = button;
+               accept();
+               buttonDown = false;
+       }
+}
+
index aae59616fe1401441939e0c0f98a1a01b6fea216..cb0abaf7352499413590e2e96d115103d59f7c2c 100644 (file)
@@ -22,8 +22,14 @@ class KeyGrabber: public QDialog
        protected:
                void keyPressEvent(QKeyEvent *);
 
-private:
+       private slots:
+               void CheckGamepad();
+
+       private:
                QLabel * label;
+               QTimer * timer;
+               bool buttonDown;
+               int button;
 
        public:
                int key;
index 892d5a74ff7e8d6aeb08080fa4af29307db8927d..9a739870df9083a596593f11d30c84204fd3db4f 100644 (file)
 
 #include "SDL.h"
 #include "app.h"
-#include "glwidget.h"
 #include "about.h"
-#include "help.h"
-#include "settings.h"
-#include "filepicker.h"
 #include "configdialog.h"
+#include "filepicker.h"
+#include "gamepad.h"
 #include "generaltab.h"
+#include "glwidget.h"
+#include "help.h"
+#include "settings.h"
 #include "version.h"
 #include "debug/cpubrowser.h"
 #include "debug/m68kdasmbrowser.h"
@@ -503,6 +504,21 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state)
 }
 
 
+void MainWin::HandleGamepads(void)
+{
+       Gamepad::Update();
+
+       for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
+       {
+               if (vjs.p1KeyBindings[i] & (JOY_BUTTON | JOY_HAT))
+                       joypad_0_buttons[i] = (Gamepad::GetState(0, vjs.p1KeyBindings[i]) ? 0x01 : 0x00);
+
+               if (vjs.p2KeyBindings[i] & (JOY_BUTTON | JOY_HAT))
+                       joypad_1_buttons[i] = (Gamepad::GetState(1, vjs.p2KeyBindings[i]) ? 0x01 : 0x00);
+       }
+}
+
+
 void MainWin::Open(void)
 {
 }
@@ -606,6 +622,7 @@ void MainWin::Timer(void)
        else
        {
                // Otherwise, run the Jaguar simulation
+               HandleGamepads();
                JaguarExecuteNew();
        }
 
index 27c99ce13b997838909dcef6e05de35267b27ed7..f7276b87e7fa000a41a1d831a09363493eb7f862 100644 (file)
@@ -65,6 +65,7 @@ class MainWin: public QMainWindow
 
        private:
                void HandleKeys(QKeyEvent *, bool);
+               void HandleGamepads(void);
                void SetFullScreen(bool state = true);
                void ResizeMainWindow(void);
                void ReadSettings(void);