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/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 c9bc21db..e8eef4f1 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" @@ -39,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); @@ -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..b02c57e5 --- /dev/null +++ b/src/drivers/Qt/PaletteConf.cpp @@ -0,0 +1,243 @@ +// 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]; + std::string paletteFile; + + // 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)) ); + + 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") ); + 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); + + if ( fceuWrapperTryLock() ) + { + 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); + + 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 (); + + 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", ""); + custom_palette_path->setText(""); + + if ( fceuWrapperTryLock() ) + { + FCEUI_SetUserPalette( NULL, 0); + fceuWrapperUnLock(); + } +} +//---------------------------------------------------- +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); + + if ( fceuWrapperTryLock() ) + { + 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/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index 7e1daca0..b65d723d 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -56,7 +56,9 @@ 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 int mutexPending = 0; +static bool emulatorHasMutux = 0; extern double g_fpsScale; @@ -78,6 +80,7 @@ int mutecapture = 0; void FCEUD_Message(const char *text) { fputs(text, stdout); + fprintf(stdout, "\n"); } /** @@ -910,29 +913,33 @@ static void DoFun(int frameskip, int periodic_saves) void fceuWrapperLock(void) { + mutexPending++; consoleWindow->mutex->lock(); - mutexLocked = 1; + mutexPending--; + mutexLocks++; } bool fceuWrapperTryLock(int timeout) { bool lockAcq; + mutexPending++; lockAcq = consoleWindow->mutex->tryLock( timeout ); + mutexPending--; if ( lockAcq ) { - mutexLocked = 1; + mutexLocks++; } return lockAcq; } void fceuWrapperUnLock(void) { - if ( mutexLocked ) + if ( mutexLocks > 0 ) { consoleWindow->mutex->unlock(); - mutexLocked = 0; + mutexLocks--; } else { @@ -942,12 +949,30 @@ void fceuWrapperUnLock(void) bool fceuWrapperIsLocked(void) { - return mutexLocked; + return mutexLocks > 0; } int fceuWrapperUpdate( void ) { - fceuWrapperLock(); + 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 ) + { + printf("Error: Emulator Failed to Acquire Mutex\n"); + usleep( 100000 ); + + return -1; + } + emulatorHasMutux = 1; if ( GameInfo && !FCEUI_EmulationPaused() ) { @@ -955,6 +980,8 @@ int fceuWrapperUpdate( void ) fceuWrapperUnLock(); + emulatorHasMutux = 0; + while ( SpeedThrottle() ) { // Input device processing is in main thread @@ -966,6 +993,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/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); } } 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