From be7dcda45e72a33048318502db997cfbb9ba86b1 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Thu, 16 Jul 2020 21:18:57 -0400 Subject: [PATCH 1/3] Added palette config window and logic. --- src/CMakeLists.txt | 1 + src/drivers/Qt/AboutWindow.cpp | 1 + src/drivers/Qt/ConsoleWindow.cpp | 25 ++++ src/drivers/Qt/ConsoleWindow.h | 2 + src/drivers/Qt/PaletteConf.cpp | 217 +++++++++++++++++++++++++++++++ src/drivers/Qt/PaletteConf.h | 46 +++++++ src/drivers/Qt/sdl-video.cpp | 1 + 7 files changed, 293 insertions(+) create mode 100644 src/drivers/Qt/PaletteConf.cpp create mode 100644 src/drivers/Qt/PaletteConf.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c1063f0c..bb37f0f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -388,6 +388,7 @@ set(SRC_DRIVERS_SDL ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleViewerSDL.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleVideoConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ConsoleSoundConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/AboutWindow.cpp diff --git a/src/drivers/Qt/AboutWindow.cpp b/src/drivers/Qt/AboutWindow.cpp index 4d67090d..b79f0315 100644 --- a/src/drivers/Qt/AboutWindow.cpp +++ b/src/drivers/Qt/AboutWindow.cpp @@ -16,6 +16,7 @@ static const char *Authors[] = { "Linux/SDL Developers:", + "\t mjbudd77", "\t Lukas Sabota //punkrockguy318", "\t Soules", "\t Bryan Cain", "\t radsaq", "\t Shinydoofy", "FceuX 2.0 Developers:", diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index c9bc21db..c0b120ee 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -19,6 +19,7 @@ #include "Qt/ConsoleWindow.h" #include "Qt/GamePadConf.h" #include "Qt/HotKeyConf.h" +#include "Qt/PaletteConf.h" #include "Qt/ConsoleSoundConf.h" #include "Qt/ConsoleVideoConf.h" #include "Qt/AboutWindow.h" @@ -285,6 +286,14 @@ void consoleWin_t::createMainMenu(void) optMenu->addAction(hotkeyConfig); + // Options -> Palette Config + paletteConfig = new QAction(tr("Palette Config"), this); + //paletteConfig->setShortcut( QKeySequence(tr("Ctrl+C"))); + paletteConfig->setStatusTip(tr("Palette Configure")); + connect(paletteConfig, SIGNAL(triggered()), this, SLOT(openPaletteConfWin(void)) ); + + optMenu->addAction(paletteConfig); + // Options -> Auto-Resume autoResume = new QAction(tr("Auto-Resume Play"), this); //autoResume->setShortcut( QKeySequence(tr("Ctrl+C"))); @@ -931,6 +940,22 @@ void consoleWin_t::openHotkeyConfWin(void) //printf("Hotkey Config Window Destroyed\n"); } +void consoleWin_t::openPaletteConfWin(void) +{ + PaletteConfDialog_t *paletteConfWin; + + //printf("Open Palette Config Window\n"); + + paletteConfWin = new PaletteConfDialog_t(this); + + paletteConfWin->show(); + paletteConfWin->exec(); + + delete paletteConfWin; + + //printf("Palette Config Window Destroyed\n"); +} + void consoleWin_t::toggleAutoResume(void) { //printf("Auto Resume: %i\n", autoResume->isChecked() ); diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index 59bb43f5..e5d563fb 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -67,6 +67,7 @@ class consoleWin_t : public QMainWindow QAction *gameSoundConfig; QAction *gameVideoConfig; QAction *hotkeyConfig; + QAction *paletteConfig; QAction *autoResume; QAction *fullscreen; QAction *aboutAct; @@ -116,6 +117,7 @@ class consoleWin_t : public QMainWindow void openGameSndConfWin(void); void openGameVideoConfWin(void); void openHotkeyConfWin(void); + void openPaletteConfWin(void); void toggleAutoResume(void); void toggleFullscreen(void); void updatePeriodic(void); diff --git a/src/drivers/Qt/PaletteConf.cpp b/src/drivers/Qt/PaletteConf.cpp new file mode 100644 index 00000000..bf167a27 --- /dev/null +++ b/src/drivers/Qt/PaletteConf.cpp @@ -0,0 +1,217 @@ +// PaletteConf.cpp +// +#include + +#include "Qt/PaletteConf.h" +#include "Qt/main.h" +#include "Qt/input.h" +#include "Qt/config.h" +#include "Qt/keyscan.h" +#include "Qt/fceuWrapper.h" + +//---------------------------------------------------- +PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent) + : QDialog( parent ) +{ + QVBoxLayout *mainLayout, *vbox; + QHBoxLayout *hbox1; + QGroupBox *frame; + QPushButton *closebutton; + QPushButton *button; + int hue, tint; + char stmp[64]; + + // sync with config + g_config->getOption ("SDL.Hue", &hue); + g_config->getOption ("SDL.Tint", &tint); + + setWindowTitle( tr("Palette Config") ); + + mainLayout = new QVBoxLayout(); + + frame = new QGroupBox( tr("Custom Palette:") ); + hbox1 = new QHBoxLayout(); + + button = new QPushButton( tr("Open Palette") ); + hbox1->addWidget( button ); + + connect( button, SIGNAL(clicked(void)), this, SLOT(openPaletteFile(void)) ); + + custom_palette_path = new QLineEdit(); + custom_palette_path->setReadOnly(true); + hbox1->addWidget( custom_palette_path ); + + button = new QPushButton( tr("Clear") ); + hbox1->addWidget( button ); + + connect( button, SIGNAL(clicked(void)), this, SLOT(clearPalette(void)) ); + + frame->setLayout( hbox1 ); + + mainLayout->addWidget( frame ); + + frame = new QGroupBox( tr("NTSC Palette Controls:") ); + + vbox = new QVBoxLayout(); + useNTSC = new QCheckBox( tr("Use NTSC Palette") ); + + int ntscPaletteEnable; + g_config->getOption("SDL.NTSCpalette", &ntscPaletteEnable); + useNTSC->setChecked( ntscPaletteEnable ); + + connect(useNTSC , SIGNAL(stateChanged(int)), this, SLOT(use_NTSC_Changed(int)) ); + + vbox->addWidget( useNTSC ); + + sprintf( stmp, "Tint: %3i \n", tint ); + tintFrame = new QGroupBox( tr(stmp) ); + hbox1 = new QHBoxLayout(); + tintSlider = new QSlider( Qt::Horizontal ); + tintSlider->setMinimum( 0); + tintSlider->setMaximum(128); + tintSlider->setValue( tint ); + + connect( tintSlider, SIGNAL(valueChanged(int)), this, SLOT(tintChanged(int)) ); + + hbox1->addWidget( tintSlider ); + tintFrame->setLayout( hbox1 ); + vbox->addWidget( tintFrame ); + + sprintf( stmp, "Hue: %3i \n", hue ); + hueFrame = new QGroupBox( tr(stmp) ); + hbox1 = new QHBoxLayout(); + hueSlider = new QSlider( Qt::Horizontal ); + hueSlider->setMinimum( 0); + hueSlider->setMaximum(128); + hueSlider->setValue( hue ); + + connect( hueSlider, SIGNAL(valueChanged(int)), this, SLOT(hueChanged(int)) ); + + hbox1->addWidget( hueSlider ); + hueFrame->setLayout( hbox1 ); + vbox->addWidget( hueFrame ); + + frame->setLayout( vbox ); + + mainLayout->addWidget( frame ); + + setLayout( mainLayout ); +} + +//---------------------------------------------------- +PaletteConfDialog_t::~PaletteConfDialog_t(void) +{ + +} +//---------------------------------------------------- +void PaletteConfDialog_t::closeWindow(void) +{ + //printf("Close Window\n"); + done(0); +} +//---------------------------------------------------- +void PaletteConfDialog_t::hueChanged(int v) +{ + int c, t; + char stmp[64]; + + sprintf( stmp, "Hue: %3i", v ); + + hueFrame->setTitle(stmp); + + g_config->setOption ("SDL.Hue", v); + g_config->save (); + g_config->getOption ("SDL.Tint", &t); + g_config->getOption ("SDL.NTSCpalette", &c); + + fceuWrapperLock(); + FCEUI_SetNTSCTH (c, t, v); + fceuWrapperUnLock(); +} +//---------------------------------------------------- +void PaletteConfDialog_t::tintChanged(int v) +{ + int c, h; + char stmp[64]; + + sprintf( stmp, "Tint: %3i", v ); + + tintFrame->setTitle(stmp); + + g_config->setOption ("SDL.Tint", v); + g_config->save (); + g_config->getOption ("SDL.NTSCpalette", &c); + g_config->getOption ("SDL.Hue", &h); + + fceuWrapperLock(); + FCEUI_SetNTSCTH (c, v, h); + fceuWrapperUnLock(); +} +//---------------------------------------------------- +void PaletteConfDialog_t::use_NTSC_Changed(int state) +{ + int value = (state == Qt::Unchecked) ? 0 : 1; + + g_config->setOption ("SDL.NTSCpalette", value); + g_config->save (); + UpdateEMUCore (g_config); +} +//---------------------------------------------------- +void PaletteConfDialog_t::clearPalette(void) +{ + g_config->setOption ("SDL.Palette", 0); + custom_palette_path->setText(""); +} +//---------------------------------------------------- +void PaletteConfDialog_t::openPaletteFile(void) +{ + int ret; + QString filename; + QFileDialog dialog(this, tr("Open NES Palette") ); + + dialog.setFileMode(QFileDialog::ExistingFile); + + dialog.setNameFilter(tr("NES Palettes (*.pal)(*.PAL) ;; All files (*)")); + + dialog.setViewMode(QFileDialog::List); + + dialog.setDirectory( tr("/usr/share/fceux/palettes") ); + + // the gnome default file dialog is not playing nice with QT. + // TODO make this a config option to use native file dialog. + dialog.setOption(QFileDialog::DontUseNativeDialog, true); + + dialog.show(); + ret = dialog.exec(); + + if ( ret ) + { + QStringList fileList; + fileList = dialog.selectedFiles(); + + if ( fileList.size() > 0 ) + { + filename = fileList[0]; + } + } + + if ( filename.isNull() ) + { + return; + } + qDebug() << "selected file path : " << filename.toUtf8(); + + g_config->setOption ("SDL.Palette", filename.toStdString().c_str() ); + g_config->setOption ("SDL.NTSCpalette", 0); + + fceuWrapperLock(); + LoadCPalette ( filename.toStdString().c_str() ); + fceuWrapperUnLock(); + + custom_palette_path->setText( filename.toStdString().c_str() ); + + useNTSC->setChecked( 0 ); + + return; +} +//---------------------------------------------------- diff --git a/src/drivers/Qt/PaletteConf.h b/src/drivers/Qt/PaletteConf.h new file mode 100644 index 00000000..f1d83041 --- /dev/null +++ b/src/drivers/Qt/PaletteConf.h @@ -0,0 +1,46 @@ +// PaletteConf.h +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Qt/main.h" + +class PaletteConfDialog_t : public QDialog +{ + Q_OBJECT + + public: + PaletteConfDialog_t(QWidget *parent = 0); + ~PaletteConfDialog_t(void); + + protected: + QLineEdit *custom_palette_path; + QCheckBox *useNTSC; + QSlider *tintSlider; + QSlider *hueSlider; + QGroupBox *tintFrame; + QGroupBox *hueFrame; + private: + + public slots: + void closeWindow(void); + private slots: + void hueChanged(int value); + void tintChanged(int value); + void openPaletteFile(void); + void clearPalette(void); + void use_NTSC_Changed(int v); + +}; diff --git a/src/drivers/Qt/sdl-video.cpp b/src/drivers/Qt/sdl-video.cpp index 003f8dcd..95e9584c 100644 --- a/src/drivers/Qt/sdl-video.cpp +++ b/src/drivers/Qt/sdl-video.cpp @@ -297,6 +297,7 @@ static void RedoPalette() { if (s_curbpp > 8) { + //printf("Refresh Palette\n"); SetPaletteBlitToHigh((uint8*)s_psdl); } } From 6fb247d7854865ab5f6b8bab61cf6ddc06944d2f Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 17 Jul 2020 21:50:23 -0400 Subject: [PATCH 2/3] Changed QMutex to be recursive to prevent dead-locks in gui and emulator. A few bug fixes for the palette config window. --- src/drivers/Qt/ConsoleSoundConf.cpp | 78 ++++++++++++++++++----------- src/drivers/Qt/ConsoleWindow.cpp | 2 +- src/drivers/Qt/PaletteConf.cpp | 50 +++++++++++++----- src/drivers/Qt/fceuWrapper.cpp | 31 +++++++++--- src/drivers/Qt/fceuWrapper.h | 2 +- src/palette.cpp | 4 +- 6 files changed, 114 insertions(+), 53 deletions(-) diff --git a/src/drivers/Qt/ConsoleSoundConf.cpp b/src/drivers/Qt/ConsoleSoundConf.cpp index 4d716f3b..9932a7ca 100644 --- a/src/drivers/Qt/ConsoleSoundConf.cpp +++ b/src/drivers/Qt/ConsoleSoundConf.cpp @@ -262,10 +262,12 @@ void ConsoleSndConfDialog_t::bufSizeChanged(int value) g_config->setOption ("SDL.Sound.BufSize", value); // reset sound subsystem for changes to take effect - fceuWrapperLock(); - KillSound (); - InitSound (); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + KillSound (); + InitSound (); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::volumeChanged(int value) @@ -278,9 +280,11 @@ void ConsoleSndConfDialog_t::volumeChanged(int value) g_config->setOption ("SDL.Sound.Volume", value); - fceuWrapperLock(); - FCEUI_SetSoundVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetSoundVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::triangleChanged(int value) @@ -293,9 +297,11 @@ void ConsoleSndConfDialog_t::triangleChanged(int value) g_config->setOption ("SDL.Sound.TriangleVolume", value); - fceuWrapperLock(); - FCEUI_SetTriangleVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetTriangleVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::square1Changed(int value) @@ -308,9 +314,11 @@ void ConsoleSndConfDialog_t::square1Changed(int value) g_config->setOption ("SDL.Sound.Square1Volume", value); - fceuWrapperLock(); - FCEUI_SetSquare1Volume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetSquare1Volume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::square2Changed(int value) @@ -323,9 +331,11 @@ void ConsoleSndConfDialog_t::square2Changed(int value) g_config->setOption ("SDL.Sound.Square2Volume", value); - fceuWrapperLock(); - FCEUI_SetSquare2Volume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetSquare2Volume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::noiseChanged(int value) @@ -338,9 +348,11 @@ void ConsoleSndConfDialog_t::noiseChanged(int value) g_config->setOption ("SDL.Sound.NoiseVolume", value); - fceuWrapperLock(); - FCEUI_SetNoiseVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNoiseVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::pcmChanged(int value) @@ -353,9 +365,11 @@ void ConsoleSndConfDialog_t::pcmChanged(int value) g_config->setOption ("SDL.Sound.PCMVolume", value); - fceuWrapperLock(); - FCEUI_SetPCMVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetPCMVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::enaSoundStateChange(int value) @@ -427,10 +441,12 @@ void ConsoleSndConfDialog_t::soundQualityChanged(int index) g_config->setOption ("SDL.Sound.Quality", qualitySelect->itemData(index).toInt() ); // reset sound subsystem for changes to take effect - fceuWrapperLock(); - KillSound (); - InitSound (); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + KillSound (); + InitSound (); + fceuWrapperUnLock(); + } g_config->save (); } //---------------------------------------------------- @@ -440,10 +456,12 @@ void ConsoleSndConfDialog_t::soundRateChanged(int index) g_config->setOption ("SDL.Sound.Rate", rateSelect->itemData(index).toInt() ); // reset sound subsystem for changes to take effect - fceuWrapperLock(); - KillSound (); - InitSound (); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + KillSound (); + InitSound (); + fceuWrapperUnLock(); + } g_config->save (); } //---------------------------------------------------- diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index c0b120ee..e8eef4f1 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -40,7 +40,7 @@ consoleWin_t::consoleWin_t(QWidget *parent) setWindowIcon(QIcon(":fceux1.png")); gameTimer = new QTimer( this ); - mutex = new QMutex( QMutex::NonRecursive ); + mutex = new QMutex( QMutex::Recursive ); emulatorThread = new emulatorThread_t(); connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater); diff --git a/src/drivers/Qt/PaletteConf.cpp b/src/drivers/Qt/PaletteConf.cpp index bf167a27..b02c57e5 100644 --- a/src/drivers/Qt/PaletteConf.cpp +++ b/src/drivers/Qt/PaletteConf.cpp @@ -16,10 +16,11 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent) QVBoxLayout *mainLayout, *vbox; QHBoxLayout *hbox1; QGroupBox *frame; - QPushButton *closebutton; + //QPushButton *closebutton; QPushButton *button; int hue, tint; char stmp[64]; + std::string paletteFile; // sync with config g_config->getOption ("SDL.Hue", &hue); @@ -37,8 +38,11 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent) connect( button, SIGNAL(clicked(void)), this, SLOT(openPaletteFile(void)) ); + g_config->getOption ("SDL.Palette", &paletteFile); + custom_palette_path = new QLineEdit(); custom_palette_path->setReadOnly(true); + custom_palette_path->setText( paletteFile.c_str() ); hbox1->addWidget( custom_palette_path ); button = new QPushButton( tr("Clear") ); @@ -124,9 +128,11 @@ void PaletteConfDialog_t::hueChanged(int v) g_config->getOption ("SDL.Tint", &t); g_config->getOption ("SDL.NTSCpalette", &c); - fceuWrapperLock(); - FCEUI_SetNTSCTH (c, t, v); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNTSCTH (c, t, v); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::tintChanged(int v) @@ -143,24 +149,42 @@ void PaletteConfDialog_t::tintChanged(int v) g_config->getOption ("SDL.NTSCpalette", &c); g_config->getOption ("SDL.Hue", &h); - fceuWrapperLock(); - FCEUI_SetNTSCTH (c, v, h); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNTSCTH (c, v, h); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::use_NTSC_Changed(int state) { + int h, t; int value = (state == Qt::Unchecked) ? 0 : 1; g_config->setOption ("SDL.NTSCpalette", value); g_config->save (); - UpdateEMUCore (g_config); + + g_config->getOption ("SDL.Hue", &h); + g_config->getOption ("SDL.Tint", &t); + + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNTSCTH (value, t, h); + //UpdateEMUCore (g_config); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::clearPalette(void) { - g_config->setOption ("SDL.Palette", 0); + g_config->setOption ("SDL.Palette", ""); custom_palette_path->setText(""); + + if ( fceuWrapperTryLock() ) + { + FCEUI_SetUserPalette( NULL, 0); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::openPaletteFile(void) @@ -204,9 +228,11 @@ void PaletteConfDialog_t::openPaletteFile(void) g_config->setOption ("SDL.Palette", filename.toStdString().c_str() ); g_config->setOption ("SDL.NTSCpalette", 0); - fceuWrapperLock(); - LoadCPalette ( filename.toStdString().c_str() ); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + LoadCPalette ( filename.toStdString().c_str() ); + fceuWrapperUnLock(); + } custom_palette_path->setText( filename.toStdString().c_str() ); diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index 7e1daca0..a43e3c15 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -56,7 +56,8 @@ static int inited = 0; static int noconfig=0; static int frameskip=0; static int periodic_saves = 0; -static bool mutexLocked = 0; +static int mutexLocks = 0; +static bool emulatorHasMutux = 0; extern double g_fpsScale; @@ -78,6 +79,7 @@ int mutecapture = 0; void FCEUD_Message(const char *text) { fputs(text, stdout); + fprintf(stdout, "\n"); } /** @@ -911,7 +913,7 @@ static void DoFun(int frameskip, int periodic_saves) void fceuWrapperLock(void) { consoleWindow->mutex->lock(); - mutexLocked = 1; + mutexLocks++; } bool fceuWrapperTryLock(int timeout) @@ -922,17 +924,17 @@ bool fceuWrapperTryLock(int timeout) if ( lockAcq ) { - mutexLocked = 1; + mutexLocks++; } return lockAcq; } void fceuWrapperUnLock(void) { - if ( mutexLocked ) + if ( mutexLocks > 0 ) { consoleWindow->mutex->unlock(); - mutexLocked = 0; + mutexLocks--; } else { @@ -942,12 +944,23 @@ void fceuWrapperUnLock(void) bool fceuWrapperIsLocked(void) { - return mutexLocked; + return mutexLocks > 0; } int fceuWrapperUpdate( void ) { - fceuWrapperLock(); + bool lock_acq; + + lock_acq = fceuWrapperTryLock(); + + if ( !lock_acq ) + { + printf("Error: Emulator Failed to Acquire Mutex\n"); + usleep( 100000 ); + + return -1; + } + emulatorHasMutux = 1; if ( GameInfo && !FCEUI_EmulationPaused() ) { @@ -955,6 +968,8 @@ int fceuWrapperUpdate( void ) fceuWrapperUnLock(); + emulatorHasMutux = 0; + while ( SpeedThrottle() ) { // Input device processing is in main thread @@ -966,6 +981,8 @@ int fceuWrapperUpdate( void ) { fceuWrapperUnLock(); + emulatorHasMutux = 0; + usleep( 100000 ); } return 0; diff --git a/src/drivers/Qt/fceuWrapper.h b/src/drivers/Qt/fceuWrapper.h index e3ce55a8..e0928e09 100644 --- a/src/drivers/Qt/fceuWrapper.h +++ b/src/drivers/Qt/fceuWrapper.h @@ -26,7 +26,7 @@ int fceuWrapperInit( int argc, char *argv[] ); int fceuWrapperClose( void ); int fceuWrapperUpdate( void ); void fceuWrapperLock(void); -bool fceuWrapperTryLock(int timeout); +bool fceuWrapperTryLock(int timeout = 1000); bool fceuWrapperIsLocked(void); void fceuWrapperUnLock(void); int fceuWrapperSoftReset(void); diff --git a/src/palette.cpp b/src/palette.cpp index 3ab97f4a..bc552d12 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -46,8 +46,8 @@ pal palette_game[64*8]; //custom palette for an individual game. (formerly palet pal palette_user[64*8]; //user's overridden palette (formerly palettec) pal palette_ntsc[64*8]; //mathematically generated NTSC palette (formerly paletten) -static bool palette_game_available; //whether palette_game is available -static bool palette_user_available; //whether palette_user is available +static bool palette_game_available=false; //whether palette_game is available +static bool palette_user_available=false; //whether palette_user is available //ntsc parameters: bool ntsccol_enable = false; //whether NTSC palette is selected From 2d4451a43c1a0292774b9d556d8e30028250359f Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 17 Jul 2020 22:14:20 -0400 Subject: [PATCH 3/3] Added logic in the emulator thread to check if requests to acquire the mutex have been made by the gui. If requests are found, the emulator thread will sleep so that the gui thread can gain access and service the requests. --- src/drivers/Qt/fceuWrapper.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index a43e3c15..b65d723d 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -57,6 +57,7 @@ static int noconfig=0; static int frameskip=0; static int periodic_saves = 0; static int mutexLocks = 0; +static int mutexPending = 0; static bool emulatorHasMutux = 0; extern double g_fpsScale; @@ -912,7 +913,9 @@ static void DoFun(int frameskip, int periodic_saves) void fceuWrapperLock(void) { + mutexPending++; consoleWindow->mutex->lock(); + mutexPending--; mutexLocks++; } @@ -920,7 +923,9 @@ bool fceuWrapperTryLock(int timeout) { bool lockAcq; + mutexPending++; lockAcq = consoleWindow->mutex->tryLock( timeout ); + mutexPending--; if ( lockAcq ) { @@ -951,6 +956,13 @@ int fceuWrapperUpdate( void ) { bool lock_acq; + // If a request is pending, + // sleep to allow request to be serviced. + if ( mutexPending > 0 ) + { + usleep( 100000 ); + } + lock_acq = fceuWrapperTryLock(); if ( !lock_acq )