diff --git a/src/driver.h b/src/driver.h index 9987643c..7838369f 100644 --- a/src/driver.h +++ b/src/driver.h @@ -142,6 +142,7 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall); //Sets the base directory(save states, snapshots, etc. are saved in directories below this directory. void FCEUI_SetBaseDirectory(std::string const & dir); +const char *FCEUI_GetBaseDirectory(void); bool FCEUI_GetUserPaletteAvail(void); void FCEUI_SetUserPalette(uint8 *pal, int nEntries); diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index d855d141..89c75483 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -78,6 +78,8 @@ consoleWin_t::~consoleWin_t(void) { nes_shm->runEmulator = 0; + gameTimer->stop(); + if ( gamePadConfWin != NULL ) { gamePadConfWin->closeWindow(); diff --git a/src/drivers/Qt/GamePadConf.cpp b/src/drivers/Qt/GamePadConf.cpp index 24cfb88c..eee64188 100644 --- a/src/drivers/Qt/GamePadConf.cpp +++ b/src/drivers/Qt/GamePadConf.cpp @@ -1,35 +1,52 @@ // GamePadConf.cpp // +#include +#include + #include "Qt/GamePadConf.h" #include "Qt/main.h" +#include "Qt/dface.h" #include "Qt/input.h" #include "Qt/config.h" #include "Qt/keyscan.h" +#include "Qt/sdl-joystick.h" #include "Qt/fceuWrapper.h" //---------------------------------------------------- GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) : QDialog( parent ) { - QHBoxLayout *hbox1, *hbox2; + QHBoxLayout *hbox, *hbox1, *hbox2, *hbox3, *hbox4; + QVBoxLayout *vbox; QGridLayout *grid; QCheckBox *efs_chkbox, *udlr_chkbox; - QGroupBox *frame; - QPushButton *loadDefaultButton; + QGroupBox *frame1, *frame2; + QLabel *label; + QPushButton *newProfileButton; + QPushButton *saveProfileButton; + QPushButton *applyProfileButton; + QPushButton *removeProfileButton; QPushButton *clearAllButton; QPushButton *closebutton; QPushButton *clearButton[GAMEPAD_NUM_BUTTONS]; + InitJoysticks(); + portNum = 0; - configNo = 0; buttonConfigStatus = 1; + inputTimer = new QTimer( this ); + + connect( inputTimer, &QTimer::timeout, this, &GamePadConfDialog_t::updatePeriodic ); + setWindowTitle( tr("GamePad Config") ); hbox1 = new QHBoxLayout(); hbox2 = new QHBoxLayout(); + hbox3 = new QHBoxLayout(); + hbox4 = new QHBoxLayout(); - QLabel *label = new QLabel(tr("Port:")); + label = new QLabel(tr("Console Port:")); portSel = new QComboBox(); hbox1->addWidget( label ); hbox1->addWidget( portSel ); @@ -39,6 +56,85 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) portSel->addItem( tr("3"), 2 ); portSel->addItem( tr("4"), 3 ); + label = new QLabel(tr("Device:")); + devSel = new QComboBox(); + hbox2->addWidget( label ); + hbox2->addWidget( devSel ); + + devSel->addItem( tr("Keyboard"), -1 ); + + for (int i=0; iisConnected() ) + { + char stmp[128]; + sprintf( stmp, "%i: %s", i, js->getName() ); + devSel->addItem( tr(stmp), i ); + + } + } + } + for (int i=0; icount(); i++) + { + if ( devSel->itemData(i).toInt() == GamePad[portNum].getDeviceIndex() ) + { + devSel->setCurrentIndex( i ); + } + } + + label = new QLabel(tr("GUID:")); + guidLbl = new QLabel(); + + hbox3->addWidget( label ); + hbox3->addWidget( guidLbl ); + + guidLbl->setText( GamePad[portNum].getGUID() ); + + frame1 = new QGroupBox(tr("Mapping Profile:")); + //grid = new QGridLayout(); + vbox = new QVBoxLayout(); + + //frame1->setLayout( grid ); + frame1->setLayout( vbox ); + + hbox = new QHBoxLayout(); + vbox->addLayout( hbox ); + + mapSel = new QComboBox(); + hbox->addWidget( mapSel ); + + mapSel->setWhatsThis( tr("Combo box for selection of a saved button mapping profile for the selected device")); + mapSel->addItem( tr("default"), 0 ); + + hbox = new QHBoxLayout(); + vbox->addLayout( hbox ); + + applyProfileButton = new QPushButton( tr("Load") ); + applyProfileButton->setWhatsThis(tr("Sets Current Active Map to the Selected Profile")); + hbox->addWidget( applyProfileButton ); + + saveProfileButton = new QPushButton( tr("Save") ); + saveProfileButton->setWhatsThis(tr("Stores Current Active Map to the Selected Profile")); + hbox->addWidget( saveProfileButton ); + + hbox = new QHBoxLayout(); + vbox->addLayout( hbox ); + + newProfileButton = new QPushButton( tr("New") ); + newProfileButton->setWhatsThis(tr("Create a New Map Profile")); + hbox->addWidget( newProfileButton ); + + removeProfileButton = new QPushButton( tr("Delete") ); + removeProfileButton->setWhatsThis(tr("Deletes the Selected Map Profile")); + hbox->addWidget( removeProfileButton ); + + mapMsg = new QLabel(); + vbox->addWidget(mapMsg); + efs_chkbox = new QCheckBox( tr("Enable Four Score") ); udlr_chkbox = new QCheckBox( tr("Allow Up+Down/Left+Right") ); @@ -50,13 +146,12 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) g_config->getOption("SDL.Input.EnableOppositeDirectionals", &opposite_dirs); udlr_chkbox->setChecked( opposite_dirs ); - frame = new QGroupBox(tr("Buttons:")); - grid = new QGridLayout(); + frame2 = new QGroupBox(tr("Current Active Button Mappings:")); + grid = new QGridLayout(); grid-> setHorizontalSpacing(50); - //frame->setFrameStyle( QFrame::Box ); - frame->setLayout( grid ); + frame2->setLayout( grid ); for (int i=0; iaddWidget( buttonName , i, 0, Qt::AlignCenter ); grid->addWidget( keyName[i] , i, 1, Qt::AlignCenter ); - grid->addWidget( button[i] , i, 2, Qt::AlignCenter ); - grid->addWidget( clearButton[i], i, 3, Qt::AlignCenter ); + grid->addWidget( label , i, 2, Qt::AlignCenter ); + grid->addWidget( keyState[i] , i, 3, Qt::AlignCenter ); + grid->addWidget( button[i] , i, 4, Qt::AlignCenter ); + grid->addWidget( clearButton[i], i, 5, Qt::AlignCenter ); } updateCntrlrDpy(); - loadDefaultButton = new QPushButton(tr("Load Defaults")); clearAllButton = new QPushButton(tr("Clear All")); closebutton = new QPushButton(tr("Close")); - hbox2->addWidget( loadDefaultButton ); - hbox2->addWidget( clearAllButton ); - hbox2->addWidget( closebutton ); + hbox4->addWidget( clearAllButton ); + hbox4->addWidget( closebutton ); connect(button[0], SIGNAL(clicked()), this, SLOT(changeButton0(void)) ); connect(button[1], SIGNAL(clicked()), this, SLOT(changeButton1(void)) ); @@ -111,29 +208,41 @@ GamePadConfDialog_t::GamePadConfDialog_t(QWidget *parent) connect(clearButton[8], SIGNAL(clicked()), this, SLOT(clearButton8(void)) ); connect(clearButton[9], SIGNAL(clicked()), this, SLOT(clearButton9(void)) ); - connect(loadDefaultButton, SIGNAL(clicked()), this, SLOT(loadDefaults(void)) ); + connect(newProfileButton , SIGNAL(clicked()), this, SLOT(newProfileCallback(void)) ); + connect(applyProfileButton , SIGNAL(clicked()), this, SLOT(loadProfileCallback(void)) ); + connect(saveProfileButton , SIGNAL(clicked()), this, SLOT(saveProfileCallback(void)) ); + connect(removeProfileButton, SIGNAL(clicked()), this, SLOT(deleteProfileCallback(void)) ); + connect(clearAllButton , SIGNAL(clicked()), this, SLOT(clearAllCallback(void)) ); connect(closebutton , SIGNAL(clicked()), this, SLOT(closeWindow(void)) ); - connect(portSel , SIGNAL(activated(int)), this, SLOT(controllerSelect(int)) ); + connect(portSel , SIGNAL(activated(int)), this, SLOT(portSelect(int)) ); + connect(devSel , SIGNAL(activated(int)), this, SLOT(deviceSelect(int)) ); connect(efs_chkbox , SIGNAL(stateChanged(int)), this, SLOT(ena4score(int)) ); connect(udlr_chkbox, SIGNAL(stateChanged(int)), this, SLOT(oppDirEna(int)) ); QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->addLayout( hbox1 ); + mainLayout->addLayout( hbox2 ); + mainLayout->addLayout( hbox3 ); + mainLayout->addWidget( frame1 ); mainLayout->addWidget( efs_chkbox ); mainLayout->addWidget( udlr_chkbox ); - mainLayout->addWidget( frame ); - mainLayout->addLayout( hbox2 ); + mainLayout->addWidget( frame2 ); + mainLayout->addLayout( hbox4 ); setLayout( mainLayout ); + inputTimer->start( 33 ); // 30hz + + loadMapList(); } //---------------------------------------------------- GamePadConfDialog_t::~GamePadConfDialog_t(void) { + inputTimer->stop(); buttonConfigStatus = 0; } void GamePadConfDialog_t::keyPressEvent(QKeyEvent *event) @@ -148,30 +257,139 @@ void GamePadConfDialog_t::keyReleaseEvent(QKeyEvent *event) pushKeyEvent( event, 0 ); } //---------------------------------------------------- +void GamePadConfDialog_t::loadMapList(void) +{ + QDir dir; + QStringList filters, fileList; + const char *baseDir = FCEUI_GetBaseDirectory(); + const char *guid; + std::string path; + std::string prefix, mapName; + int index, devIdx; + jsDev_t *js; + size_t n=0; + char stmp[256]; + + index = devSel->currentIndex(); + devIdx = devSel->itemData(index).toInt(); + + if ( devIdx < 0 ) + { + guid = "keyboard"; + } + else + { + js = getJoystickDevice( devIdx ); + + guid = js->getGUID(); + } + + if ( guid == NULL ) + { + return; + } + + path = std::string(baseDir) + "/input/" + std::string(guid); + + dir.setPath( QString::fromStdString(path) ); + + filters << "*.txt"; + dir.setNameFilters(filters); + + fileList = dir.entryList( filters, QDir::Files, QDir::NoSort ); + + sprintf( stmp, "SDL.Input.GamePad.%u.", portNum ); + prefix = stmp; + + g_config->getOption(prefix + "Profile", &mapName ); + + mapSel->clear(); + mapSel->addItem( tr("default"), 0 ); n=1; + + for (size_t i=0; i < fileList.size(); i++) + { + size_t suffixIdx; + std::string fileName = fileList[i].toStdString(); + + suffixIdx = fileName.find_last_of('.'); + + fileName.erase( suffixIdx ); + + //printf("File: %s \n", fileName.c_str() ); + // + + if ( fileName.compare("default") == 0 ) continue; + + mapSel->addItem( tr(fileName.c_str()), (int)i+1 ); + + if ( mapName.compare( fileName ) == 0 ) + { + mapSel->setCurrentIndex(n); + } + n++; + } +} +//---------------------------------------------------- void GamePadConfDialog_t::updateCntrlrDpy(void) { char keyNameStr[128]; for (int i=0; isetText( tr(keyNameStr) ); } } //---------------------------------------------------- -void GamePadConfDialog_t::controllerSelect(int index) +void GamePadConfDialog_t::portSelect(int index) { //printf("Port Number:%i \n", index); portNum = index; updateCntrlrDpy(); + + for (int i=0; icount(); i++) + { + if ( devSel->itemData(i).toInt() == GamePad[portNum].getDeviceIndex() ) + { + devSel->setCurrentIndex( i ); + } + } + guidLbl->setText( GamePad[portNum].getGUID() ); + + loadMapList(); +} +//---------------------------------------------------- +void GamePadConfDialog_t::deviceSelect(int index) +{ + jsDev_t *js; + int devIdx = devSel->itemData(index).toInt(); + + js = getJoystickDevice( devIdx ); + + if ( js != NULL ) + { + if ( js->isConnected() ) + { + guidLbl->setText( js->getGUID() ); + } + } + else + { + guidLbl->setText(""); + } + GamePad[portNum].setDeviceIndex( devIdx ); + + loadMapList(); + + updateCntrlrDpy(); } //---------------------------------------------------- void GamePadConfDialog_t::ena4score(int state) @@ -190,8 +408,8 @@ void GamePadConfDialog_t::oppDirEna(int state) //---------------------------------------------------- void GamePadConfDialog_t::changeButton(int padNo, int x) { - char buf[256]; - std::string prefix; + //char buf[256]; + //std::string prefix; const char *keyNameStr; if ( buttonConfigStatus == 2 ) @@ -205,29 +423,9 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) button[x]->setText("Waiting" ); - snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); - prefix = buf; - DWaitButton (NULL, &GamePadConfig[padNo][x], configNo, &buttonConfigStatus ); + DWaitButton (NULL, &GamePad[padNo].bmap[x], &buttonConfigStatus ); - g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[padNo][x].ButtonNum[configNo]); - - if (GamePadConfig[padNo][x].ButtType[configNo] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePadConfig[padNo][x].ButtType[configNo] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePadConfig[padNo][x].DeviceNum[configNo]); - - keyNameStr = ButtonName( &GamePadConfig[padNo][x], configNo ); + keyNameStr = ButtonName( &GamePad[padNo].bmap[x] ); keyName[x]->setText( keyNameStr ); button[x]->setText("Change"); @@ -239,19 +437,9 @@ void GamePadConfDialog_t::changeButton(int padNo, int x) //---------------------------------------------------- void GamePadConfDialog_t::clearButton( int padNo, int x ) { - char buf[256]; - std::string prefix; - - GamePadConfig[padNo][x].ButtonNum[configNo] = -1; + GamePad[padNo].bmap[x].ButtonNum = -1; keyName[x]->setText(""); - - snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); - prefix = buf; - - g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[padNo][x].ButtonNum[configNo]); - } //---------------------------------------------------- void GamePadConfDialog_t::closeEvent(QCloseEvent *event) @@ -377,48 +565,150 @@ void GamePadConfDialog_t::clearAllCallback(void) } } //---------------------------------------------------- -void GamePadConfDialog_t::loadDefaults(void) +void GamePadConfDialog_t::saveConfig(void) { - char buf[256]; - std::string prefix; + char stmp[256]; + std::string prefix, mapName; - if ( portNum > 0 ) - { - clearAllCallback(); - return; - } + sprintf( stmp, "SDL.Input.GamePad.%u.", portNum ); + prefix = stmp; - snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", portNum); - prefix = buf; + mapName = mapSel->currentText().toStdString(); - for (int x=0; xsetOption(prefix + "DeviceGUID", GamePad[portNum].getGUID() ); + g_config->setOption(prefix + "Profile" , mapName.c_str() ); +} +//---------------------------------------------------- +void GamePadConfDialog_t::createNewProfile( const char *name ) +{ + printf("Creating: %s \n", name ); - g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[portNum][x].ButtonNum[configNo]); + GamePad[portNum].createProfile(name); + + mapSel->addItem( tr(name) ); +} +//---------------------------------------------------- +void GamePadConfDialog_t::newProfileCallback(void) +{ + int ret; + QInputDialog dialog(this); + + dialog.setWindowTitle( tr("New Profile") ); + dialog.setLabelText( tr("Specify New Profile Name") ); + dialog.setOkButtonText( tr("Create") ); + + dialog.show(); + ret = dialog.exec(); + + if ( QDialog::Accepted == ret ) + { + createNewProfile( dialog.textValue().toStdString().c_str() ); + } +} +//---------------------------------------------------- +void GamePadConfDialog_t::loadProfileCallback(void) +{ + char stmp[256]; + int index, devIdx, ret; + std::string mapName; + + index = devSel->currentIndex(); + devIdx = devSel->itemData(index).toInt(); + + mapName = mapSel->currentText().toStdString(); + + GamePad[portNum].setDeviceIndex( devIdx ); + + if ( mapName.compare("default") == 0 ) + { + ret =GamePad[portNum].loadDefaults(); + } + else + { + ret = GamePad[portNum].loadProfile( mapName.c_str() ); + } + if ( ret == 0 ) + { + saveConfig(); + + sprintf( stmp, "Mapping Loaded: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Load Mapping: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + mapMsg->setText( tr(stmp) ); - if (GamePadConfig[portNum][x].ButtType[configNo] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePadConfig[portNum][x].ButtType[configNo] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePadConfig[portNum][x].DeviceNum[configNo]); - } updateCntrlrDpy(); } //---------------------------------------------------- +void GamePadConfDialog_t::saveProfileCallback(void) +{ + int ret; + std::string mapName; + char stmp[256]; + + mapName = mapSel->currentText().toStdString(); + + ret = GamePad[portNum].saveCurrentMapToFile( mapName.c_str() ); + + if ( ret == 0 ) + { + saveConfig(); + + sprintf( stmp, "Mapping Saved: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Save Mapping: %s \n", mapName.c_str() ); + } + mapMsg->setText( tr(stmp) ); + +} +//---------------------------------------------------- +void GamePadConfDialog_t::deleteProfileCallback(void) +{ + int ret; + std::string mapName; + char stmp[256]; + + mapName = mapSel->currentText().toStdString(); + + ret = GamePad[portNum].deleteMapping( mapName.c_str() ); + + if ( ret == 0 ) + { + sprintf( stmp, "Mapping Deleted: %s/%s \n", GamePad[portNum].getGUID(), mapName.c_str() ); + } + else + { + sprintf( stmp, "Error: Failed to Delete Mapping: %s \n", mapName.c_str() ); + } + mapMsg->setText( tr(stmp) ); + + loadMapList(); +} +//---------------------------------------------------- +void GamePadConfDialog_t::updatePeriodic(void) +{ + for (int i=0; isetText( tr(txt) ); + keyState[i]->setStyleSheet( style ); + } +} +//---------------------------------------------------- GamePadConfigButton_t::GamePadConfigButton_t(int i) { idx = i; diff --git a/src/drivers/Qt/GamePadConf.h b/src/drivers/Qt/GamePadConf.h index 0f83000c..ba24b463 100644 --- a/src/drivers/Qt/GamePadConf.h +++ b/src/drivers/Qt/GamePadConf.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "Qt/main.h" @@ -37,12 +38,18 @@ class GamePadConfDialog_t : public QDialog ~GamePadConfDialog_t(void); protected: + QTimer *inputTimer; QComboBox *portSel; + QComboBox *devSel; + QComboBox *mapSel; + QComboBox *profSel; + QLabel *guidLbl; + QLabel *mapMsg; QLabel *keyName[GAMEPAD_NUM_BUTTONS]; + QLabel *keyState[GAMEPAD_NUM_BUTTONS]; GamePadConfigButton_t *button[GAMEPAD_NUM_BUTTONS]; int portNum; - int configNo; int buttonConfigStatus; void changeButton( int port, int button ); @@ -52,6 +59,9 @@ class GamePadConfDialog_t : public QDialog void closeEvent(QCloseEvent *bar); private: void updateCntrlrDpy(void); + void createNewProfile( const char *name ); + void loadMapList(void); + void saveConfig(void); public slots: void closeWindow(void); @@ -77,9 +87,14 @@ class GamePadConfDialog_t : public QDialog void clearButton8(void); void clearButton9(void); void clearAllCallback(void); - void loadDefaults(void); void ena4score(int state); void oppDirEna(int state); - void controllerSelect(int index); + void portSelect(int index); + void deviceSelect(int index); + void newProfileCallback(void); + void loadProfileCallback(void); + void saveProfileCallback(void); + void deleteProfileCallback(void); + void updatePeriodic(void); }; diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index cd927b8d..f0d54880 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -102,20 +102,20 @@ LoadCPalette(const std::string &file) static void CreateDirs(const std::string &dir) { - const char *subs[8]={"fcs","snaps","gameinfo","sav","cheats","movies","cfg.d"}; + const char *subs[9]={"fcs","snaps","gameinfo","sav","cheats","movies","input"}; std::string subdir; int x; #if defined(WIN32) || defined(NEED_MINGW_HACKS) mkdir(dir.c_str()); chmod(dir.c_str(), 755); - for(x = 0; x < 6; x++) { + for(x = 0; x < 7; x++) { subdir = dir + PSS + subs[x]; mkdir(subdir.c_str()); } #else mkdir(dir.c_str(), S_IRWXU); - for(x = 0; x < 6; x++) { + for(x = 0; x < 7; x++) { subdir = dir + PSS + subs[x]; mkdir(subdir.c_str(), S_IRWXU); } @@ -242,7 +242,7 @@ InitConfig() config->addOption("input4", "SDL.Input.3", "Gamepad.3"); // allow for input configuration - config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg); + //config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg); // display input config->addOption("inputdisplay", "SDL.InputDisplay", 0); @@ -317,10 +317,8 @@ InitConfig() prefix = buf; config->addOption(prefix + "DeviceType", DefaultGamePadDevice[i]); - config->addOption(prefix + "DeviceNum", 0); - for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) { - config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]); - } + config->addOption(prefix + "DeviceGUID", ""); + config->addOption(prefix + "Profile" , ""); } // PowerPad 0 - 1 diff --git a/src/drivers/Qt/dface.h b/src/drivers/Qt/dface.h index 2f3890ec..12c515ee 100644 --- a/src/drivers/Qt/dface.h +++ b/src/drivers/Qt/dface.h @@ -18,6 +18,8 @@ void SilenceSound(int s); /* DOS and SDL */ int InitJoysticks(void); int KillJoysticks(void); +int AddJoystick( int which ); +int RemoveJoystick( int which ); uint32 *GetJSOr(void); int InitVideo(FCEUGI *gi); diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index b65d723d..0d5f18a7 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -414,6 +414,7 @@ static void ShowUsage(const char *prog) int fceuWrapperInit( int argc, char *argv[] ) { int error; + std::string s; for (int i=0; isave(); } - std::string s; - g_config->getOption("SDL.InputCfg", &s); + //g_config->getOption("SDL.InputCfg", &s); - if (s.size() != 0) - { - InitVideo(GameInfo); - InputCfg(s); - } + //if (s.size() != 0) + //{ + // InitVideo(GameInfo); + // InputCfg(s); + //} // update the input devices UpdateInput(g_config); diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp index 552f7ad8..ce2bf93b 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -24,8 +24,9 @@ #include "Qt/config.h" -#include "Qt/sdl-video.h" #include "Qt/sdl.h" +#include "Qt/sdl-video.h" +#include "Qt/sdl-joystick.h" #include "common/cheat.h" #include "../../movie.h" @@ -49,8 +50,8 @@ extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay; /* UsrInputType[] is user-specified. CurInputType[] is current (game loading can override user settings) */ -static int UsrInputType[NUM_INPUT_DEVICES]; -static int CurInputType[NUM_INPUT_DEVICES]; +static int UsrInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE }; +static int CurInputType[NUM_INPUT_DEVICES] = { SI_GAMEPAD, SI_GAMEPAD, SI_NONE }; static int cspec = 0; static int buttonConfigInProgress = 0; @@ -956,6 +957,12 @@ UpdatePhysicalInput () g_keyState[ event.key.keysym.scancode ] = (event.type == SDL_KEYDOWN) ? 1 : 0; //checkKeyBoardState( event.key.keysym.scancode ); break; + case SDL_JOYDEVICEADDED: + AddJoystick( event.jdevice.which ); + break; + case SDL_JOYDEVICEREMOVED: + RemoveJoystick( event.jdevice.which ); + break; default: break; } @@ -964,8 +971,6 @@ UpdatePhysicalInput () } -static int bcpv=0, bcpj=0; - /** * Begin configuring the buttons by placing the video and joystick * subsystems into a well-known state. Button configuration really @@ -973,13 +978,7 @@ static int bcpv=0, bcpj=0; */ int ButtonConfigBegin () { - // shut down the joystick subsystems - //SDL_Surface *screen; - - bcpj = KillJoysticks (); - - // XXX soules - why did we shut this down? - // initialize the joystick subsystem + // initialize the joystick subsystem (if not already inited) InitJoysticks (); buttonConfigInProgress = 1; @@ -995,18 +994,6 @@ int ButtonConfigBegin () void ButtonConfigEnd () { - // shutdown the joystick and video subsystems - KillJoysticks (); - //SDL_QuitSubSystem(SDL_INIT_VIDEO); - - // re-initialize joystick and video subsystems if they were active before - /*if(!bcpv) { - InitVideo(GameInfo); - } */ - if (!bcpj) - { - InitJoysticks (); - } buttonConfigInProgress = 0; } @@ -1016,49 +1003,50 @@ ButtonConfigEnd () static int DTestButton (ButtConfig * bc) { - int x; - for (x = 0; x < bc->NumC; x++) + if (bc->ButtType == BUTTC_KEYBOARD) { - if (bc->ButtType[x] == BUTTC_KEYBOARD) + if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum)]) { - if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum[x])]) - { - return 1; - } + bc->state = 1; + return 1; } - else if (bc->ButtType[x] == BUTTC_JOYSTICK) + else + { + bc->state = 0; + } + } + else if (bc->ButtType == BUTTC_JOYSTICK) + { + if (DTestButtonJoy (bc)) { - if (DTestButtonJoy (bc)) - { - return 1; - } + return 1; } } return 0; } -#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1} -#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2} -#define MKZ() {{0},{0},{-1},0} +#define MK(x) {BUTTC_KEYBOARD,0,MKK(x),0} +//#define MK2(x1,x2) {BUTTC_KEYBOARD,0,MKK(x1)} +#define MKZ() {0,0,-1,0} #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} -ButtConfig GamePadConfig[ GAMEPAD_NUM_DEVICES ][ GAMEPAD_NUM_BUTTONS ] = -{ -/* Gamepad 1 */ - {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER), - MK (w), MK (z), MK (a), MK (s), MKZ (), MKZ ()}, - - /* Gamepad 2 */ - GPZ (), - - /* Gamepad 3 */ - GPZ (), - - /* Gamepad 4 */ - GPZ () -}; +//ButtConfig GamePadConfig[ GAMEPAD_NUM_DEVICES ][ GAMEPAD_NUM_BUTTONS ] = +//{ +///* Gamepad 1 */ +// {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER), +// MK (w), MK (z), MK (a), MK (s), MKZ (), MKZ ()}, +// +// /* Gamepad 2 */ +// GPZ (), +// +// /* Gamepad 3 */ +// GPZ (), +// +// /* Gamepad 4 */ +// GPZ () +//}; /** * Update the status of the gamepad input devices. @@ -1090,7 +1078,7 @@ UpdateGamepad(void) // a, b, select, start, up, down, left, right for (x = 0; x < 8; x++) { - if (DTestButton (&GamePadConfig[wg][x])) + if (DTestButton (&GamePad[wg].bmap[x])) { //printf("GamePad%i Button Hit: %i \n", wg, x ); if(opposite_dirs == 0) @@ -1128,7 +1116,7 @@ UpdateGamepad(void) { for (x = 0; x < 2; x++) { - if (DTestButton (&GamePadConfig[wg][8 + x])) + if (DTestButton (&GamePad[wg].bmap[8 + x])) { JS |= (1 << x) << (wg << 3); } @@ -1563,42 +1551,42 @@ UpdateFTrainer () * @param bc the NES gamepad's button config * @param which the index of the button */ -const char * ButtonName (const ButtConfig * bc, int which) +const char * ButtonName (const ButtConfig * bc) { static char name[256]; name[0] = 0; - if (bc->ButtonNum[which] == -1) + if (bc->ButtonNum == -1) { return name; } - switch (bc->ButtType[which]) + switch (bc->ButtType) { case BUTTC_KEYBOARD: - return SDL_GetKeyName (bc->ButtonNum[which]); + return SDL_GetKeyName (bc->ButtonNum); break; case BUTTC_JOYSTICK: { int joyNum, inputNum; const char *inputType, *inputDirection; - joyNum = bc->DeviceNum[which]; + joyNum = bc->DeviceNum; - if (bc->ButtonNum[which] & 0x8000) + if (bc->ButtonNum & 0x8000) { inputType = "Axis"; - inputNum = bc->ButtonNum[which] & 0x3FFF; - inputDirection = bc->ButtonNum[which] & 0x4000 ? "-" : "+"; + inputNum = bc->ButtonNum & 0x3FFF; + inputDirection = bc->ButtonNum & 0x4000 ? "-" : "+"; } - else if (bc->ButtonNum[which] & 0x2000) + else if (bc->ButtonNum & 0x2000) { int inputValue; char direction[128] = ""; inputType = "Hat"; - inputNum = (bc->ButtonNum[which] >> 8) & 0x1F; - inputValue = bc->ButtonNum[which] & 0xF; + inputNum = (bc->ButtonNum >> 8) & 0x1F; + inputValue = bc->ButtonNum & 0xF; if (inputValue & SDL_HAT_UP) strncat (direction, "Up ", sizeof (direction)-1); @@ -1617,7 +1605,7 @@ const char * ButtonName (const ButtConfig * bc, int which) else { inputType = "Button"; - inputNum = bc->ButtonNum[which]; + inputNum = bc->ButtonNum; inputDirection = ""; } sprintf( name, "js%i:%s%i%s", joyNum, inputType, inputNum, inputDirection ); @@ -1632,7 +1620,7 @@ const char * ButtonName (const ButtConfig * bc, int which) * Waits for a button input and returns the information as to which * button was pressed. Used in button configuration. */ -int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfigStatus ) +int DWaitButton (const uint8_t * text, ButtConfig * bc, int *buttonConfigStatus ) { SDL_Event event; static int32 LastAx[64][64]; @@ -1684,23 +1672,23 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi { case SDL_KEYDOWN: //printf("SDL KeyDown:%i \n", event.key.keysym.sym ); - bc->ButtType[wb] = BUTTC_KEYBOARD; - bc->DeviceNum[wb] = 0; - bc->ButtonNum[wb] = event.key.keysym.sym; + bc->ButtType = BUTTC_KEYBOARD; + bc->DeviceNum = 0; + bc->ButtonNum = event.key.keysym.sym; return (1); case SDL_JOYBUTTONDOWN: - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jbutton.which; - bc->ButtonNum[wb] = event.jbutton.button; + bc->ButtType = BUTTC_JOYSTICK; + bc->DeviceNum = event.jbutton.which; + bc->ButtonNum = event.jbutton.button; return (1); case SDL_JOYHATMOTION: if (event.jhat.value == SDL_HAT_CENTERED) done--; else { - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jhat.which; - bc->ButtonNum[wb] = + bc->ButtType = BUTTC_JOYSTICK; + bc->DeviceNum = event.jhat.which; + bc->ButtonNum = (0x2000 | ((event.jhat.hat & 0x1F) << 8) | event. jhat.value); return (1); @@ -1722,9 +1710,9 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi (LastAx[event.jaxis.which][event.jaxis.axis] - event.jaxis.value) >= 8192) { - bc->ButtType[wb] = BUTTC_JOYSTICK; - bc->DeviceNum[wb] = event.jaxis.which; - bc->ButtonNum[wb] = (0x8000 | event.jaxis.axis | + bc->ButtType = BUTTC_JOYSTICK; + bc->DeviceNum = event.jaxis.which; + bc->ButtonNum = (0x8000 | event.jaxis.axis | ((event.jaxis.value < 0) ? 0x4000 : 0)); return (1); @@ -1761,170 +1749,169 @@ int DWaitButton (const uint8_t * text, ButtConfig * bc, int wb, int *buttonConfi * used as input for the specified button, thus allowing up to four * possible settings for each input button. */ - void -ConfigButton (char *text, ButtConfig * bc) -{ - uint8 buf[256]; - int wc; - - for (wc = 0; wc < MAXBUTTCONFIG; wc++) - { - sprintf ((char *) buf, "%s (%d)", text, wc + 1); - DWaitButton (buf, bc, wc, NULL); - - if (wc && - bc->ButtType[wc] == bc->ButtType[wc - 1] && - bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] && - bc->ButtonNum[wc] == bc->ButtonNum[wc - 1]) - { - break; - } - } - bc->NumC = wc; -} +// void +//ConfigButton (char *text, ButtConfig * bc) +//{ +// uint8 buf[256]; +// int wc; +// +// for (wc = 0; wc < MAXBUTTCONFIG; wc++) +// { +// sprintf ((char *) buf, "%s (%d)", text, wc + 1); +// DWaitButton (buf, bc, wc, NULL); +// +// if (wc && +// bc->ButtType[wc] == bc->ButtType[wc - 1] && +// bc->DeviceNum[wc] == bc->DeviceNum[wc - 1] && +// bc->ButtonNum[wc] == bc->ButtonNum[wc - 1]) +// { +// break; +// } +// } +//} /** * Update the button configuration for a specified device. */ extern Config *g_config; -void ConfigDevice (int which, int arg) -{ - char buf[256]; - int x; - std::string prefix; - const char *str[10] = - { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A", - "Rapid B" - }; - - // XXX soules - set the configuration options so that later calls - // don't override these. This is a temp hack until I - // can clean up this file. - - ButtonConfigBegin (); - switch (which) - { - case FCFGD_QUIZKING: - prefix = "SDL.Input.QuizKing."; - for (x = 0; x < 6; x++) - { - sprintf (buf, "Quiz King Buzzer #%d", x + 1); - ConfigButton (buf, &QuizKingButtons[x]); - - g_config->setOption (prefix + QuizKingNames[x], - QuizKingButtons[x].ButtonNum[0]); - } - - if (QuizKingButtons[0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (QuizKingButtons[0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - QuizKingButtons[0].DeviceNum[0]); - break; - case FCFGD_HYPERSHOT: - prefix = "SDL.Input.HyperShot."; - for (x = 0; x < 4; x++) - { - sprintf (buf, "Hyper Shot %d: %s", - ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN"); - ConfigButton (buf, &HyperShotButtons[x]); - - g_config->setOption (prefix + HyperShotNames[x], - HyperShotButtons[x].ButtonNum[0]); - } - - if (HyperShotButtons[0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (HyperShotButtons[0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - HyperShotButtons[0].DeviceNum[0]); - break; - case FCFGD_POWERPAD: - snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1)); - prefix = buf; - for (x = 0; x < 12; x++) - { - sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11); - ConfigButton (buf, &powerpadsc[arg & 1][x]); - - g_config->setOption (prefix + PowerPadNames[x], - powerpadsc[arg & 1][x].ButtonNum[0]); - } - - if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (powerpadsc[arg & 1][0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - powerpadsc[arg & 1][0].DeviceNum[0]); - break; - - case FCFGD_GAMEPAD: - snprintf (buf, 256, "SDL.Input.GamePad.%d", arg); - prefix = buf; - for (x = 0; x < 10; x++) - { - sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]); - ConfigButton (buf, &GamePadConfig[arg][x]); - - g_config->setOption (prefix + GamePadNames[x], - GamePadConfig[arg][x].ButtonNum[0]); - } - - if (GamePadConfig[arg][0].ButtType[0] == BUTTC_KEYBOARD) - { - g_config->setOption (prefix + "DeviceType", "Keyboard"); - } - else if (GamePadConfig[arg][0].ButtType[0] == BUTTC_JOYSTICK) - { - g_config->setOption (prefix + "DeviceType", "Joystick"); - } - else - { - g_config->setOption (prefix + "DeviceType", "Unknown"); - } - g_config->setOption (prefix + "DeviceNum", - GamePadConfig[arg][0].DeviceNum[0]); - break; - } - - ButtonConfigEnd (); -} +//void ConfigDevice (int which, int arg) +//{ +// char buf[256]; +// int x; +// std::string prefix; +// const char *str[10] = +// { "A", "B", "SELECT", "START", "UP", "DOWN", "LEFT", "RIGHT", "Rapid A", +// "Rapid B" +// }; +// +// // XXX soules - set the configuration options so that later calls +// // don't override these. This is a temp hack until I +// // can clean up this file. +// +// ButtonConfigBegin (); +// switch (which) +// { +// case FCFGD_QUIZKING: +// prefix = "SDL.Input.QuizKing."; +// for (x = 0; x < 6; x++) +// { +// sprintf (buf, "Quiz King Buzzer #%d", x + 1); +// ConfigButton (buf, &QuizKingButtons[x]); +// +// g_config->setOption (prefix + QuizKingNames[x], +// QuizKingButtons[x].ButtonNum); +// } +// +// if (QuizKingButtons[0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (QuizKingButtons[0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// QuizKingButtons[0].DeviceNum); +// break; +// case FCFGD_HYPERSHOT: +// prefix = "SDL.Input.HyperShot."; +// for (x = 0; x < 4; x++) +// { +// sprintf (buf, "Hyper Shot %d: %s", +// ((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN"); +// ConfigButton (buf, &HyperShotButtons[x]); +// +// g_config->setOption (prefix + HyperShotNames[x], +// HyperShotButtons[x].ButtonNum); +// } +// +// if (HyperShotButtons[0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (HyperShotButtons[0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// HyperShotButtons[0].DeviceNum); +// break; +// case FCFGD_POWERPAD: +// snprintf (buf, 256, "SDL.Input.PowerPad.%d", (arg & 1)); +// prefix = buf; +// for (x = 0; x < 12; x++) +// { +// sprintf (buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11); +// ConfigButton (buf, &powerpadsc[arg & 1][x]); +// +// g_config->setOption (prefix + PowerPadNames[x], +// powerpadsc[arg & 1][x].ButtonNum); +// } +// +// if (powerpadsc[arg & 1][0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (powerpadsc[arg & 1][0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// powerpadsc[arg & 1][0].DeviceNum); +// break; +// +// case FCFGD_GAMEPAD: +// snprintf (buf, 256, "SDL.Input.GamePad.%d", arg); +// prefix = buf; +// for (x = 0; x < 10; x++) +// { +// sprintf (buf, "GamePad #%d: %s", arg + 1, str[x]); +// ConfigButton (buf, &GamePadConfig[arg][x]); +// +// g_config->setOption (prefix + GamePadNames[x], +// GamePadConfig[arg][x].ButtonNum); +// } +// +// if (GamePadConfig[arg][0].ButtType == BUTTC_KEYBOARD) +// { +// g_config->setOption (prefix + "DeviceType", "Keyboard"); +// } +// else if (GamePadConfig[arg][0].ButtType == BUTTC_JOYSTICK) +// { +// g_config->setOption (prefix + "DeviceType", "Joystick"); +// } +// else +// { +// g_config->setOption (prefix + "DeviceType", "Unknown"); +// } +// g_config->setOption (prefix + "DeviceNum", +// GamePadConfig[arg][0].DeviceNum); +// break; +// } +// +// ButtonConfigEnd (); +//} /** * Update the button configuration for a device, specified by a text string. */ -void InputCfg (const std::string & text) -{ - +//void InputCfg (const std::string & text) +//{ +// // if (noGui) // { // if (text.find ("gamepad") != std::string::npos) @@ -1960,8 +1947,8 @@ void InputCfg (const std::string & text) // } // else // printf ("Please run \"fceux --nogui\" before using --inputcfg\n"); - -} +// +//} /** @@ -1973,7 +1960,9 @@ void InputCfg (const std::string & text) UpdateInput (Config * config) { char buf[64]; - std::string device, prefix; + std::string device, prefix, guid, mapping; + + InitJoysticks(); for (unsigned int i = 0; i < 3; i++) { @@ -2066,37 +2055,18 @@ UpdateInput (Config * config) snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%u.", i); prefix = buf; - config->getOption (prefix + "DeviceType", &device); - if (device.find ("Keyboard") != std::string::npos) - { - type = BUTTC_KEYBOARD; - } - else if (device.find ("Joystick") != std::string::npos) - { - type = BUTTC_JOYSTICK; - } - else - { - type = 0; - } + config->getOption (prefix + "DeviceType", &device ); + config->getOption (prefix + "DeviceGUID", &guid ); + config->getOption (prefix + "Profile" , &mapping); - config->getOption (prefix + "DeviceNum", &devnum); - for (unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) - { - config->getOption (prefix + GamePadNames[j], &button); - - GamePadConfig[i][j].ButtType[0] = type; - GamePadConfig[i][j].DeviceNum[0] = devnum; - GamePadConfig[i][j].ButtonNum[0] = button; - GamePadConfig[i][j].NumC = 1; - } + GamePad[i].init( i, guid.c_str(), mapping.c_str() ); } // PowerPad 0 - 1 for (unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { char buf[64]; - snprintf (buf, 32, "SDL.Input.PowerPad.%u.", i); + snprintf (buf, sizeof(buf)-1, "SDL.Input.PowerPad.%u.", i); prefix = buf; config->getOption (prefix + "DeviceType", &device); @@ -2118,10 +2088,9 @@ UpdateInput (Config * config) { config->getOption (prefix + PowerPadNames[j], &button); - powerpadsc[i][j].ButtType[0] = type; - powerpadsc[i][j].DeviceNum[0] = devnum; - powerpadsc[i][j].ButtonNum[0] = button; - powerpadsc[i][j].NumC = 1; + powerpadsc[i][j].ButtType = type; + powerpadsc[i][j].DeviceNum = devnum; + powerpadsc[i][j].ButtonNum = button; } } @@ -2145,10 +2114,9 @@ UpdateInput (Config * config) { config->getOption (prefix + QuizKingNames[j], &button); - QuizKingButtons[j].ButtType[0] = type; - QuizKingButtons[j].DeviceNum[0] = devnum; - QuizKingButtons[j].ButtonNum[0] = button; - QuizKingButtons[j].NumC = 1; + QuizKingButtons[j].ButtType = type; + QuizKingButtons[j].DeviceNum = devnum; + QuizKingButtons[j].ButtonNum = button; } // HyperShot @@ -2171,10 +2139,9 @@ UpdateInput (Config * config) { config->getOption (prefix + HyperShotNames[j], &button); - HyperShotButtons[j].ButtType[0] = type; - HyperShotButtons[j].DeviceNum[0] = devnum; - HyperShotButtons[j].ButtonNum[0] = button; - HyperShotButtons[j].NumC = 1; + HyperShotButtons[j].ButtType = type; + HyperShotButtons[j].DeviceNum = devnum; + HyperShotButtons[j].ButtonNum = button; } // Mahjong @@ -2197,10 +2164,9 @@ UpdateInput (Config * config) { config->getOption (prefix + MahjongNames[j], &button); - MahjongButtons[j].ButtType[0] = type; - MahjongButtons[j].DeviceNum[0] = devnum; - MahjongButtons[j].ButtonNum[0] = button; - MahjongButtons[j].NumC = 1; + MahjongButtons[j].ButtType = type; + MahjongButtons[j].DeviceNum = devnum; + MahjongButtons[j].ButtonNum = button; } // TopRider @@ -2223,10 +2189,9 @@ UpdateInput (Config * config) { config->getOption (prefix + TopRiderNames[j], &button); - TopRiderButtons[j].ButtType[0] = type; - TopRiderButtons[j].DeviceNum[0] = devnum; - TopRiderButtons[j].ButtonNum[0] = button; - TopRiderButtons[j].NumC = 1; + TopRiderButtons[j].ButtType = type; + TopRiderButtons[j].DeviceNum = devnum; + TopRiderButtons[j].ButtonNum = button; } // FTrainer @@ -2249,10 +2214,9 @@ UpdateInput (Config * config) { config->getOption (prefix + FTrainerNames[j], &button); - FTrainerButtons[j].ButtType[0] = type; - FTrainerButtons[j].DeviceNum[0] = devnum; - FTrainerButtons[j].ButtonNum[0] = button; - FTrainerButtons[j].NumC = 1; + FTrainerButtons[j].ButtType = type; + FTrainerButtons[j].DeviceNum = devnum; + FTrainerButtons[j].ButtonNum = button; } // FamilyKeyBoard @@ -2275,10 +2239,9 @@ UpdateInput (Config * config) { config->getOption (prefix + FamilyKeyBoardNames[j], &button); - fkbmap[j].ButtType[0] = type; - fkbmap[j].DeviceNum[0] = devnum; - fkbmap[j].ButtonNum[0] = button; - fkbmap[j].NumC = 1; + fkbmap[j].ButtType = type; + fkbmap[j].DeviceNum = devnum; + fkbmap[j].ButtonNum = button; } } diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h index d9a70118..07dc1d04 100644 --- a/src/drivers/Qt/input.h +++ b/src/drivers/Qt/input.h @@ -5,7 +5,7 @@ #include "common/configSys.h" -#define MAXBUTTCONFIG 4 +//#define MAXBUTTCONFIG 4 enum { BUTTC_KEYBOARD = 0, @@ -14,14 +14,14 @@ enum { }; struct ButtConfig { - int ButtType[MAXBUTTCONFIG]; - int DeviceNum[MAXBUTTCONFIG]; - int ButtonNum[MAXBUTTCONFIG]; - uint32_t NumC; + int ButtType; //[MAXBUTTCONFIG]; + int DeviceNum; //[MAXBUTTCONFIG]; + int ButtonNum; //[MAXBUTTCONFIG]; + int state; + //uint32_t NumC; //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ }; - extern int NoWaiting; extern CFGSTRUCT InputConfig[]; extern ARGPSTRUCT InputArgs[]; @@ -32,7 +32,7 @@ int getKeyState( int k ); int ButtonConfigBegin(); void ButtonConfigEnd(); void ConfigButton(char *text, ButtConfig *bc); -int DWaitButton(const uint8_t *text, ButtConfig *bc, int wb, int *buttonConfigStatus = NULL); +int DWaitButton(const uint8_t *text, ButtConfig *bc, int *buttonConfigStatus = NULL); #define FCFGD_GAMEPAD 1 @@ -46,7 +46,7 @@ void InitInputInterface(void); void InputUserActiveFix(void); extern bool replaceP2StartWithMicrophone; -extern ButtConfig GamePadConfig[4][10]; +//extern ButtConfig GamePadConfig[4][10]; //extern ButtConfig powerpadsc[2][12]; //extern ButtConfig QuizKingButtons[6]; //extern ButtConfig FTrainerButtons[12]; @@ -59,9 +59,9 @@ int DTestButtonJoy(ButtConfig *bc); void FCEUD_UpdateInput(void); void UpdateInput(Config *config); -void InputCfg(const std::string &); +//void InputCfg(const std::string &); std::string GetUserText(const char* title); -const char* ButtonName(const ButtConfig* bc, int which); +const char* ButtonName(const ButtConfig* bc); #endif diff --git a/src/drivers/Qt/sdl-joystick.cpp b/src/drivers/Qt/sdl-joystick.cpp index 71148b2e..57c2f616 100644 --- a/src/drivers/Qt/sdl-joystick.cpp +++ b/src/drivers/Qt/sdl-joystick.cpp @@ -22,106 +22,1018 @@ /// \file /// \brief Handles joystick input using the SDL. +#include #include "Qt/sdl.h" +#include "Qt/sdl-joystick.h" #include #include #include #include -#define MAX_JOYSTICKS 32 -static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL}; +//#define MAX_JOYSTICKS 32 +// Public Variables +GamePad_t GamePad[4]; + +// Static Functions +static int sdlButton2NesGpIdx( const char *id ); + +// Static Variables static int s_jinited = 0; +static const char *buttonNames[ GAMEPAD_NUM_BUTTONS ] = +{ + "a", "b","back","start", + "dpup","dpdown","dpleft","dpright", + "turboA","turboB" +}; +//******************************************************************************** +// Joystick Device +jsDev_t::jsDev_t(void) +{ + js = NULL; + gc = NULL; + devIdx = 0; + portBindMask = 0; +}; + +//******************************************************************************** +int jsDev_t::close(void) +{ + if ( gc ) + { + SDL_GameControllerClose( gc ); gc = NULL; js = NULL; + } + else + { + if ( js ) + { + SDL_JoystickClose( js ); js = NULL; + } + } + return 0; +} + +//******************************************************************************** +SDL_Joystick *jsDev_t::getJS(void) +{ + return js; +} + +//******************************************************************************** +const char *jsDev_t::getName(void) +{ + return ( name.c_str() ); +} + +//******************************************************************************** +const char *jsDev_t::getGUID(void) +{ + return ( guidStr.c_str() ); +} + +//******************************************************************************** +int jsDev_t::bindPort( int idx ) +{ + portBindMask |= (0x00000001 << idx); + + return portBindMask; +} +//******************************************************************************** +int jsDev_t::unbindPort( int idx ) +{ + portBindMask &= ~(0x00000001 << idx); + + return portBindMask; +} +//******************************************************************************** +int jsDev_t::getBindPorts(void) +{ + return portBindMask; +} +//******************************************************************************** +bool jsDev_t::isGameController(void) +{ + return ( gc != NULL ); +} + +//******************************************************************************** +bool jsDev_t::isConnected(void) +{ + return ( (js != NULL) || (gc != NULL) ); +} + +//******************************************************************************** +void jsDev_t::init( int idx ) +{ + SDL_JoystickGUID guid; + char stmp[64]; + + devIdx = idx; + + if ( gc ) + { + js = SDL_GameControllerGetJoystick( gc ); + + guid = SDL_JoystickGetGUID( js ); + + name.assign( SDL_GameControllerName(gc) ); + } + else + { + guid = SDL_JoystickGetGUID( js ); + + name.assign( SDL_JoystickName(js) ); + } + SDL_JoystickGetGUIDString( guid, stmp, sizeof(stmp) ); + + guidStr.assign( stmp ); + +} + +void jsDev_t::print(void) +{ + char guidStr[64]; + + SDL_JoystickGUID guid = SDL_JoystickGetGUID( js ); + + SDL_JoystickGetGUIDString( guid, guidStr, sizeof(guidStr) ); + + printf("JoyStickID: %i: '%s' \n", + SDL_JoystickInstanceID( js ), SDL_JoystickName( js ) ); + printf("GUID: %s \n", guidStr ); + printf("NumAxes: %i \n", SDL_JoystickNumAxes(js) ); + printf("NumButtons: %i \n", SDL_JoystickNumButtons(js) ); + printf("NumHats: %i \n", SDL_JoystickNumHats(js) ); + + if ( gc ) + { + printf("GameController Name: '%s'\n", SDL_GameControllerName(gc) ); + printf("GameController Mapping: %s\n", SDL_GameControllerMapping(gc) ); + } +} + +static jsDev_t jsDev[ MAX_JOYSTICKS ]; + +//******************************************************************************** +nesGamePadMap_t::nesGamePadMap_t(void) +{ + clearMapping(); +} +//******************************************************************************** +nesGamePadMap_t::~nesGamePadMap_t(void) +{ + +} +//******************************************************************************** +void nesGamePadMap_t::clearMapping(void) +{ + guid[0] = 0; + name[0] = 0; + os[0] = 0; + for (int i=0; i= 0 ) + { + strcpy( btn[bIdx], val[i] ); + } + else if ( strcmp( id[i], "platform" ) == 0 ) + { + strcpy( os, val[i] ); + } + } + return 0; +} +//******************************************************************************** +GamePad_t::GamePad_t(void) +{ + devIdx = -1; + portNum = 0; + + for (int i=0; i= 0 ) + { + jsDev[ devIdx ].unbindPort( portNum ); + } + + devIdx = in; + + if ( devIdx >= 0 ) + { + jsDev[ devIdx ].bindPort( portNum ); + } + return 0; +} +//******************************************************************************** +const char *GamePad_t::getGUID(void) +{ + if ( devIdx < 0 ) + { + return "keyboard"; + } + if ( jsDev[ devIdx ].isConnected() ) + { + return jsDev[ devIdx ].getGUID(); + } + return NULL; +} +//******************************************************************************** +static int sdlButton2NesGpIdx( const char *id ) +{ + int i, idx = -1; + + for (i=0; ibtn[i][0] == 0) + { + continue; + } + if (gpm->btn[i][0] == 'k') + { + SDL_Keycode key; + + bmap[i].ButtType = BUTTC_KEYBOARD; + bmap[i].DeviceNum = -1; + + key = SDL_GetKeyFromName( &gpm->btn[i][1] ); + + if ( key != SDLK_UNKNOWN ) + { + bmap[i].ButtonNum = key; + } + else + { + bmap[i].ButtonNum = -1; + } + } + else if ( (gpm->btn[i][0] == 'b') && isdigit( gpm->btn[i][1] ) ) + { + bmap[i].ButtType = BUTTC_JOYSTICK; + bmap[i].DeviceNum = devIdx; + bmap[i].ButtonNum = atoi( &gpm->btn[i][1] ); + } + else if ( (gpm->btn[i][0] == 'h') && isdigit( gpm->btn[i][1] ) && + (gpm->btn[i][2] == '.') && isdigit( gpm->btn[i][3] ) ) + { + int hatIdx, hatVal; + + hatIdx = gpm->btn[i][1] - '0'; + hatVal = atoi( &gpm->btn[i][3] ); + + bmap[i].ButtType = BUTTC_JOYSTICK; + bmap[i].DeviceNum = devIdx; + bmap[i].ButtonNum = 0x2000 | ( (hatIdx & 0x1F) << 8) | (hatVal & 0xFF); + } + else if ( (gpm->btn[i][0] == 'a') || (gpm->btn[i][1] == 'a') ) + { + int l=0, axisIdx=0, axisSign=0; + + l=0; + if ( gpm->btn[i][l] == '-' ) + { + axisSign = 1; l++; + } + else if ( gpm->btn[i][l] == '+' ) + { + axisSign = 0; l++; + } + + if ( gpm->btn[i][l] == 'a' ) + { + l++; + } + if ( isdigit( gpm->btn[i][l] ) ) + { + axisIdx = atoi( &gpm->btn[i][l] ); + + while ( isdigit(gpm->btn[i][l]) ) l++; + } + if ( gpm->btn[i][l] == '-' ) + { + axisSign = 1; l++; + } + else if ( gpm->btn[i][l] == '+' ) + { + axisSign = 0; l++; + } + bmap[i].ButtType = BUTTC_JOYSTICK; + bmap[i].DeviceNum = devIdx; + bmap[i].ButtonNum = 0x8000 | (axisSign ? 0x4000 : 0) | (axisIdx & 0xFF); + } + } + return 0; +} +//******************************************************************************** +int GamePad_t::setMapping( const char *map ) +{ + nesGamePadMap_t gpm; + + gpm.parseMapping( map ); + setMapping( &gpm ); + + return 0; +} +//******************************************************************************** +int GamePad_t::getMapFromFile( const char *filename, char *out ) +{ + int i=0,j=0; + FILE *fp; + char line[256]; + + out[0] = 0; + + fp = ::fopen( filename, "r" ); + + if ( fp == NULL ) + { + return -1; + } + while ( fgets( line, sizeof(line), fp ) != 0 ) + { + i=0; + while (line[i] != 0) + { + if ( line[i] == '#' ) + { + line[i] = 0; break; + } + i++; + } + + if ( i < 32 ) continue; // need at least 32 chars for a valid line entry + + i=0; j=0; + while ( isspace(line[i]) ) i++; + + while ( line[i] != 0 ) + { + out[j] = line[i]; i++; j++; + } + out[j] = 0; + + if ( j < 34 ) continue; + + break; + } + + ::fclose(fp); + + return (j < 34); +} +//******************************************************************************** +int GamePad_t::getDefaultMap( char *out, const char *guid ) +{ + char txtMap[256]; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path; + + out[0] = 0; + + if ( devIdx < 0 ) + { + guid = "keyboard"; + } + if ( guid == NULL ) + { + if ( jsDev[ devIdx ].isConnected() ) + { + guid = jsDev[ devIdx ].getGUID(); + } + } + if ( guid == NULL ) + { + return -1; + } + + path = std::string(baseDir) + "/input/" + std::string(guid) + "/default.txt"; + + if ( getMapFromFile( path.c_str(), txtMap ) == 0 ) + { + printf("Using Mapping From File: %s\n", path.c_str() ); + strcpy( out, txtMap ); + return 0; + } + + if ( devIdx >= 0 ) + { + if ( jsDev[ devIdx ].gc ) + { + char *sdlMapping; + + sdlMapping = SDL_GameControllerMapping( jsDev[ devIdx ].gc ); + + if ( sdlMapping == NULL ) return -1; + + strcpy( out, sdlMapping ); + + SDL_free(sdlMapping); + + return 0; + } + } + else + { + if ( strcmp( guid, "keyboard" ) == 0 ) + { + for (int x=0; x= 0 ) + { + if ( !jsDev[devIdx].isConnected() ) + { + printf("Error: JS%i Not Connected\n", devIdx ); + return -1; + } + guid = jsDev[devIdx].getGUID(); + } + else + { + guid = "keyboard"; + } + path = std::string(baseDir) + "/input/" + std::string(guid); + + dir.mkpath( QString::fromStdString(path) ); + + path += "/" + std::string(name) + ".txt"; + + output.assign( guid ); + output.append( "," ); + output.append( name ); + output.append( "," ); + + for (i=0; i> 8) & 0x1F, bmap[i].ButtonNum & 0xFF ); + } + else if (bmap[i].ButtonNum & 0x8000) + { + /* Axis "button" */ + sprintf( stmp, "%ca%i", + (bmap[i].ButtonNum & 0x4000) ? '-' : '+', bmap[i].ButtonNum & 0x3FFF ); + } + else + { + /* Button */ + sprintf( stmp, "b%i", bmap[i].ButtonNum ); + } + } + output.append( buttonNames[i] ); + output.append( ":" ); + output.append( stmp ); + output.append( "," ); + } + + return saveMappingToFile( path.c_str(), output.c_str() ); +} +//******************************************************************************** +int GamePad_t::saveMappingToFile( const char *filename, const char *txtMap ) +{ + FILE *fp; + + fp = ::fopen(filename, "w"); + + if ( fp == NULL ) + { + return -1; + } + fprintf( fp, "%s\n", txtMap ); + + ::fclose(fp); + + return 0; +} +//******************************************************************************** +int GamePad_t::createProfile( const char *name ) +{ + char txtMap[256]; + const char *guid = NULL; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path; + QDir dir; + + if ( baseDir[0] == 0 ) + { + printf("Error: Invalid base directory\n"); + return -1; + } + if ( devIdx >= 0 ) + { + if ( !jsDev[devIdx].isConnected() ) + { + printf("Error: JS%i Not Connected\n", devIdx ); + return -1; + } + guid = jsDev[devIdx].getGUID(); + } + else + { + guid = "keyboard"; + } + path = std::string(baseDir) + "/input/" + std::string(guid); + + dir.mkpath( QString::fromStdString(path) ); + //printf("DIR: '%s'\n", path.c_str() ); + + path += "/" + std::string(name) + ".txt"; + + //printf("File: '%s'\n", path.c_str() ); + + getDefaultMap( txtMap, guid ); + + saveMappingToFile( path.c_str(), txtMap ); + + return 0; +} +//******************************************************************************** +int GamePad_t::deleteMapping( const char *name ) +{ + const char *guid = NULL; + const char *baseDir = FCEUI_GetBaseDirectory(); + std::string path; + + if ( baseDir[0] == 0 ) + { + printf("Error: Invalid base directory\n"); + return -1; + } + if ( devIdx >= 0 ) + { + if ( !jsDev[devIdx].isConnected() ) + { + printf("Error: JS%i Not Connected\n", devIdx ); + return -1; + } + guid = jsDev[devIdx].getGUID(); + } + else + { + guid = "keyboard"; + } + path = std::string(baseDir) + "/input/" + std::string(guid) + + "/" + std::string(name) + ".txt"; + + //printf("File: '%s'\n", path.c_str() ); + + return remove( path.c_str() ); +} +//******************************************************************************** +jsDev_t *getJoystickDevice( int devNum ) +{ + if ( (devNum >= 0) && (devNum < MAX_JOYSTICKS) ) + { + return &jsDev[ devNum ]; + } + return NULL; +} + +//******************************************************************************** /** * Tests if the given button is active on the joystick. */ int DTestButtonJoy(ButtConfig *bc) { - int x; + SDL_Joystick *js; - for(x = 0; x < bc->NumC; x++) + if (bc->ButtonNum == -1) { - if (bc->ButtonNum[x] == -1) - { - continue; - } - if (bc->ButtonNum[x] & 0x2000) - { - /* Hat "button" */ - if(SDL_JoystickGetHat(s_Joysticks[bc->DeviceNum[x]], - ((bc->ButtonNum[x] >> 8) & 0x1F)) & - (bc->ButtonNum[x]&0xFF)) - return 1; - } - else if (bc->ButtonNum[x] & 0x8000) - { - /* Axis "button" */ - int pos; - pos = SDL_JoystickGetAxis(s_Joysticks[bc->DeviceNum[x]], - bc->ButtonNum[x] & 16383); - if ((bc->ButtonNum[x] & 0x4000) && pos <= -16383) { - return 1; - } else if (!(bc->ButtonNum[x] & 0x4000) && pos >= 16363) { - return 1; - } - } - else if(SDL_JoystickGetButton(s_Joysticks[bc->DeviceNum[x]], - bc->ButtonNum[x])) - return 1; + return 0; } + if ( bc->DeviceNum < 0 ) + { + return 0; + } + js = jsDev[bc->DeviceNum].getJS(); + + if (bc->ButtonNum & 0x2000) + { + /* Hat "button" */ + if (SDL_JoystickGetHat( js, + ((bc->ButtonNum >> 8) & 0x1F)) & + (bc->ButtonNum&0xFF)) + { + bc->state = 1; + return 1; + } + else + { + bc->state = 0; + } + } + else if (bc->ButtonNum & 0x8000) + { + /* Axis "button" */ + int pos; + pos = SDL_JoystickGetAxis( js, + bc->ButtonNum & 0x3FFF); + if ((bc->ButtonNum & 0x4000) && pos <= -16383) + { + bc->state = 1; + return 1; + } + else if (!(bc->ButtonNum & 0x4000) && pos >= 16363) + { + bc->state = 1; + return 1; + } + else + { + bc->state = 0; + } + } + else if (SDL_JoystickGetButton( js, + bc->ButtonNum)) + { + bc->state = 1; + return 1; + } + else + { + bc->state = 0; + } + return 0; } +//******************************************************************************** + +//static void printJoystick( SDL_Joystick *js ) +//{ +// char guidStr[64]; +// SDL_Joystick *js; +// +// js = jsDev[i].getJS(); +// +// SDL_JoystickGUID guid = SDL_JoystickGetGUID( js ); +// +// SDL_JoystickGetGUIDString( guid, guidStr, sizeof(guidStr) ); +// +// printf("JoyStickID: %i: %s \n", +// SDL_JoystickInstanceID( js ), SDL_JoystickName( js ) ); +// printf("GUID: %s \n", guidStr ); +// printf("NumAxes: %i \n", SDL_JoystickNumAxes(js) ); +// printf("NumButtons: %i \n", SDL_JoystickNumButtons(js) ); +// printf("NumHats: %i \n", SDL_JoystickNumHats(js) ); +// +//} + +//******************************************************************************** /** * Shutdown the SDL joystick subsystem. */ int -KillJoysticks() +KillJoysticks(void) { int n; /* joystick index */ - if(!s_jinited) { + if (!s_jinited) { return -1; } - for(n = 0; n < MAX_JOYSTICKS; n++) { - if (s_Joysticks[n] != 0) { - SDL_JoystickClose(s_Joysticks[n]); - } - s_Joysticks[n]=0; + for (n = 0; n < MAX_JOYSTICKS; n++) + { + jsDev[n].close(); } SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + + s_jinited = 0; + return 0; } +//******************************************************************************** +int AddJoystick( int which ) +{ + if ( jsDev[ which ].isConnected() ) + { + //printf("Error: Joystick already exists at device index %i \n", which ); + return -1; + } + else + { + if ( SDL_IsGameController(which) ) + { + jsDev[which].gc = SDL_GameControllerOpen(which); + + if ( jsDev[which].gc == NULL ) + { + printf("Could not open game controller %d: %s.\n", + which, SDL_GetError()); + } + else + { + //printf("Added Joystick: %i \n", which ); + jsDev[which].init(which); + //jsDev[which].print(); + //printJoystick( s_Joysticks[which] ); + } + } + else + { + jsDev[which].js = SDL_JoystickOpen(which); + + if ( jsDev[which].js == NULL ) + { + printf("Could not open joystick %d: %s.\n", + which, SDL_GetError()); + } + else + { + //printf("Added Joystick: %i \n", which ); + jsDev[which].init(which); + //jsDev[which].print(); + //printJoystick( s_Joysticks[which] ); + } + } + } + return 0; +} + +//******************************************************************************** +int RemoveJoystick( int which ) +{ + //printf("Remove Joystick: %i \n", which ); + + for (int i=0; iMAX_JOYSTICKS) { + if (total > MAX_JOYSTICKS) + { total = MAX_JOYSTICKS; } - for(n = 0; n < total; n++) { + for (n = 0; n < total; n++) + { /* Open the joystick under SDL. */ - s_Joysticks[n] = SDL_JoystickOpen(n); - //printf("Could not open joystick %d: %s.\n", - //joy[n] - 1, SDL_GetError()); - continue; + AddJoystick(n); } s_jinited = 1; return 1; } +//******************************************************************************** diff --git a/src/drivers/Qt/sdl-joystick.h b/src/drivers/Qt/sdl-joystick.h new file mode 100644 index 00000000..568f736b --- /dev/null +++ b/src/drivers/Qt/sdl-joystick.h @@ -0,0 +1,92 @@ +// sdl-joystick.h + +#ifndef __SDL_JOYSTICK_H__ +#define __SDL_JOYSTICK_H__ + +#include + +#include "Qt/main.h" +#include "Qt/input.h" +#include "Qt/sdl.h" + +#define MAX_JOYSTICKS 32 + +struct nesGamePadMap_t +{ + char guid[64]; + char name[128]; + char btn[GAMEPAD_NUM_BUTTONS][32]; + char os[64]; + + nesGamePadMap_t(void); + ~nesGamePadMap_t(void); + + void clearMapping(void); + int parseMapping( const char *text ); +}; + +struct jsDev_t +{ + SDL_Joystick *js; + SDL_GameController *gc; + + jsDev_t(void); + //~jsDev_t(void); + + void init( int idx ); + int close(void); + SDL_Joystick *getJS(void); + bool isGameController(void); + bool isConnected(void); + void print(void); + int bindPort( int idx ); + int unbindPort( int idx ); + int getBindPorts(void); + const char *getName(void); + const char *getGUID(void); + + private: + int devIdx; + int portBindMask; + std::string guidStr; + std::string name; +}; + +class GamePad_t +{ + public: + + ButtConfig bmap[GAMEPAD_NUM_BUTTONS]; + + GamePad_t(void); + ~GamePad_t(void); + + int init( int port, const char *guid, const char *profile = NULL ); + const char *getGUID(void); + + int loadDefaults(void); + int loadProfile( const char *name, const char *guid = NULL ); + + int getDeviceIndex(void){ return devIdx; } + int setDeviceIndex( int devIdx ); + int setMapping( const char *map ); + int setMapping( nesGamePadMap_t *map ); + + int createProfile( const char *name ); + int getMapFromFile( const char *filename, char *out ); + int getDefaultMap( char *out, const char *guid = NULL ); + int saveMappingToFile( const char *filename, const char *txtMap ); + int saveCurrentMapToFile( const char *filename ); + int deleteMapping( const char *name ); + + private: + int devIdx; + int portNum; + +}; + +extern GamePad_t GamePad[4]; + +jsDev_t *getJoystickDevice( int devNum ); + +#endif diff --git a/src/file.cpp b/src/file.cpp index f7f58cbd..9fe6e933 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -465,6 +465,11 @@ void FCEUI_SetBaseDirectory(std::string const & dir) { BaseDirectory = dir; } +/// Gets the base directory +const char *FCEUI_GetBaseDirectory(void) +{ + return BaseDirectory.c_str(); +} static char *odirs[FCEUIOD__COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0}; // odirs, odors. ^_^