diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1ec3242c..60dba054 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -506,6 +506,7 @@ set(SRC_DRIVERS_SDL ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerSDL.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/InputConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FamilyKeyboard.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TimingConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/FrameTimingStats.cpp diff --git a/src/drivers/Qt/FamilyKeyboard.cpp b/src/drivers/Qt/FamilyKeyboard.cpp new file mode 100644 index 00000000..9ae4a033 --- /dev/null +++ b/src/drivers/Qt/FamilyKeyboard.cpp @@ -0,0 +1,372 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 mjbudd77 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +// FamilyKeyboard.cpp +#include +#include + +#include "Qt/config.h" +#include "Qt/fceuWrapper.h" +#include "Qt/FamilyKeyboard.h" + +static const char *keyNames[] = +{ + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "0", + "-", + "^", + "\\", + "STP", + "ESC", + "Q", + "W", + "E", + "R", + "T", + "Y", + "U", + "I", + "O", + "P", + "@", + "[", + "RETURN", + "CTR", + "A", + "S", + "D", + "F", + "G", + "H", + "J", + "K", + "L", + ";", + ":", + "]", + "KANA", + "SHIFT", + "Z", + "X", + "C", + "V", + "B", + "N", + "M", + ",", + ".", + "/", + "_", + "SHIFT", + "GRPH", + "SPACE", + "CLR", + "INS", + "DEL", + "UP", + "LEFT", + "RIGHT", + "DOWN", + NULL +}; +//********************************************************************************* +FamilyKeyboardWidget::FamilyKeyboardWidget( QWidget *parent ) +{ + QFont font; + std::string fontString; + + g_config->getOption("SDL.FamilyKeyboardFont", &fontString); + + if ( fontString.size() > 0 ) + { + font.fromString( QString::fromStdString( fontString ) ); + } + else + { + font.setFamily("Courier New"); + font.setStyle( QFont::StyleNormal ); + font.setStyleHint( QFont::Monospace ); + } + setFont( font ); + + setMinimumSize( 512, 256 ); + + calcFontData(); + +} +//********************************************************************************* +FamilyKeyboardWidget::~FamilyKeyboardWidget(void) +{ + +} +//********************************************************************************* +void FamilyKeyboardWidget::calcFontData(void) +{ + QWidget::setFont(font()); + QFontMetrics metrics(font()); +#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0) + pxCharWidth = metrics.horizontalAdvance(QLatin1Char('2')); +#else + pxCharWidth = metrics.width(QLatin1Char('2')); +#endif + pxCharHeight = metrics.capHeight(); + //pxLineSpacing = metrics.lineSpacing() * 1.25; + //pxCursorHeight = metrics.height(); + + pxBtnGridX = (3 * pxCharWidth) + 2; + pxBtnGridY = (2 * pxCharHeight); + + if ( pxBtnGridX % 2 ) + { + pxBtnGridX++; + } + if ( pxBtnGridY % 2 ) + { + pxBtnGridY++; + } + setMinimumWidth( pxBtnGridX * 25 ); + setMinimumHeight( pxBtnGridY * 8 ); +} +//********************************************************************************* +void FamilyKeyboardWidget::paintEvent(QPaintEvent *event) +{ + int i, j, x, y, w, h, xs, ys; + QPainter painter(this); + + // Row 1 + x = pxBtnGridX / 2; + y = pxBtnGridY / 2; + + w = pxBtnGridX * 2; + h = pxBtnGridY; + + xs = w / 4; + ys = h / 4; + + for (i=0; i<8; i++) + { + j = i; + + key[j].rect = QRect( x, y, w, h ); + + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += (w + xs); + } + + // Row 2 + x = pxBtnGridX; + y += pxBtnGridY + ys; + + w = pxBtnGridX; + + xs = w / 4; + + for (i=8; i<22; i++) + { + j = i; + + key[j].rect = QRect( x, y, w, h ); + + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += (w + xs); + } + + // Row 3 + x = pxBtnGridX / 2; + y += pxBtnGridY + ys; + + w = pxBtnGridX; + + xs = w / 4; + + for (i=22; i<35; i++) + { + j = i; + + key[j].rect = QRect( x, y, w, h ); + + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += (w + xs); + } + + x += (xs); + + j = 35; + key[j].rect = QRect( x, y, w*3, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + // Row 4 + x = pxBtnGridX; + y += pxBtnGridY + ys; + + w = pxBtnGridX; + + xs = w / 4; + x -= xs; + + for (i=36; i<49; i++) + { + j = i; + + key[j].rect = QRect( x, y, w, h ); + + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += (w + xs); + } + + j = 49; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + // Row 5 + x = pxBtnGridX / 2; + y += pxBtnGridY + ys; + + w = pxBtnGridX; + + xs = w / 4; + //x -= xs; + + j = 50; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += ((w*2) + xs); + + for (i=51; i<62; i++) + { + j = i; + + key[j].rect = QRect( x, y, w, h ); + + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += (w + xs); + } + + j = 62; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + // Row 6 + x = (pxBtnGridX * 5) / 2; + y += pxBtnGridY + ys; + + w = pxBtnGridX; + + xs = w / 4; + x += (2*xs); + + j = 63; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += ((w*2) + xs); + + j = 64; + key[j].rect = QRect( x, y, (w*8) + (xs*7), h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + // Row 7 + xs = pxBtnGridX / 4; + x = (pxBtnGridX+xs) * 17; + y = (pxBtnGridY * 3) / 2; + + w = pxBtnGridX; + + xs = w / 4; + //x += (2*xs); + y += (2*ys); + + for (i=65; i<68; i++) + { + j = i; + + key[j].rect = QRect( x, y, w, h ); + + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += (w + xs); + } + + // Arrow Keys + x = (pxBtnGridX+xs) * 17 + (pxBtnGridX)/2 + xs; + y += pxBtnGridY + ys; + + j = 68; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x = (pxBtnGridX+xs) * 17 - (pxBtnGridX)/2 + (xs/2); + y += pxBtnGridY + ys; + + j = 69; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x += ((w*2) + xs); + + j = 70; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); + + x = (pxBtnGridX+xs) * 17 + (pxBtnGridX)/2 + xs; + y += pxBtnGridY + ys; + + j = 71; + key[j].rect = QRect( x, y, w*2, h ); + painter.drawText( key[j].rect, Qt::AlignCenter, tr(keyNames[j]) ); + painter.drawRect( key[j].rect ); +} +//********************************************************************************* diff --git a/src/drivers/Qt/FamilyKeyboard.h b/src/drivers/Qt/FamilyKeyboard.h new file mode 100644 index 00000000..0cbb96c2 --- /dev/null +++ b/src/drivers/Qt/FamilyKeyboard.h @@ -0,0 +1,37 @@ +#include +#include +#include + + +class FKB_Key_t +{ + + public: + QRect rect; + char name[16]; +}; + +class FamilyKeyboardWidget : public QWidget +{ + Q_OBJECT + +public: + FamilyKeyboardWidget( QWidget *parent = 0); + ~FamilyKeyboardWidget(void); + + static const unsigned int NUM_KEYS = 0x48; + +protected: + //void keyPressEvent(QKeyEvent *event); + //void kepaintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event); + + void calcFontData(void); + + int pxCharWidth; + int pxCharHeight; + int pxBtnGridX; + int pxBtnGridY; + + FKB_Key_t key[NUM_KEYS]; +}; diff --git a/src/drivers/Qt/InputConf.cpp b/src/drivers/Qt/InputConf.cpp index db51c787..99002bb4 100644 --- a/src/drivers/Qt/InputConf.cpp +++ b/src/drivers/Qt/InputConf.cpp @@ -38,9 +38,12 @@ #include "Qt/fceuWrapper.h" #include "Qt/ConsoleWindow.h" #include "Qt/ConsoleUtilities.h" +#include "Qt/FamilyKeyboard.h" #include "Qt/InputConf.h" static InputConfDialog_t *win = NULL; +static FKBConfigDialog *fkbCfgWin = NULL; + //---------------------------------------------------------------------------- void openInputConfWindow(QWidget *parent) { @@ -244,6 +247,7 @@ InputConfDialog_t::InputConfDialog_t(QWidget *parent) connect(nesPortConfButton[0], SIGNAL(clicked(void)), this, SLOT(port1Configure(void))); connect(nesPortConfButton[1], SIGNAL(clicked(void)), this, SLOT(port2Configure(void))); + connect(expPortConfButton , SIGNAL(clicked(void)), this, SLOT(expPortConfigure(void))); connect(loadConfigButton, SIGNAL(clicked(void)), this, SLOT(openLoadPresetFile(void))); connect(saveConfigButton, SIGNAL(clicked(void)), this, SLOT(openSavePresetFile(void))); @@ -329,6 +333,8 @@ void InputConfDialog_t::updatePortLabels(void) expPortLabel->setText(expPortComboxBox->itemText(j)); } } + + expPortConfButton->setEnabled( curNesInput[2] == SIFC_FKB ); } //---------------------------------------------------------------------------- void InputConfDialog_t::updatePortComboBoxes(void) @@ -428,6 +434,18 @@ void InputConfDialog_t::port2Configure(void) openPortConfig(1); } //---------------------------------------------------------------------------- +void InputConfDialog_t::expPortConfigure(void) +{ + if ( curNesInput[2] == SIFC_FKB ) + { + if ( fkbCfgWin == NULL ) + { + fkbCfgWin = new FKBConfigDialog(this); + fkbCfgWin->show(); + } + } +} +//---------------------------------------------------------------------------- void InputConfDialog_t::openLoadPresetFile(void) { int ret, useNativeFileDialogVal; @@ -587,3 +605,109 @@ void InputConfDialog_t::updatePeriodic(void) } } //---------------------------------------------------------------------------- +//--- Family Keyboard Config Dialog +//---------------------------------------------------------------------------- +FKBConfigDialog::FKBConfigDialog(QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *mainVbox; + QHBoxLayout *hbox; + QPushButton *closeButton; + QTreeWidgetItem *item; + + setWindowTitle( "Family Keyboard Config" ); + + mainVbox = new QVBoxLayout(); + + mainVbox->addWidget( new FamilyKeyboardWidget() ); + + setLayout( mainVbox ); + + keyTree = new QTreeWidget(); + + keyTree->setColumnCount(2); + keyTree->setSelectionMode( QAbstractItemView::SingleSelection ); + keyTree->setAlternatingRowColors(true); + + item = new QTreeWidgetItem(); + item->setText(0, QString::fromStdString("FKB Key")); + item->setText(1, QString::fromStdString("SDL Binding")); + item->setTextAlignment(0, Qt::AlignLeft); + item->setTextAlignment(1, Qt::AlignCenter); + + keyTree->setHeaderItem(item); + + keyTree->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + + for (int i=0; isetText(0, tr(FamilyKeyBoardNames[i])); + //item->setText(1, tr(FamilyKeyBoardNames[i])); + + item->setTextAlignment(0, Qt::AlignLeft); + item->setTextAlignment(1, Qt::AlignCenter); + + keyTree->addTopLevelItem(item); + } + updateBindingList(); + + mainVbox->addWidget( keyTree ); + + hbox = new QHBoxLayout(); + + mainVbox->addLayout( hbox ); + + closeButton = new QPushButton( tr("Close") ); + closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton)); + + hbox->addStretch(5); + hbox->addWidget( closeButton, 1); + + connect(closeButton , SIGNAL(clicked(void)), this, SLOT(closeWindow(void))); +} +//---------------------------------------------------------------------------- +FKBConfigDialog::~FKBConfigDialog(void) +{ + +} +//---------------------------------------------------------------------------- +void FKBConfigDialog::updateBindingList(void) +{ + char keyNameStr[128]; + + for (int i=0; itopLevelItem(i); + + item->setText(0, tr(FamilyKeyBoardNames[i])); + + if (fkbmap[i].ButtType == BUTTC_KEYBOARD) + { + snprintf(keyNameStr, sizeof(keyNameStr), "%s", + SDL_GetKeyName(fkbmap[i].ButtonNum)); + } + else + { + strcpy(keyNameStr, ButtonName(&fkbmap[i])); + } + item->setText(1, tr(keyNameStr)); + } +} +//---------------------------------------------------------------------------- +void FKBConfigDialog::closeEvent(QCloseEvent *event) +{ + printf("FKB Config Close Window Event\n"); + done(0); + deleteLater(); + event->accept(); +} +//---------------------------------------------------------------------------- +void FKBConfigDialog::closeWindow(void) +{ + //printf("Close Window\n"); + done(0); + deleteLater(); +} +//---------------------------------------------------------------------------- diff --git a/src/drivers/Qt/InputConf.h b/src/drivers/Qt/InputConf.h index ba4623f2..3176713d 100644 --- a/src/drivers/Qt/InputConf.h +++ b/src/drivers/Qt/InputConf.h @@ -20,6 +20,25 @@ #include "Qt/main.h" +class FKBConfigDialog : public QDialog +{ + Q_OBJECT + +public: + FKBConfigDialog(QWidget *parent = 0); + ~FKBConfigDialog(void); + +protected: + void closeEvent(QCloseEvent *event); + void updateBindingList(void); + + QTreeWidget *keyTree; + + +public slots: + void closeWindow(void); +}; + class InputConfDialog_t : public QDialog { Q_OBJECT @@ -58,6 +77,7 @@ public slots: private slots: void port1Configure(void); void port2Configure(void); + void expPortConfigure(void); void port1Select(int index); void port2Select(int index); void expSelect(int index); diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp index b80007c7..26b570d9 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -1841,7 +1841,7 @@ void InitInputInterface() FCEUI_SetInputFourscore((eoptions & EO_FOURSCORE) != 0); } -static ButtConfig fkbmap[0x48] = { +ButtConfig fkbmap[FAMILYKEYBOARD_NUM_BUTTONS] = { /* 0 */ MK(SDLK_F1), MK(SDLK_F2), MK(SDLK_F3), MK(SDLK_F4), MK(SDLK_F5), MK(SDLK_F6), MK(SDLK_F7), MK(SDLK_F8), /* 8 */ MK(SDLK_1), MK(SDLK_2), MK(SDLK_3), MK(SDLK_4), MK(SDLK_5), MK(SDLK_6), MK(SDLK_7), MK(SDLK_8), MK(SDLK_9), /* 17 */ MK(SDLK_0), @@ -1870,7 +1870,7 @@ static void UpdateFKB() leftShiftDown = DTestButton(&fkbmap[50]); - for (x = 0; x < 0x48; x++) + for (x = 0; x < FAMILYKEYBOARD_NUM_BUTTONS; x++) { if ( leftShiftDown && (x == 62) ) { // Family BASIC appears to not like when both shift keys are pressed at the diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h index 940b0d5f..f76ef0a5 100644 --- a/src/drivers/Qt/input.h +++ b/src/drivers/Qt/input.h @@ -129,6 +129,7 @@ extern bool replaceP2StartWithMicrophone; //extern ButtConfig powerpadsc[2][12]; //extern ButtConfig QuizKingButtons[6]; //extern ButtConfig FTrainerButtons[12]; +extern ButtConfig fkbmap[FAMILYKEYBOARD_NUM_BUTTONS]; void IncreaseEmulationSpeed(void); void DecreaseEmulationSpeed(void);