]> Shamusworld >> Repos - virtualjaguar/commitdiff
Fixed updated joystick handling, first major stab at gamepad profiles.
authorShamus Hammons <jlhamm@acm.org>
Sat, 4 May 2013 03:53:35 +0000 (22:53 -0500)
committerShamus Hammons <jlhamm@acm.org>
Sat, 4 May 2013 03:53:35 +0000 (22:53 -0500)
There was a problem in JERRY's read byte routine, it was getting bad
data as a result of the conversion of the joystick read routines to
word data size only. Apparently some programs (like Rayman) read
JOYSTICK a byte at a time. :-P

Also, this marks the first stable commit of the the new gamepad profile
system. There's still work to do, but this should make it much nicer
for people who use VJ with multiple input devices.

17 files changed:
src/gui/app.cpp
src/gui/configdialog.cpp
src/gui/configdialog.h
src/gui/controllertab.cpp
src/gui/controllertab.h
src/gui/controllerwidget.cpp
src/gui/controllerwidget.h
src/gui/gamepad.cpp
src/gui/mainwin.cpp
src/gui/mainwin.h
src/gui/profile.cpp [new file with mode: 0644]
src/gui/profile.h [new file with mode: 0644]
src/jerry.cpp
src/joystick.cpp
virtualjaguar.pro
virtualjaguar_fr.ts
virtualjaguar_gr.ts

index a951e644c8921c60698ad93d0f87879ed96336ea..bbe1333a04cb15af8fdd4624f2f5ce25e30fb8fd 100644 (file)
@@ -22,6 +22,7 @@
 #include "gamepad.h"
 #include "log.h"
 #include "mainwin.h"
+#include "profile.h"
 #include "settings.h"
 #include "version.h"
 
@@ -108,6 +109,7 @@ 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();
+               AutoConnectProfiles();
                retVal = app.exec();                                    // And run it!
                Gamepad::DeallocateJoysticks();
 
index 1c8936796b0cd9b82eb2bbb35aed7406e0841786..752713bde6998e163e5597350d97d4e96e634eec 100644 (file)
 #include "settings.h"
 
 
-ConfigDialog::ConfigDialog(QWidget * parent/*= 0*/): QDialog(parent)
+ConfigDialog::ConfigDialog(QWidget * parent/*= 0*/): QDialog(parent),
+       tabWidget(new QTabWidget),
+       generalTab(new GeneralTab(this)),
+       controllerTab1(new ControllerTab(this))
 {
-       tabWidget = new QTabWidget;
-       generalTab = new GeneralTab(this);
-       controllerTab1 = new ControllerTab(this);
-       controllerTab2 = new ControllerTab(this);
+//     tabWidget = new QTabWidget;
+//     generalTab = new GeneralTab(this);
+//     controllerTab1 = new ControllerTab(this);
+////   controllerTab2 = new ControllerTab(this);
 
-       if (vjs.hardwareTypeAlpine)
-               alpineTab = new AlpineTab(this);
+//     if (vjs.hardwareTypeAlpine)
+//             alpineTab = new AlpineTab(this);
 
        tabWidget->addTab(generalTab, tr("General"));
-       tabWidget->addTab(controllerTab1, tr("Controller #1"));
-       tabWidget->addTab(controllerTab2, tr("Controller #2"));
+       tabWidget->addTab(controllerTab1, tr("Controllers"));
+//     tabWidget->addTab(controllerTab2, tr("Controller #2"));
 
        if (vjs.hardwareTypeAlpine)
+       {
+               alpineTab = new AlpineTab(this);
                tabWidget->addTab(alpineTab, tr("Alpine"));
+       }
 
        buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
 
@@ -50,10 +56,7 @@ ConfigDialog::ConfigDialog(QWidget * parent/*= 0*/): QDialog(parent)
        setLayout(mainLayout);
 
        setWindowTitle(tr("Virtual Jaguar Settings"));
-
        LoadDialogFromSettings();
-//     controllerTab1->UpdateLabel();                          // Now it's safe to do this... ;-)
-//     controllerTab2->UpdateLabel();                          // Now it's safe to do this... ;-)
 }
 
 
@@ -82,11 +85,15 @@ void ConfigDialog::LoadDialogFromSettings(void)
                alpineTab->writeROM->setChecked(vjs.allowWritesToROM);
        }
 
+#warning "!!! Need to load settings from controller profile !!!"
+#if 0
        for(int i=0; i<21; i++)
        {
+// We need to find the right profile and load it up here...
                controllerTab1->controllerWidget->keys[i] = vjs.p1KeyBindings[i];
-               controllerTab2->controllerWidget->keys[i] = vjs.p2KeyBindings[i];
+//             controllerTab2->controllerWidget->keys[i] = vjs.p2KeyBindings[i];
        }
+#endif
 }
 
 
@@ -112,10 +119,12 @@ void ConfigDialog::UpdateVJSettings(void)
                vjs.allowWritesToROM = alpineTab->writeROM->isChecked();
        }
 
+#warning "!!! Need to save settings to controller profile !!!"
        for(int i=0; i<21; i++)
        {
+// We need to find the right profile and load it up here...
                vjs.p1KeyBindings[i] = controllerTab1->controllerWidget->keys[i];
-               vjs.p2KeyBindings[i] = controllerTab2->controllerWidget->keys[i];
+//             vjs.p2KeyBindings[i] = controllerTab2->controllerWidget->keys[i];
        }
 }
 
index 532c47ffafb968fea7a57a5f898becfc71b2fdd2..295ebdf10eb0d371f4b8f54bc2449ec1b9cedcc5 100644 (file)
@@ -34,7 +34,7 @@ class ConfigDialog: public QDialog
        public:
                GeneralTab * generalTab;
                ControllerTab * controllerTab1;
-               ControllerTab * controllerTab2;
+//             ControllerTab * controllerTab2;
                AlpineTab * alpineTab;
 };
 
index a5b5328de18c4813909a2bbecbd0f55ddd993744..b9145f68e45e21a2781ac45e15b690877c79c166 100644 (file)
 #include "gamepad.h"
 #include "joystick.h"
 #include "keygrabber.h"
+#include "profile.h"
 
 
 ControllerTab::ControllerTab(QWidget * parent/*= 0*/): QWidget(parent),
-       label(new QLabel(tr("Controller:"))),
-       profileList(new QComboBox(this)),
+       label1(new QLabel(tr("Host Device:"))),
+       label2(new QLabel(tr("Map Name:"))),
+       label3(new QLabel(tr("Maps to:"))),
+       deviceList(new QComboBox(this)),
+       mapNameList(new QComboBox(this)),
+       controller1(new QCheckBox(tr("Jaguar Controller #1"))),
+       controller2(new QCheckBox(tr("Jaguar Controller #2"))),
+       addMapName(new QPushButton(tr("+"))),
+       deleteMapName(new QPushButton(tr("-"))),
        redefineAll(new QPushButton(tr("Define All Inputs"))),
        controllerWidget(new ControllerWidget(this))
 {
+//     mapNameList->setEditable(true);
+
        QVBoxLayout * layout = new QVBoxLayout;
        QHBoxLayout * top = new QHBoxLayout;
+       QVBoxLayout * left = new QVBoxLayout;
+       QVBoxLayout * right = new QVBoxLayout;
+       QHBoxLayout * middle = new QHBoxLayout;
+       top->addLayout(left, 0);
+       top->addLayout(right, 1);
        layout->addLayout(top);
-       top->addWidget(label);
-       top->addWidget(profileList, 0, Qt::AlignLeft);
+       left->addWidget(label1, 0, Qt::AlignRight);
+       left->addWidget(label2, 0, Qt::AlignRight);
+       left->addWidget(label3, 0, Qt::AlignRight);
+       left->addWidget(new QLabel);
+       right->addWidget(deviceList);
+
+       right->addLayout(middle);
+       middle->addWidget(mapNameList, 1);
+       middle->addWidget(addMapName, 0);
+       middle->addWidget(deleteMapName, 0);
+//     right->addWidget(mapNameList);
+
+       right->addWidget(controller1);
+       right->addWidget(controller2);
        layout->addWidget(controllerWidget);
        layout->addWidget(redefineAll, 0, Qt::AlignHCenter);
        setLayout(layout);
@@ -40,15 +67,58 @@ ControllerTab::ControllerTab(QWidget * parent/*= 0*/): QWidget(parent),
        setFixedWidth(sizeHint().width());
 
        connect(redefineAll, SIGNAL(clicked()), this, SLOT(DefineAllKeys()));
-       connect(profileList, SIGNAL(currentIndexChanged(int)), this, SLOT(ChangeProfile(int)));
+       connect(deviceList, SIGNAL(currentIndexChanged(int)), this, SLOT(ChangeDevice(int)));
+       connect(mapNameList, SIGNAL(currentIndexChanged(int)), this, SLOT(ChangeMapName(int)));
+       connect(addMapName, SIGNAL(clicked()), this, SLOT(AddMapName()));
+       connect(deleteMapName, SIGNAL(clicked()), this, SLOT(DeleteMapName()));
+       connect(controllerWidget, SIGNAL(KeyDefined(int, uint32_t)), this, SLOT(UpdateProfileKeys(int, uint32_t)));
+       connect(controller1, SIGNAL(clicked()), this, SLOT(UpdateProfileConnections()));
+       connect(controller2, SIGNAL(clicked()), this, SLOT(UpdateProfileConnections()));
 
-       // Set up the profile combobox (Keyboard is the default, and always
+       // Set up the device combobox (Keyboard is the default, and always
        // present)
-       profileList->addItem(tr("Keyboard"));
+       deviceList->addItem(tr("Keyboard"), 0);
+       // Set up map name combobox (Default is default, and always present)
+//     mapNameList->addItem(tr("Default"));
 
        for(int i=0; i<Gamepad::numJoysticks; i++)
-               profileList->addItem(Gamepad::GetJoystickName(i));
+       {
+               int deviceNum = FindDeviceNumberForName(Gamepad::GetJoystickName(i));
+               deviceList->addItem(Gamepad::GetJoystickName(i), deviceNum);
+       }
 }
+/*
+So now we come to implementation. When changing devices, could have a helper function
+in profile.cpp that fills the mapNameList combobox with the appropriate names/profile
+numbers.
+
+There needs to be some way of getting data from the ControllerWidget and the current
+profile.
+
+Gamepad will have to have some way of knowing which profile is mapped to which
+Jaguar controllers and filtering out everything else.
+
+Will have to have some intelligent handling of profiles when first run, to see first
+what is connected and second, to assign profiles to Jaguar controllers. In this
+case, keyboard is the lowest priority--if a controller is plugged in and assigned to
+the same Jaguar controller as a keyboard, the controller is used. Not sure what to
+do in the case of multiple controllers plugged in and assigned to the same Jaguar
+controller.
+
+Also, need a way to load/save profiles.
+
+Meaning of checkboxes: None checked == profile not used.
+1 checked == prefer connection to Jaguar controller X.
+2 checked == no preference, use any available.
+
+Single mapping cannot be deleted ("-" will be disabled). Can always add, up to the max
+limit of profiles (MAX_PROFILES).
+
+------------------------------
+
+Now the main window passes in/removes the last edited profile #. From here, when starting
+up, we need to pull that number from the profile store and populate all our boxes.
+*/
 
 
 ControllerTab::~ControllerTab()
@@ -56,6 +126,19 @@ ControllerTab::~ControllerTab()
 }
 
 
+void ControllerTab::SetupLastUsedProfile(void)
+{
+       int deviceNum = deviceList->findData(profile[profileNum].device);
+       int mapNum = mapNameList->findText(profile[profileNum].mapName);
+
+       if (deviceNum == -1 || mapNum == -1)
+               return;
+
+       ChangeDevice(deviceNum);
+       ChangeMapName(mapNum);
+}
+
+
 void ControllerTab::DefineAllKeys(void)
 {
 //     char jagButtonName[21][10] = { "Up", "Down", "Left", "Right",
@@ -66,7 +149,6 @@ void ControllerTab::DefineAllKeys(void)
 
        for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
        {
-//             keyGrab.SetText(jagButtonName[orderToDefine[i]]);
                keyGrab.SetKeyText(orderToDefine[i]);
                keyGrab.exec();
                int key = keyGrab.key;
@@ -77,16 +159,60 @@ void ControllerTab::DefineAllKeys(void)
                // Otherwise, populate the appropriate spot in the settings & update screen...
                controllerWidget->keys[orderToDefine[i]] = key;
                controllerWidget->update();
+               profile[profileNum].map[orderToDefine[i]] = key;
        }
 }
 
 
-void ControllerTab::ChangeProfile(int profile)
+void ControllerTab::UpdateProfileKeys(int mapPosition, uint32_t key)
 {
-printf("You selected profile: %s\n", (profile == 0 ? "Keyboard" : Gamepad::GetJoystickName(profile - 1)));
+       profile[profileNum].map[mapPosition] = key;
 }
 
-#if 0
+
+void ControllerTab::UpdateProfileConnections(void)
+{
+       profile[profileNum].preferredController = (controller1->isChecked() ? CONTROLLER1 : 0) | (controller2->isChecked() ? CONTROLLER2 : 0);
+}
+
+
+void ControllerTab::ChangeDevice(int selection)
+{
+       int deviceNum = deviceList->itemData(selection).toInt();
+       mapNameList->clear();
+       int numberOfMappings = FindMappingsForDevice(deviceNum, mapNameList);
+       deleteMapName->setDisabled(numberOfMappings == 1 ? true : false);
+//printf("Found %i mappings for device #%u...\n", numberOfMappings, deviceNum);
+}
+
+
+void ControllerTab::ChangeMapName(int selection)
+{
+       profileNum = mapNameList->itemData(selection).toInt();
+//printf("You selected mapping: %s (profile #%u)\n", (mapNameList->itemText(selection)).toAscii().data(), profileNum);
+
+       for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
+               controllerWidget->keys[i] = profile[profileNum].map[i];
+
+       controllerWidget->update();
+       controller1->setChecked(profile[profileNum].preferredController & CONTROLLER1);
+       controller2->setChecked(profile[profileNum].preferredController & CONTROLLER2);
+}
+
+
+void ControllerTab::AddMapName(void)
+{
+printf("Add new mapping (TODO)...\n");
+}
+
+
+void ControllerTab::DeleteMapName(void)
+{
+printf("Delete current mapping (TODO)...\n");
+}
+
+
+/*
 The profiles need the following:
 
  - The name of the controller
@@ -129,5 +255,32 @@ data structure.
 When a new controller is plugged in with no profiles attached, it defaults to
 a set keyboard layout which the user can change. So every new controller will
 always have at least one profile.
-#endif
+
+Data structures:
+The Gamepad class has the name of the controller (except for Keyboard)
+The profile list is just a list
+The controller name index + profile index makes a unique key
+Probably the best way to deal with it is to stuff the name/profile indices
+into the key definition structure.
+
+#define CONTROLLER1 0x01
+#define CONTROLLER2 0x02
+
+struct Profile
+{
+       int device;                                     // Host device number
+       char mapName[32];                       // Human readable map name
+       int preferredController;        // CONTROLLER1 and/or CONTROLLER2
+       int map[21];                            // Keys/buttons/axes
+};
+
+NOTE that device is an int, and the list is maintained elsewhere. It is
+*not* the same as what you see in GetJoystickName(); the device names have
+to be able to persist even when not available.
+
+Where to store the master profile list? It has to be accessible to this class.
+vjs.profile[x] would be good, but it's not really a concern for the Jaguar core.
+So it shouldn't go there. There should be a separate global setting place for
+GUI stuff...
+*/
 
index 998d193333ac79341500bee89c99231ba669e928..d0749d2d70f63af547398a27644a3e10f98f48d1 100644 (file)
@@ -14,19 +14,32 @@ class ControllerTab: public QWidget
                ControllerTab(QWidget * parent = 0);
                ~ControllerTab();
 
+               void SetupLastUsedProfile(void);
+
        protected slots:
                void DefineAllKeys(void);
-               void ChangeProfile(int);
+               void UpdateProfileKeys(int, uint32_t);
+               void UpdateProfileConnections(void);
+               void ChangeDevice(int);
+               void ChangeMapName(int);
+               void AddMapName(void);
+               void DeleteMapName(void);
 
        private:
-               QLabel * label;
-               QComboBox * controllerList;
-               QComboBox * profileList;
+               QLabel * label1;
+               QLabel * label2;
+               QLabel * label3;
+               QComboBox * deviceList;
+               QComboBox * mapNameList;
+               QCheckBox * controller1;
+               QCheckBox * controller2;
+               QPushButton * addMapName;
+               QPushButton * deleteMapName;
                QPushButton * redefineAll;
 
        public:
                ControllerWidget * controllerWidget;
-               int profile;
+               int profileNum;
 };
 
 #endif // __CONTROLLERTAB_H__
index eb91c34274ea28666dbd020a8e7e74e522de395d..53a747a01d62e2f919ffe3a55fdf2a454525fce5 100644 (file)
@@ -182,7 +182,10 @@ void ControllerWidget::mouseReleaseEvent(QMouseEvent * /*event*/)
        int key = keyGrab.key;
 
        if (key != Qt::Key_Escape)
+       {
                keys[keyToHighlightSave] = key;
+               emit(KeyDefined(keyToHighlightSave, key));
+       }
 
        keyToHighlight = keyToHighlightSave;
        update();
index b1065cdffe859b7f8ff25a4f98fbaa6b8e86a71a..d506071d9f7d9501f8892c5d22ec290cd8ed325c 100644 (file)
@@ -24,6 +24,9 @@ class ControllerWidget: public QWidget
        private:
                void DrawBorderedText(QPainter &, int, int, QString);
 
+       signals:
+               void KeyDefined(int, uint32_t);
+
        public:
                uint32_t keys[21];
 
index 8706e17643667499b39d8fe78caed6190898181a..93989eed7ae7a975ecdec6d39469f23e06809da6 100644 (file)
@@ -52,7 +52,7 @@ void Gamepad::AllocateJoysticks(void)
        {
                pad[i] = SDL_JoystickOpen(i);
                padName[i] = SDL_JoystickName(i);
-               numButtons[i] = numHats[i] = 0;
+               numButtons[i] = numHats[i] = numAxes[i] = 0;
 
                if (pad[i])
                {
@@ -104,14 +104,21 @@ bool Gamepad::GetState(int joystickID, int buttonID)
        {
                int axisNum = (buttonID & JOY_AXISNUM_MASK) >> 1;
                int direction = (buttonID & JOY_AXISDIR_MASK);
+//printf("Checking pad #%u axis %u: axis = %i, direction = %u\n", joystickID, axisNum, axis[joystickID][axisNum], direction);
 
                if (axis[joystickID][axisNum] != 0)
                {
-                       if (axis[joystickID][axisNum] > 16000 && (direction == 0))
+                       if ((axis[joystickID][axisNum] > 32000) && (direction == 0))
+//{
+//printf("Axis + hit!\n");
                                return true;
+//}
 
-                       if (axis[joystickID][axisNum] < -16000 && (direction == 1))
+                       if ((axis[joystickID][axisNum] < -32000) && (direction == 1))
+//{
+//printf("Axis - hit!\n");
                                return true;
+//}
                }
        }
 
index 43ec937cbf5cfbaa123d7746f6f02bc06d40fe8f..3c93d03a8a62ce02a06b87e12372d8f0520c2639 100644 (file)
 #include "app.h"
 #include "about.h"
 #include "configdialog.h"
+#include "controllertab.h"
 #include "filepicker.h"
 #include "gamepad.h"
 #include "generaltab.h"
 #include "glwidget.h"
 #include "help.h"
+#include "profile.h"
 #include "settings.h"
 #include "version.h"
 #include "debug/cpubrowser.h"
@@ -564,7 +566,10 @@ void MainWin::HandleGamepads(void)
        {
                if (vjs.p1KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS))
                        joypad0Buttons[i] = (Gamepad::GetState(0, vjs.p1KeyBindings[i]) ? 0x01 : 0x00);
-
+/*{
+if (vjs.p1KeyBindings[i] & JOY_AXIS)
+       printf("Axis state (HandleGamepads): %i\n", joypad0Buttons[i]);
+}*/
                if (vjs.p2KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS))
                        joypad1Buttons[i] = (Gamepad::GetState(1, vjs.p2KeyBindings[i]) ? 0x01 : 0x00);
        }
@@ -582,6 +587,8 @@ void MainWin::Configure(void)
        ConfigDialog dlg(this);
        //ick.
        dlg.generalTab->useUnknownSoftware->setChecked(allowUnknownSoftware);
+       dlg.controllerTab1->profileNum = lastEditedProfile;
+       dlg.controllerTab1->SetupLastUsedProfile();
 
        if (dlg.exec() == false)
                return;
@@ -601,6 +608,7 @@ void MainWin::Configure(void)
        bool allowOld = allowUnknownSoftware;
        //ick.
        allowUnknownSoftware = dlg.generalTab->useUnknownSoftware->isChecked();
+       lastEditedProfile = dlg.controllerTab1->profileNum;
 
        // We rescan the "software" folder if the user either changed the path or
        // checked/unchecked the "Allow unknown files" option in the config dialog.
@@ -1074,6 +1082,7 @@ void MainWin::ReadSettings(void)
 
        zoomLevel = settings.value("zoom", 2).toInt();
        allowUnknownSoftware = settings.value("showUnknownSoftware", false).toBool();
+       lastEditedProfile = settings.value("lastEditedProfile", 0).toInt();
 
        vjs.useJoystick      = settings.value("useJoystick", false).toBool();
        vjs.joyport          = settings.value("joyport", 0).toInt();
@@ -1146,6 +1155,8 @@ WriteLog("Pipelined DSP = %s\n", (vjs.usePipelinedDSP ? "ON" : "off"));
        vjs.p2KeyBindings[BUTTON_9] = settings.value("p2k_9", Qt::Key_9).toInt();
        vjs.p2KeyBindings[BUTTON_d] = settings.value("p2k_pound", Qt::Key_Slash).toInt();
        vjs.p2KeyBindings[BUTTON_s] = settings.value("p2k_star", Qt::Key_Asterisk).toInt();
+
+       ReadProfiles(&settings);
 }
 
 
@@ -1158,6 +1169,7 @@ void MainWin::WriteSettings(void)
 
        settings.setValue("zoom", zoomLevel);
        settings.setValue("showUnknownSoftware", allowUnknownSoftware);
+       settings.setValue("lastEditedProfile", lastEditedProfile);
 
        settings.setValue("useJoystick", vjs.useJoystick);
        settings.setValue("joyport", vjs.joyport);
@@ -1224,6 +1236,8 @@ void MainWin::WriteSettings(void)
        settings.setValue("p2k_9", vjs.p2KeyBindings[BUTTON_9]);
        settings.setValue("p2k_pound", vjs.p2KeyBindings[BUTTON_d]);
        settings.setValue("p2k_star", vjs.p2KeyBindings[BUTTON_s]);
+
+       WriteProfiles(&settings);
 }
 
 
@@ -1236,3 +1250,4 @@ void MainWin::WriteUISettings(void)
 
        settings.setValue("zoom", zoomLevel);
 }
+
index c87ce997dd4ee1fe44ac96ebe83e86eae030dbfd..06ca4054e86a75e3c512a66afa92b704691ee68c 100644 (file)
@@ -108,6 +108,7 @@ class MainWin: public QMainWindow
        private:
                QPoint mainWinPosition;
 //             QSize mainWinSize;
+               int lastEditedProfile;
                QMenu * fileMenu;
                QMenu * helpMenu;
                QMenu * debugMenu;
diff --git a/src/gui/profile.cpp b/src/gui/profile.cpp
new file mode 100644 (file)
index 0000000..05d173d
--- /dev/null
@@ -0,0 +1,290 @@
+//
+// profile.cpp - Global profile storage/definition/manipulation
+//
+// by James Hammons
+// (C) 2013 Underground Software
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -------------------------------------------------------------
+// JLH  05/01/2013  Created this file
+//
+
+
+#include "profile.h"
+#include <QtGui>
+#include "gamepad.h"
+#include "settings.h"
+
+
+#define MAX_DEVICES  64
+
+
+Profile profile[MAX_PROFILES];
+int controller1Profile;
+int controller2Profile;
+int gamepad1Slot;
+int gamepad2Slot;
+int numberOfProfiles;
+int numberOfDevices;
+char deviceNames[MAX_DEVICES][128];
+
+// This is so that new devices have something reasonable to show for default
+uint32_t defaultMap[21] = {
+       'S', 'X', 'Z', 'C', '-','7', '4', '1', '0', '8', '5', '2', '=', '9', '6',
+       '3', 'L', 'K', 'J', 'O', 'P'
+};
+
+
+void ReadProfiles(QSettings * set)
+{
+       // Assume no profiles, until we read them
+       numberOfProfiles = 0;
+
+       // There is always at least one device present, and it's the keyboard
+       // (hey, we're PC centric here ;-)
+       numberOfDevices = 1;
+       strcpy(deviceNames[0], "Keyboard");
+
+       // Read the rest of the devices (if any)
+       numberOfDevices += set->beginReadArray("devices");
+
+       for(int i=1; i<numberOfDevices; i++)
+       {
+               set->setArrayIndex(i - 1);
+               strcpy(deviceNames[i], set->value("deviceName").toString().toAscii().data());
+//printf("Read device name: %s\n", deviceNames[i]);
+       }
+
+       set->endArray();
+       numberOfProfiles = set->beginReadArray("profiles");
+//printf("Number of profiles: %u\n", numberOfProfiles);
+
+       for(int i=0; i<numberOfProfiles; i++)
+       {
+               set->setArrayIndex(i);
+               profile[i].device = set->value("deviceNum").toInt();
+               strcpy(profile[i].mapName, set->value("mapName").toString().toAscii().data());
+               profile[i].preferredController = set->value("preferredController").toInt();
+
+               for(int j=0; j<21; j++)
+               {
+                       QString string = QString("map%1").arg(j);
+                       profile[i].map[j] = set->value(string).toInt();
+               }
+//printf("Profile #%u: device=%u (%s)\n", i, profile[i].device, deviceNames[profile[i].device]);
+       }
+
+       set->endArray();
+
+//printf("Number of profiles found: %u\n", numberOfProfiles);
+       // Set up a reasonable default if no profiles were found
+       if (numberOfProfiles == 0)
+       {
+//printf("Setting up default profile...\n");
+               numberOfProfiles++;
+               profile[0].device = 0;  // Keyboard is always device #0
+               strcpy(profile[0].mapName, "Default");
+               profile[0].preferredController = CONTROLLER1;
+
+               for(int i=0; i<21; i++)
+                       profile[0].map[i] = defaultMap[i];
+       }
+}
+
+
+void WriteProfiles(QSettings * set)
+{
+#if 0
+       // Don't write anything for now...
+       return;
+#endif
+       // NB: Should only do this if something changed; otherwise, no need to do
+       //     this.
+       set->beginWriteArray("devices");
+
+       for(int i=1; i<numberOfDevices; i++)
+       {
+               set->setArrayIndex(i - 1);
+               set->setValue("deviceName", deviceNames[i]);
+       }
+
+       set->endArray();
+       set->beginWriteArray("profiles");
+
+       for(int i=0; i<numberOfProfiles; i++)
+       {
+               set->setArrayIndex(i);
+               set->setValue("deviceNum", profile[i].device);
+               set->setValue("mapName", profile[i].mapName);
+               set->setValue("preferredController", profile[i].preferredController);
+
+               for(int j=0; j<21; j++)
+               {
+                       QString string = QString("map%1").arg(j);
+                       set->setValue(string, profile[i].map[j]);
+               }
+       }
+
+       set->endArray();
+}
+
+
+int FindDeviceNumberForName(const char * name)
+{
+       for(int i=0; i<numberOfDevices; i++)
+       {
+               if (strcmp(deviceNames[i], name) == 0)
+                       return i;
+       }
+
+       if (numberOfDevices == MAX_DEVICES)
+               return -1;
+
+       // If the device wasn't found, it must be new; so add it to the list.
+       int deviceNum = numberOfDevices;
+       deviceNames[deviceNum][127] = 0;
+       strncpy(deviceNames[deviceNum], name, 127);
+       numberOfDevices++;
+
+       return deviceNum;
+}
+
+
+int FindMappingsForDevice(int deviceNum, QComboBox * combo)
+{
+       int found = 0;
+
+       for(int i=0; i<numberOfProfiles; i++)
+       {
+               if (profile[i].device == -1)
+                       continue;
+
+               if (profile[i].device == deviceNum)
+               {
+                       combo->addItem(profile[i].mapName, i);
+                       found++;
+               }
+       }
+
+       // If no mappings were found, create a default one for it
+       if (found == 0)
+       {
+               profile[numberOfProfiles].device = deviceNum;
+               strcpy(profile[numberOfProfiles].mapName, "Default");
+               profile[numberOfProfiles].preferredController = CONTROLLER1;
+
+               for(int i=0; i<21; i++)
+                       profile[numberOfProfiles].map[i] = defaultMap[i];
+
+               combo->addItem(profile[numberOfProfiles].mapName, numberOfProfiles);
+               numberOfProfiles++;
+               found++;
+       }
+
+       return found;
+}
+
+
+bool ConnectProfileToController(int profileNum, int controllerNum)
+{
+       if (profile[profileNum].device == -1)
+               return false;
+
+       if (controllerNum < 0 || controllerNum > 2)
+               return false;
+
+       uint32_t * dest = (controllerNum == 0 ? &vjs.p1KeyBindings[0] : &vjs.p2KeyBindings[0]);
+
+       for(int i=0; i<21; i++)
+               dest[i] = profile[profileNum].map[i];
+
+printf("Successfully mapped device '%s' (%s) to controller #%u...\n", deviceNames[profile[profileNum].device], profile[profileNum].mapName, controllerNum);
+       return true;
+}
+
+
+//
+// This is a pretty crappy way of doing autodetection. What it does is scan for
+// keyboard profiles first, then look for plugged in gamepads next. If more
+// than one plugged in gamepad matches a preferred controller slot, the last
+// one found is chosen.
+//
+// There has to be a better way to do this, I just can't think of what it
+// should be ATM... :-P
+//
+/*
+Also, there is a problem with this approach and having multiple devices
+that are the same. Currently, if two of the same device are plugged in
+and the profile is set to both controllers, it will broadcast buttons
+pressed from either gamepad, no matter who is pressing them. This is
+BAD(tm). [Not true, but there's a different problem described under 'How to
+solve?', so GOOD(tm).]
+
+Also, the gamepad logic doesn't distinguish inputs by controller, it just
+grabs them all regardless. This is also BAD(tm). [Actually, it doesn't. It
+properly segregates the inputs. So this is GOOD(tm).]
+
+How to solve?
+
+Seems there's yet ANOTHER dimension to all this: The physical gamepads
+plugged into their ports. Now the device # can map these fine if they're
+different, but we still run into problems with the handling in the MainWin
+because it's hardwired to take pad 0 in slot 0 and pad 1 in slot 1. If you have
+them configured other than this, you won't get anything. So we need to also
+map the physical devices to their respective slots.
+*/
+void AutoConnectProfiles(void)
+{
+       int controller1Profile = -1;
+       int controller2Profile = -1;
+
+       // Nothing plugged in, we fall back to the default keyboard device profiles
+//     if (Gamepad::numJoysticks == 0)
+       {
+// Check for Keyboard device first, if anything else is plugged in it will
+// default to it instead
+               for(int i=0; i<numberOfProfiles; i++)
+               {
+                       // Skip profile if it's not Keyboard device
+                       if (profile[i].device != 0)
+                               continue;
+
+                       if (profile[i].preferredController & CONTROLLER1)
+                               controller1Profile = i;
+
+                       if (profile[i].preferredController & CONTROLLER2)
+                               controller2Profile = i;
+               }
+       }
+//     else
+       {
+//printf("Number of gamepads found: %u\n", Gamepad::numJoysticks);
+               for(int i=0; i<Gamepad::numJoysticks; i++)
+               {
+                       int deviceNum = FindDeviceNumberForName(Gamepad::GetJoystickName(i));
+//printf("Attempting to find valid gamepad profile. Device=%u\n", deviceNum);
+
+                       for(int j=0; j<numberOfProfiles; j++)
+                       {
+                               // Skip profile if it's not discovered device
+                               if (profile[j].device != deviceNum)
+                                       continue;
+
+                               if (profile[j].preferredController & CONTROLLER1)
+                                       controller1Profile = j;
+
+                               if (profile[j].preferredController & CONTROLLER2)
+                                       controller2Profile = j;
+                       }
+               }
+       }
+
+       if (controller1Profile != -1)
+               ConnectProfileToController(controller1Profile, 0);
+
+       if (controller2Profile != -1)
+               ConnectProfileToController(controller2Profile, 1);
+}
+
diff --git a/src/gui/profile.h b/src/gui/profile.h
new file mode 100644 (file)
index 0000000..df164f6
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __PROFILE_H__
+#define __PROFILE_H__
+
+#include <stdint.h>
+
+class QComboBox;
+class QSettings;
+
+#define MAX_PROFILES  64
+#define CONTROLLER1   0x01
+#define CONTROLLER2   0x02
+
+
+struct Profile
+{
+       int device;                                     // Host device number (-1 == invalid profile)
+       char mapName[32];                       // Human readable map name
+       int preferredController;        // CONTROLLER1 and/or CONTROLLER2
+       uint32_t map[21];                       // Keys/buttons/axes
+};
+
+
+// Function prototypes
+void ReadProfiles(QSettings *);
+void WriteProfiles(QSettings *);
+int FindDeviceNumberForName(const char *);
+int FindMappingsForDevice(int, QComboBox *);
+bool ConnectProfileToController(int, int);
+void AutoConnectProfiles(void);
+
+
+// Exported variables
+extern Profile profile[];
+extern int controller1Profile;
+extern int controller2Profile;
+extern int gamepad1Slot;
+extern int gamepad2Slot;
+//extern int numberOfProfiles;
+
+#endif // __PROFILE_H__
+
index 3237d7bd16ca461492a090788725cf89b789dcc4..e0255c49d394b071e5e290711a282d37a274996a 100644 (file)
@@ -436,7 +436,17 @@ WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset);
 //             return anajoy_byte_read(offset);
        else if (offset >= 0xF14000 && offset <= 0xF14003)
 //             return JoystickReadByte(offset) | EepromReadByte(offset);
-               return JoystickReadWord(offset & 0xFE) | EepromReadByte(offset);
+       {
+               uint16_t value = JoystickReadWord(offset & 0xFE);
+
+               if (offset & 0x01)
+                       value &= 0xFF;
+               else
+                       value >>= 8;
+
+               // This is wrong, should only have the lowest bit from $F14001
+               return value | EepromReadByte(offset);
+       }
        else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
                return EepromReadByte(offset);
 
@@ -569,8 +579,10 @@ WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", offset);
        }*/
        else if ((offset >= 0xF14000) && (offset <= 0xF14003))
        {
+WriteLog("JERRYWriteByte: Unhandled byte write to JOYSTICK by %s.\n", whoName[who]);
 //             JoystickWriteByte(offset, data);
                JoystickWriteWord(offset & 0xFE, (uint16_t)data);
+// This is wrong, EEPROM is never written here
                EepromWriteByte(offset, data);
                return;
        }
index e662bf1308526a475013527da707480c1c1eccf5..91cfbbb0b661563c5c2caf3d77dbfd415ad9e4b1 100644 (file)
@@ -136,7 +136,7 @@ uint16_t JoystickReadWord(uint32_t offset)
                return ~data;
 #else
                if (!joysticksEnabled)
-                       return 0xFF;
+                       return 0xFFFF;
 
                // Joystick data returns active low for buttons pressed, high for non-
                // pressed.
@@ -147,6 +147,7 @@ uint16_t JoystickReadWord(uint32_t offset)
                if (offset0 != 0xFF)
                {
                        uint16_t mask[4] = { 0xFEFF, 0xFDFF, 0xFBFF, 0xF7FF };
+//                     uint16_t mask[4] = { 0xFFFE, 0xFFFD, 0xFFFB, 0xFFF7 };
 
                        for(uint8_t i=0; i<4; i++)
                                data &= (joypad0Buttons[offset0 + i] ? mask[i] : 0xFFFF);
@@ -155,6 +156,7 @@ uint16_t JoystickReadWord(uint32_t offset)
                if (offset1 != 0xFF)
                {
                        uint16_t mask[4] = { 0xEFFF, 0xDFFF, 0xBFFF, 0x7FFF };
+//                     uint16_t mask[4] = { 0xFFEF, 0xFFDF, 0xFFBF, 0xFF7F };
 
                        for(uint8_t i=0; i<4; i++)
                                data &= (joypad1Buttons[offset1 + i] ? mask[i] : 0xFFFF);
@@ -252,7 +254,7 @@ uint16_t JoystickReadWord(uint32_t offset)
        }
 
 //     return joystick_ram[offset];
-       return 0xFF;
+       return 0xFFFF;
 }
 
 
index 31bf263af45fbd51ccb7b024e714183b7bd6e64b..7eb87789c51944d969b4d2f1bf92a7f77ec19960 100644 (file)
@@ -78,6 +78,7 @@ HEADERS = \
        src/gui/imagedelegate.h \
        src/gui/keygrabber.h \
        src/gui/mainwin.h \
+       src/gui/profile.h \
        src/gui/debug/cpubrowser.h \
        src/gui/debug/m68kdasmbrowser.h \
        src/gui/debug/memorybrowser.h \
@@ -102,6 +103,7 @@ SOURCES = \
        src/gui/imagedelegate.cpp \
        src/gui/keygrabber.cpp \
        src/gui/mainwin.cpp \
+       src/gui/profile.cpp \
        src/gui/debug/cpubrowser.cpp \
        src/gui/debug/m68kdasmbrowser.cpp \
        src/gui/debug/memorybrowser.cpp \
index 26f7b1380b648949bc2646febc5d3d797cc5578f..8d12ab8a1b30a175f943452b112164317ff1eefa 100644 (file)
@@ -4,7 +4,8 @@
 <context>
     <name>AboutWindow</name>
     <message id="0">
-        <location filename="src/gui/about.cpp" line="25"/>
+        <location filename="src/gui/about.cpp" line="26"/>
+        <location filename="src/gui/controllertab.cpp" line="25"/>
         <location filename="src/gui/debug/cpubrowser.cpp" line="27"/>
         <location filename="src/gui/debug/m68kdasmbrowser.cpp" line="27"/>
         <location filename="src/gui/debug/memorybrowser.cpp" line="24"/>
@@ -16,7 +17,7 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/about.cpp" line="32"/>
+        <location filename="src/gui/about.cpp" line="33"/>
         <source>&lt;img src=&apos;:/res/vj_title_small.png&apos; style=&apos;float: right&apos;&gt;&lt;table&gt;&lt;tr&gt;&lt;td align=&apos;right&apos;&gt;&lt;b&gt;Version: &lt;/b&gt;&lt;/td&gt;&lt;td&gt;</source>
         <translation type="unfinished"></translation>
     </message>
 <context>
     <name>ControllerTab</name>
     <message>
-        <location filename="src/gui/controllertab.cpp" line="26"/>
-        <source>Define All Keys</source>
+        <location filename="src/gui/controllertab.cpp" line="27"/>
+        <source>Define All Inputs</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="src/gui/controllertab.cpp" line="47"/>
+        <source>Keyboard</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
 <context>
     <name>MainWin</name>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="95"/>
+        <location filename="src/gui/mainwin.cpp" line="102"/>
         <source>Virtual Jaguar </source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="98"/>
+        <location filename="src/gui/mainwin.cpp" line="105"/>
         <source> - Alpine Mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="118"/>
+        <location filename="src/gui/mainwin.cpp" line="125"/>
         <source>E&amp;xit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="121"/>
+        <location filename="src/gui/mainwin.cpp" line="128"/>
         <source>Ctrl+q</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="122"/>
+        <location filename="src/gui/mainwin.cpp" line="130"/>
         <source>Quit Virtual Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="131"/>
+        <location filename="src/gui/mainwin.cpp" line="139"/>
         <source>&amp;Power</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="132"/>
+        <location filename="src/gui/mainwin.cpp" line="140"/>
         <source>Powers Jaguar on/off</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="142"/>
+        <location filename="src/gui/mainwin.cpp" line="150"/>
         <source>Pause</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="143"/>
+        <location filename="src/gui/mainwin.cpp" line="151"/>
         <source>Toggles the running state</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="146"/>
+        <location filename="src/gui/mainwin.cpp" line="154"/>
         <source>Esc</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="151"/>
+        <location filename="src/gui/mainwin.cpp" line="160"/>
         <source>Zoom 100%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="152"/>
+        <location filename="src/gui/mainwin.cpp" line="161"/>
         <source>Set window zoom to 100%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="156"/>
+        <location filename="src/gui/mainwin.cpp" line="165"/>
         <source>Zoom 200%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="157"/>
+        <location filename="src/gui/mainwin.cpp" line="166"/>
         <source>Set window zoom to 200%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="161"/>
+        <location filename="src/gui/mainwin.cpp" line="170"/>
         <source>Zoom 300%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="162"/>
+        <location filename="src/gui/mainwin.cpp" line="171"/>
         <source>Set window zoom to 300%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="168"/>
+        <location filename="src/gui/mainwin.cpp" line="177"/>
         <source>NTSC</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="169"/>
+        <location filename="src/gui/mainwin.cpp" line="178"/>
         <source>Sets Jaguar to NTSC mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="173"/>
+        <location filename="src/gui/mainwin.cpp" line="182"/>
         <source>PAL</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="174"/>
+        <location filename="src/gui/mainwin.cpp" line="183"/>
         <source>Sets Jaguar to PAL mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="178"/>
+        <location filename="src/gui/mainwin.cpp" line="187"/>
         <source>Blur</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="179"/>
+        <location filename="src/gui/mainwin.cpp" line="188"/>
         <source>Sets OpenGL rendering to GL_NEAREST</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="183"/>
+        <location filename="src/gui/mainwin.cpp" line="192"/>
         <source>&amp;About...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="184"/>
+        <location filename="src/gui/mainwin.cpp" line="193"/>
         <source>Blatant self-promotion</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="187"/>
+        <location filename="src/gui/mainwin.cpp" line="196"/>
         <source>&amp;Contents...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="188"/>
+        <location filename="src/gui/mainwin.cpp" line="197"/>
         <source>Help is available, if you should need it</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="191"/>
+        <location filename="src/gui/mainwin.cpp" line="200"/>
         <source>&amp;Insert Cartridge...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="192"/>
+        <location filename="src/gui/mainwin.cpp" line="201"/>
         <source>Insert a cartridge into Virtual Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="193"/>
+        <location filename="src/gui/mainwin.cpp" line="202"/>
         <source>Ctrl+i</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="196"/>
+        <location filename="src/gui/mainwin.cpp" line="206"/>
         <source>&amp;Configure</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="197"/>
+        <location filename="src/gui/mainwin.cpp" line="207"/>
         <source>Configure options for Virtual Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="198"/>
+        <location filename="src/gui/mainwin.cpp" line="208"/>
         <source>Ctrl+c</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="201"/>
+        <location filename="src/gui/mainwin.cpp" line="212"/>
         <source>&amp;Use CD Unit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="202"/>
+        <location filename="src/gui/mainwin.cpp" line="213"/>
         <source>Use Jaguar Virtual CD unit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="207"/>
+        <location filename="src/gui/mainwin.cpp" line="218"/>
         <source>&amp;Frame Advance</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="208"/>
+        <location filename="src/gui/mainwin.cpp" line="219"/>
         <source>F7</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="211"/>
+        <location filename="src/gui/mainwin.cpp" line="224"/>
         <source>F&amp;ull Screen</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="212"/>
+        <location filename="src/gui/mainwin.cpp" line="225"/>
         <source>F9</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="217"/>
+        <location filename="src/gui/mainwin.cpp" line="231"/>
         <source>Memory Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="218"/>
+        <location filename="src/gui/mainwin.cpp" line="232"/>
         <source>Shows the Jaguar memory browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="222"/>
+        <location filename="src/gui/mainwin.cpp" line="236"/>
         <source>CPU Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="223"/>
+        <location filename="src/gui/mainwin.cpp" line="237"/>
         <source>Shows the Jaguar CPU browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="227"/>
+        <location filename="src/gui/mainwin.cpp" line="241"/>
         <source>OP Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="228"/>
+        <location filename="src/gui/mainwin.cpp" line="242"/>
         <source>Shows the Jaguar OP browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="232"/>
+        <location filename="src/gui/mainwin.cpp" line="246"/>
         <source>68K Listing Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="233"/>
+        <location filename="src/gui/mainwin.cpp" line="247"/>
         <source>Shows the 68K disassembly browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="237"/>
+        <location filename="src/gui/mainwin.cpp" line="251"/>
         <source>RISC Listing Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="238"/>
+        <location filename="src/gui/mainwin.cpp" line="252"/>
         <source>Shows the RISC disassembly browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="248"/>
+        <location filename="src/gui/mainwin.cpp" line="262"/>
         <source>&amp;Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="259"/>
-        <location filename="src/gui/mainwin.cpp" line="289"/>
+        <location filename="src/gui/mainwin.cpp" line="273"/>
+        <location filename="src/gui/mainwin.cpp" line="304"/>
         <source>&amp;Debug</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="267"/>
+        <location filename="src/gui/mainwin.cpp" line="281"/>
         <source>&amp;Help</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="271"/>
+        <location filename="src/gui/mainwin.cpp" line="285"/>
         <source>Stuff</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="298"/>
+        <location filename="src/gui/mainwin.cpp" line="322"/>
         <source>Ready</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="575"/>
-        <location filename="src/gui/mainwin.cpp" line="588"/>
+        <location filename="src/gui/mainwin.cpp" line="617"/>
+        <location filename="src/gui/mainwin.cpp" line="630"/>
         <source>Could not load file &quot;%1&quot;!</source>
         <translation type="unfinished"></translation>
     </message>
index a40cce8c08f49c4e885beb74a89da8b6c997a339..dfa51ea6abb0b8dabb3dd937b2b3108a607d5858 100644 (file)
@@ -4,7 +4,8 @@
 <context>
     <name>AboutWindow</name>
     <message id="0">
-        <location filename="src/gui/about.cpp" line="25"/>
+        <location filename="src/gui/about.cpp" line="26"/>
+        <location filename="src/gui/controllertab.cpp" line="25"/>
         <location filename="src/gui/debug/cpubrowser.cpp" line="27"/>
         <location filename="src/gui/debug/m68kdasmbrowser.cpp" line="27"/>
         <location filename="src/gui/debug/memorybrowser.cpp" line="24"/>
@@ -16,7 +17,7 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/about.cpp" line="32"/>
+        <location filename="src/gui/about.cpp" line="33"/>
         <source>&lt;img src=&apos;:/res/vj_title_small.png&apos; style=&apos;float: right&apos;&gt;&lt;table&gt;&lt;tr&gt;&lt;td align=&apos;right&apos;&gt;&lt;b&gt;Version: &lt;/b&gt;&lt;/td&gt;&lt;td&gt;</source>
         <translation type="unfinished"></translation>
     </message>
 <context>
     <name>ControllerTab</name>
     <message>
-        <location filename="src/gui/controllertab.cpp" line="26"/>
-        <source>Define All Keys</source>
+        <location filename="src/gui/controllertab.cpp" line="27"/>
+        <source>Define All Inputs</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="src/gui/controllertab.cpp" line="47"/>
+        <source>Keyboard</source>
         <translation type="unfinished"></translation>
     </message>
 </context>
 <context>
     <name>MainWin</name>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="95"/>
+        <location filename="src/gui/mainwin.cpp" line="102"/>
         <source>Virtual Jaguar </source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="98"/>
+        <location filename="src/gui/mainwin.cpp" line="105"/>
         <source> - Alpine Mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="118"/>
+        <location filename="src/gui/mainwin.cpp" line="125"/>
         <source>E&amp;xit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="121"/>
+        <location filename="src/gui/mainwin.cpp" line="128"/>
         <source>Ctrl+q</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="122"/>
+        <location filename="src/gui/mainwin.cpp" line="130"/>
         <source>Quit Virtual Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="131"/>
+        <location filename="src/gui/mainwin.cpp" line="139"/>
         <source>&amp;Power</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="132"/>
+        <location filename="src/gui/mainwin.cpp" line="140"/>
         <source>Powers Jaguar on/off</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="142"/>
+        <location filename="src/gui/mainwin.cpp" line="150"/>
         <source>Pause</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="143"/>
+        <location filename="src/gui/mainwin.cpp" line="151"/>
         <source>Toggles the running state</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="146"/>
+        <location filename="src/gui/mainwin.cpp" line="154"/>
         <source>Esc</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="151"/>
+        <location filename="src/gui/mainwin.cpp" line="160"/>
         <source>Zoom 100%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="152"/>
+        <location filename="src/gui/mainwin.cpp" line="161"/>
         <source>Set window zoom to 100%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="156"/>
+        <location filename="src/gui/mainwin.cpp" line="165"/>
         <source>Zoom 200%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="157"/>
+        <location filename="src/gui/mainwin.cpp" line="166"/>
         <source>Set window zoom to 200%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="161"/>
+        <location filename="src/gui/mainwin.cpp" line="170"/>
         <source>Zoom 300%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="162"/>
+        <location filename="src/gui/mainwin.cpp" line="171"/>
         <source>Set window zoom to 300%</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="168"/>
+        <location filename="src/gui/mainwin.cpp" line="177"/>
         <source>NTSC</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="169"/>
+        <location filename="src/gui/mainwin.cpp" line="178"/>
         <source>Sets Jaguar to NTSC mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="173"/>
+        <location filename="src/gui/mainwin.cpp" line="182"/>
         <source>PAL</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="174"/>
+        <location filename="src/gui/mainwin.cpp" line="183"/>
         <source>Sets Jaguar to PAL mode</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="178"/>
+        <location filename="src/gui/mainwin.cpp" line="187"/>
         <source>Blur</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="179"/>
+        <location filename="src/gui/mainwin.cpp" line="188"/>
         <source>Sets OpenGL rendering to GL_NEAREST</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="183"/>
+        <location filename="src/gui/mainwin.cpp" line="192"/>
         <source>&amp;About...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="184"/>
+        <location filename="src/gui/mainwin.cpp" line="193"/>
         <source>Blatant self-promotion</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="187"/>
+        <location filename="src/gui/mainwin.cpp" line="196"/>
         <source>&amp;Contents...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="188"/>
+        <location filename="src/gui/mainwin.cpp" line="197"/>
         <source>Help is available, if you should need it</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="191"/>
+        <location filename="src/gui/mainwin.cpp" line="200"/>
         <source>&amp;Insert Cartridge...</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="192"/>
+        <location filename="src/gui/mainwin.cpp" line="201"/>
         <source>Insert a cartridge into Virtual Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="193"/>
+        <location filename="src/gui/mainwin.cpp" line="202"/>
         <source>Ctrl+i</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="196"/>
+        <location filename="src/gui/mainwin.cpp" line="206"/>
         <source>&amp;Configure</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="197"/>
+        <location filename="src/gui/mainwin.cpp" line="207"/>
         <source>Configure options for Virtual Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="198"/>
+        <location filename="src/gui/mainwin.cpp" line="208"/>
         <source>Ctrl+c</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="201"/>
+        <location filename="src/gui/mainwin.cpp" line="212"/>
         <source>&amp;Use CD Unit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="202"/>
+        <location filename="src/gui/mainwin.cpp" line="213"/>
         <source>Use Jaguar Virtual CD unit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="207"/>
+        <location filename="src/gui/mainwin.cpp" line="218"/>
         <source>&amp;Frame Advance</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="208"/>
+        <location filename="src/gui/mainwin.cpp" line="219"/>
         <source>F7</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="211"/>
+        <location filename="src/gui/mainwin.cpp" line="224"/>
         <source>F&amp;ull Screen</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="212"/>
+        <location filename="src/gui/mainwin.cpp" line="225"/>
         <source>F9</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="217"/>
+        <location filename="src/gui/mainwin.cpp" line="231"/>
         <source>Memory Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="218"/>
+        <location filename="src/gui/mainwin.cpp" line="232"/>
         <source>Shows the Jaguar memory browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="222"/>
+        <location filename="src/gui/mainwin.cpp" line="236"/>
         <source>CPU Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="223"/>
+        <location filename="src/gui/mainwin.cpp" line="237"/>
         <source>Shows the Jaguar CPU browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="227"/>
+        <location filename="src/gui/mainwin.cpp" line="241"/>
         <source>OP Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="228"/>
+        <location filename="src/gui/mainwin.cpp" line="242"/>
         <source>Shows the Jaguar OP browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="232"/>
+        <location filename="src/gui/mainwin.cpp" line="246"/>
         <source>68K Listing Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="233"/>
+        <location filename="src/gui/mainwin.cpp" line="247"/>
         <source>Shows the 68K disassembly browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="237"/>
+        <location filename="src/gui/mainwin.cpp" line="251"/>
         <source>RISC Listing Browser</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="238"/>
+        <location filename="src/gui/mainwin.cpp" line="252"/>
         <source>Shows the RISC disassembly browser window</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="248"/>
+        <location filename="src/gui/mainwin.cpp" line="262"/>
         <source>&amp;Jaguar</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="259"/>
-        <location filename="src/gui/mainwin.cpp" line="289"/>
+        <location filename="src/gui/mainwin.cpp" line="273"/>
+        <location filename="src/gui/mainwin.cpp" line="304"/>
         <source>&amp;Debug</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="267"/>
+        <location filename="src/gui/mainwin.cpp" line="281"/>
         <source>&amp;Help</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="271"/>
+        <location filename="src/gui/mainwin.cpp" line="285"/>
         <source>Stuff</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="298"/>
+        <location filename="src/gui/mainwin.cpp" line="322"/>
         <source>Ready</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="src/gui/mainwin.cpp" line="575"/>
-        <location filename="src/gui/mainwin.cpp" line="588"/>
+        <location filename="src/gui/mainwin.cpp" line="617"/>
+        <location filename="src/gui/mainwin.cpp" line="630"/>
         <source>Could not load file &quot;%1&quot;!</source>
         <translation type="unfinished"></translation>
     </message>