Files
RMG/Source/RMG/UserInterface/Dialog/SettingsDialog.cpp
T

1575 lines
62 KiB
C++

/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020-2025 Rosalie Wanders <rosalie@mailbox.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "UserInterface/Dialog/Netplay/NetplayCommon.hpp"
#include "UserInterface/Widget/KeybindButton.hpp"
#include "Utilities/QtMessageBox.hpp"
#include "OnScreenDisplay.hpp"
#include "SettingsDialog.hpp"
#include <QRegularExpressionValidator>
#include <QCryptographicHash>
#include <QRegularExpression>
#include <QFileDialog>
#include <QColorDialog>
#include <QDirIterator>
#include <QLabel>
#include <QDir>
#include <RMG-Core/CachedRomHeaderAndSettings.hpp>
#include <RMG-Core/Directories.hpp>
#include <RMG-Core/Emulation.hpp>
#include <RMG-Core/Settings.hpp>
#include <RMG-Core/Error.hpp>
#include <RMG-Core/Rom.hpp>
using namespace UserInterface::Dialog;
using namespace Utilities;
//
// Local Enums
//
enum class SettingsDialogTab
{
InterfaceGeneral = 0,
InterfaceEmulation = 1,
InterfaceRomBrowser = 2,
InterfaceLog = 3,
InterfaceOSD = 4,
InterfaceNetplay = 5,
Hotkey = 6,
Core = 7,
Game = 8,
GameCore = 9,
GamePlugin = 10,
Plugin = 11,
Directory = 12,
N64DD = 13,
Invalid = 14
};
//
// Exported Functions
//
SettingsDialog::SettingsDialog(QWidget *parent, QString file) : QDialog(parent)
{
this->setupUi(this);
this->setIconsForEmulationInfoText();
// if ROM is open, we should retrieve the current settings,
// if it's not opened but we got a filename, try to
// retrieve cached entries
if (CoreHasRomOpen())
{
std::filesystem::path romPath;
// only show game tab once retrieving info succeeds
this->showGameSettings = CoreGetRomPath(romPath) &&
CoreGetRomType(this->currentGameType) &&
CoreGetCurrentRomHeader(this->currentGameHeader) &&
CoreGetCurrentRomSettings(this->currentGameSettings) &&
CoreGetCurrentDefaultRomSettings(this->defaultGameSettings);
this->currentGameFile = QString::fromStdU32String(romPath.u32string());
}
else if (!file.isEmpty())
{
// only show game tab once retrieving cached entry succeeds
this->showGameSettings = CoreGetCachedRomHeaderAndSettings(file.toStdU32String(), &this->currentGameType,
&this->currentGameHeader, &this->defaultGameSettings, &this->currentGameSettings);
if (this->showGameSettings)
{
this->currentGameFile = file;
}
}
if (this->showGameSettings)
{
this->gameSection = this->currentGameSettings.MD5;
// no need to show emulation info text,
// when we're not running/paused
if (!CoreIsEmulationRunning() && !CoreIsEmulationPaused())
{
this->hideEmulationInfoText();
}
}
else
{
this->hideEmulationInfoText();
this->tabWidget->setTabEnabled(3, false);
}
pluginList = CoreGetAllPlugins();
for (int i = 0; i < static_cast<int>(SettingsDialogTab::Invalid); i++)
{
this->loadSettings(i);
}
// connect hotkey settings to slot
this->commonHotkeySettings(SettingsDialogAction::ConnectSignals);
#ifndef NETPLAY
this->innerInterfaceTabWidget->setTabVisible(static_cast<int>(SettingsDialogTab::InterfaceNetplay), false);
#endif // !NETPLAY
#ifndef UPDATER
this->checkForUpdatesCheckBox->setHidden(true);
#endif // !UPDATER
}
SettingsDialog::~SettingsDialog(void)
{
}
void SettingsDialog::ShowGameTab(void)
{
this->tabWidget->setCurrentIndex(3);
}
int SettingsDialog::currentIndex(void)
{
int currentIndex = this->tabWidget->currentIndex();
int index = currentIndex;
if (currentIndex == 0)
{ // interface tab
index += this->innerInterfaceTabWidget->currentIndex();
}
else if (currentIndex > 0)
{ // above interface tab
index += this->innerInterfaceTabWidget->count() - 1;
}
if (currentIndex == 3)
{ // game tab
index += this->innerGameTabWidget->currentIndex();
}
else if (currentIndex > 3)
{ // above game tab
index += this->innerGameTabWidget->count() - 1;
}
return index;
}
void SettingsDialog::restoreDefaults(int stackedWidgetIndex)
{
if (stackedWidgetIndex < 0 ||
stackedWidgetIndex > static_cast<int>(SettingsDialogTab::Invalid))
{
return;
}
switch (static_cast<SettingsDialogTab>(stackedWidgetIndex))
{
default:
break;
case SettingsDialogTab::InterfaceGeneral:
this->loadDefaultInterfaceGeneralSettings();
break;
case SettingsDialogTab::InterfaceEmulation:
this->loadDefaultInterfaceEmulationSettings();
break;
case SettingsDialogTab::InterfaceRomBrowser:
this->loadDefaultInterfaceRomBrowserSettings();
break;
case SettingsDialogTab::InterfaceLog:
this->loadDefaultInterfaceLogSettings();
break;
case SettingsDialogTab::InterfaceOSD:
this->loadDefaultInterfaceOSDSettings();
break;
case SettingsDialogTab::InterfaceNetplay:
this->loadDefaultInterfaceNetplaySettings();
break;
case SettingsDialogTab::Hotkey:
this->loadDefaultHotkeySettings();
break;
case SettingsDialogTab::Core:
this->loadDefaultCoreSettings();
break;
case SettingsDialogTab::Game:
this->loadDefaultGameSettings();
break;
case SettingsDialogTab::GameCore:
this->loadDefaultGameCoreSettings();
break;
case SettingsDialogTab::GamePlugin:
this->loadDefaultGamePluginSettings();
break;
case SettingsDialogTab::Plugin:
this->loadDefaultPluginSettings();
break;
case SettingsDialogTab::Directory:
this->loadDefaultDirectorySettings();
break;
case SettingsDialogTab::N64DD:
this->loadDefault64DDSettings();
break;
}
}
void SettingsDialog::loadSettings(int stackedWidgetIndex)
{
if (stackedWidgetIndex < 0 ||
stackedWidgetIndex > static_cast<int>(SettingsDialogTab::Invalid))
{
return;
}
switch (static_cast<SettingsDialogTab>(stackedWidgetIndex))
{
default:
break;
case SettingsDialogTab::InterfaceGeneral:
this->loadInterfaceGeneralSettings();
break;
case SettingsDialogTab::InterfaceEmulation:
this->loadInterfaceEmulationSettings();
break;
case SettingsDialogTab::InterfaceRomBrowser:
this->loadInterfaceRomBrowserSettings();
break;
case SettingsDialogTab::InterfaceLog:
this->loadInterfaceLogSettings();
break;
case SettingsDialogTab::InterfaceOSD:
this->loadInterfaceOSDSettings();
break;
case SettingsDialogTab::InterfaceNetplay:
this->loadInterfaceNetplaySettings();
break;
case SettingsDialogTab::Hotkey:
this->loadHotkeySettings();
break;
case SettingsDialogTab::Core:
this->loadCoreSettings();
break;
case SettingsDialogTab::Game:
this->loadGameSettings();
break;
case SettingsDialogTab::GameCore:
this->loadGameCoreSettings();
break;
case SettingsDialogTab::GamePlugin:
this->loadGamePluginSettings();
break;
case SettingsDialogTab::Plugin:
this->loadPluginSettings();
break;
case SettingsDialogTab::Directory:
this->loadDirectorySettings();
break;
case SettingsDialogTab::N64DD:
this->load64DDSettings();
break;
}
}
void SettingsDialog::loadCoreSettings(void)
{
bool disableExtraMem = CoreSettingsGetBoolValue(SettingsID::CoreOverlay_DisableExtraMem);
int counterFactor = CoreSettingsGetIntValue(SettingsID::CoreOverlay_CountPerOp);
const int cpuEmulator = CoreSettingsGetIntValue(SettingsID::CoreOverlay_CPU_Emulator);
const QString videoCaptureBackend = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::CoreOverlay_GbCameraVideoCaptureBackend1));
const int saveFilenameFormat = CoreSettingsGetIntValue(SettingsID::CoreOverLay_SaveFileNameFormat);
int siDmaDuration = CoreSettingsGetIntValue(SettingsID::CoreOverlay_SiDmaDuration);
const bool randomizeInterrupt = CoreSettingsGetBoolValue(SettingsID::CoreOverlay_RandomizeInterrupt);
const bool usePIFROM = CoreSettingsGetBoolValue(SettingsID::Core_PIF_Use);
const QString ntscPifROM = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Core_PIF_NTSC));
const QString palPifRom = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Core_PIF_PAL));
const bool overrideGameSettings = CoreSettingsGetBoolValue(SettingsID::Core_OverrideGameSpecificSettings);
this->coreCpuEmulatorComboBox->setCurrentIndex(cpuEmulator);
this->coreVideoCaptureBackendComboBox->setCurrentIndex(videoCaptureBackend == "sdl3" ? 1 : 0);
this->coreSaveFilenameFormatComboBox->setCurrentIndex(saveFilenameFormat);
this->coreRandomizeTimingCheckBox->setChecked(randomizeInterrupt);
this->usePifRomGroupBox->setChecked(usePIFROM);
this->ntscPifRomLineEdit->setText(ntscPifROM);
this->palPifRomLineEdit->setText(palPifRom);
this->coreOverrideGameSettingsGroup->setChecked(overrideGameSettings);
if (!overrideGameSettings)
{
disableExtraMem = false;
counterFactor = 2;
siDmaDuration = 2304;
}
this->coreMemorySizeComboBox->setCurrentIndex(!disableExtraMem);
this->coreCounterFactorComboBox->setCurrentIndex(counterFactor - 1);
this->coreSiDmaDurationSpinBox->setValue(siDmaDuration);
}
void SettingsDialog::loadGameSettings(void)
{
this->gameGoodNameLineEdit->setText(QString::fromStdString(this->currentGameSettings.GoodName));
this->gameMemorySizeComboBox->setCurrentIndex(!this->currentGameSettings.DisableExtraMem);
this->gameSaveTypeComboBox->setCurrentIndex(this->currentGameSettings.SaveType);
this->gameCounterFactorComboBox->setCurrentIndex(this->currentGameSettings.CountPerOp - 1);
this->gameTransferPakComboBox->setCurrentIndex(this->currentGameSettings.TransferPak);
this->gameSiDmaDurationSpinBox->setValue(this->currentGameSettings.SiDMADuration);
}
void SettingsDialog::loadGameCoreSettings(void)
{
const bool overrideEnabled = CoreSettingsGetBoolValue(SettingsID::Game_OverrideCoreSettings, this->gameSection);
const int cpuEmulator = CoreSettingsGetIntValue(SettingsID::Game_CPU_Emulator, this->gameSection);
const int overclockingFactor = CoreSettingsGetIntValue(SettingsID::Game_CountPerOpDenomPot, this->gameSection);
const bool randomizeInterrupt = CoreSettingsGetBoolValue(SettingsID::Game_RandomizeInterrupt, this->gameSection);
gameOverrideCoreSettingsGroupBox->setChecked(overrideEnabled);
gameCoreCpuEmulatorComboBox->setCurrentIndex(cpuEmulator);
gameOverclockingFactorSpinBox->setValue(overclockingFactor);
gameRandomizeTimingCheckBox->setChecked(randomizeInterrupt);
}
void SettingsDialog::loadGamePluginSettings(void)
{
QComboBox *comboBoxArray[] = {this->gameRspPluginsComboBox, this->gameVideoPluginsComboBox,
this->gameAudioPluginsComboBox, this->gameInputPluginsComboBox};
SettingsID settingsId[] = {SettingsID::Game_RSP_Plugin, SettingsID::Game_GFX_Plugin,
SettingsID::Game_AUDIO_Plugin, SettingsID::Game_INPUT_Plugin};
bool pluginFound[] = {false, false, false, false};
QString pluginFileNames[4];
QString pluginFileName;
QString pluginName;
QComboBox *comboBox;
int index = 0;
for (int i = 0; i < 4; i++)
{
pluginFileName = QString::fromStdString(CoreSettingsGetStringValue(settingsId[i], this->gameSection));
if (!pluginFileName.isEmpty())
{
// account for full path (<v0.3.5 we used the full path)
pluginFileName = QFileInfo(pluginFileName).fileName();
pluginFileNames[i] = pluginFileName;
}
}
for (QComboBox *comboBox : comboBoxArray)
{
comboBox->clear();
comboBox->addItem("**Use Core Plugin Settings**");
}
for (const auto &p : this->pluginList)
{
index = (static_cast<int>(p.Type) - 1);
comboBox = comboBoxArray[index];
comboBox->addItem(QString::fromStdString(p.Name), QString::fromStdString(p.File));
if (pluginFileNames[index] == QString::fromStdString(p.File))
{
comboBox->setCurrentText(QString::fromStdString(p.Name));
pluginFound[index] = true;
}
}
for (int i = 0; i < 4; i++)
{
comboBox = comboBoxArray[i];
if (CoreSettingsGetStringValue(settingsId[i], this->gameSection).empty())
{ // skip empty values
continue;
}
if (!pluginFound[i])
{
pluginName = pluginFileNames[i] + " (not found)";
comboBox->addItem(pluginName, pluginFileNames[i]);
comboBox->setCurrentText(pluginName);
}
}
}
void SettingsDialog::loadPluginSettings(void)
{
this->commonPluginSettings(SettingsDialogAction::LoadSettings);
}
void SettingsDialog::loadDirectorySettings(void)
{
const std::string screenshotDir = CoreSettingsGetStringValue(SettingsID::Core_ScreenshotPath);
const std::string saveStateDir = CoreSettingsGetStringValue(SettingsID::Core_SaveStatePath);
const std::string saveSramDir = CoreSettingsGetStringValue(SettingsID::Core_SaveSRAMPath);
this->screenshotDirLineEdit->setText(QString::fromStdString(screenshotDir));
this->saveStateDirLineEdit->setText(QString::fromStdString(saveStateDir));
this->saveSramDirLineEdit->setText(QString::fromStdString(saveSramDir));
}
void SettingsDialog::load64DDSettings(void)
{
const std::string japaneseIPLRom = CoreSettingsGetStringValue(SettingsID::Core_64DD_JapaneseIPL);
const std::string americanIPlRom = CoreSettingsGetStringValue(SettingsID::Core_64DD_AmericanIPL);
const std::string developmentIPLRom = CoreSettingsGetStringValue(SettingsID::Core_64DD_DevelopmentIPL);
const int saveDiskFormat = CoreSettingsGetIntValue(SettingsID::Core_64DD_SaveDiskFormat);
this->japaneseIPLRomLineEdit->setText(QString::fromStdString(japaneseIPLRom));
this->americanIPLRomLineEdit->setText(QString::fromStdString(americanIPlRom));
this->developmentIPLRomLineEdit->setText(QString::fromStdString(developmentIPLRom));
this->diskSaveTypeComboBox->setCurrentIndex(saveDiskFormat);
}
void SettingsDialog::loadHotkeySettings(void)
{
this->commonHotkeySettings(SettingsDialogAction::LoadSettings);
}
void SettingsDialog::loadInterfaceGeneralSettings(void)
{
// find stylesheets and add them to the UI
QString directory;
directory = QString::fromStdString(CoreGetSharedDataDirectory().string());
directory += CORE_DIR_SEPERATOR_STR;
directory += "Styles";
directory += CORE_DIR_SEPERATOR_STR;
QStringList filter;
filter << "*.qss";
QDirIterator stylesDirectoryIter(directory, filter, QDir::Files, QDirIterator::NoIteratorFlags);
while (stylesDirectoryIter.hasNext())
{
QFileInfo fileInfo(stylesDirectoryIter.next());
this->themeComboBox->addItem(fileInfo.fileName());
}
#ifdef _WIN32
this->themeComboBox->insertItem(1,"Windows Vista");
#endif
// select currently chosen theme in UI
this->themeComboBox->setCurrentText(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_Theme)));
this->iconThemeComboBox->setCurrentText(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::GUI_IconTheme)));
#ifdef UPDATER
this->checkForUpdatesCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_CheckForUpdates));
#endif // UPDATER
}
void SettingsDialog::loadInterfaceEmulationSettings(void)
{
this->pauseEmulationOnFocusCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss));
this->resumeEmulationOnFocusCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_ResumeEmulationOnFocus));
this->hideCursorCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_HideCursorInEmulation));
this->hideCursorFullscreenCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_HideCursorInFullscreenEmulation));
this->automaticFullscreenCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_AutomaticFullscreen));
this->confirmDragDropCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_ConfirmDragDrop));
this->confirmExitWhileInGameCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_ConfirmExitWhileInGame));
this->statusBarMessageDurationSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_StatusbarMessageDuration));
this->openglTypeComboBox->setCurrentIndex(CoreSettingsGetBoolValue(SettingsID::GUI_OpenGLES));
}
void SettingsDialog::loadInterfaceRomBrowserSettings(void)
{
this->searchSubDirectoriesCheckbox->setChecked(CoreSettingsGetBoolValue(SettingsID::RomBrowser_Recursive));
this->romSearchLimitSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::RomBrowser_MaxItems));
}
void SettingsDialog::loadInterfaceLogSettings(void)
{
this->showVerboseLogMessagesCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_ShowVerboseLogMessages));
}
void SettingsDialog::loadInterfaceOSDSettings(void)
{
this->osdEnabledCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::GUI_OnScreenDisplayEnabled));
this->osdLocationComboBox->setCurrentIndex(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayLocation));
this->osdVerticalPaddingSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayPaddingY));
this->osdHorizontalPaddingSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayPaddingX));
this->osdDurationSpinBox->setValue(CoreSettingsGetIntValue(SettingsID::GUI_OnScreenDisplayDuration));
std::vector<int> backgroundColor = CoreSettingsGetIntListValue(SettingsID::GUI_OnScreenDisplayBackgroundColor);
std::vector<int> textColor = CoreSettingsGetIntListValue(SettingsID::GUI_OnScreenDisplayTextColor);
if (backgroundColor.size() == 4)
{
this->currentBackgroundColor = QColor(backgroundColor.at(0), backgroundColor.at(1),
backgroundColor.at(2), backgroundColor.at(3));
this->chooseColor(this->changeBackgroundColorButton, &this->currentBackgroundColor, true);
}
if (textColor.size() == 4)
{
this->currentTextColor = QColor(textColor.at(0), textColor.at(1), textColor.at(2), textColor.at(3));
this->chooseColor(this->changeTextColorButton, &this->currentTextColor, true);
}
}
void SettingsDialog::loadInterfaceNetplaySettings(void)
{
// TODO: maybe add initialize functions for each tab?
static bool initialized = false;
if (!initialized)
{ // set regexp for nickname
QRegularExpression re(NETPLAYCOMMON_NICKNAME_REGEX);
this->netplayNicknameLineEdit->setValidator(new QRegularExpressionValidator(re, this));
initialized = true;
}
this->netplayNicknameLineEdit->setText(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Netplay_Nickname)));
this->netplayServerUrlLineEdit->setText(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Netplay_ServerJsonUrl)));
this->netplayDispatcherUrlLineEdit->setText(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Netplay_DispatcherUrl)));
}
void SettingsDialog::loadDefaultCoreSettings(void)
{
bool disableExtraMem = CoreSettingsGetDefaultBoolValue(SettingsID::CoreOverlay_DisableExtraMem);
int counterFactor = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverlay_CountPerOp);
const int cpuEmulator = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverlay_CPU_Emulator);
const QString videoCaptureBackend = QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::CoreOverlay_GbCameraVideoCaptureBackend1));
int siDmaDuration = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverlay_SiDmaDuration);
const int saveFilenameFormat = CoreSettingsGetDefaultIntValue(SettingsID::CoreOverLay_SaveFileNameFormat);
const bool randomizeInterrupt = CoreSettingsGetDefaultBoolValue(SettingsID::CoreOverlay_RandomizeInterrupt);
const bool usePIFROM = CoreSettingsGetDefaultBoolValue(SettingsID::Core_PIF_Use);
const QString ntscPifROM = QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_PIF_NTSC));
const QString palPifRom = QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_PIF_PAL));
const bool overrideGameSettings = CoreSettingsGetDefaultBoolValue(SettingsID::Core_OverrideGameSpecificSettings);
this->coreCpuEmulatorComboBox->setCurrentIndex(cpuEmulator);
this->coreVideoCaptureBackendComboBox->setCurrentIndex(videoCaptureBackend == "sdl3" ? 1 : 0);
this->coreSaveFilenameFormatComboBox->setCurrentIndex(saveFilenameFormat);
this->coreRandomizeTimingCheckBox->setChecked(randomizeInterrupt);
this->usePifRomGroupBox->setChecked(usePIFROM);
this->ntscPifRomLineEdit->setText(ntscPifROM);
this->palPifRomLineEdit->setText(palPifRom);
this->coreOverrideGameSettingsGroup->setChecked(overrideGameSettings);
if (!this->coreOverrideGameSettingsGroup->isChecked())
{
disableExtraMem = false;
counterFactor = 2;
siDmaDuration = 2304;
}
this->coreMemorySizeComboBox->setCurrentIndex(!disableExtraMem);
this->coreCounterFactorComboBox->setCurrentIndex(counterFactor - 1);
this->coreSiDmaDurationSpinBox->setValue(siDmaDuration);
}
void SettingsDialog::loadDefaultGameSettings(void)
{
this->gameGoodNameLineEdit->setText(QString::fromStdString(this->defaultGameSettings.GoodName));
this->gameMemorySizeComboBox->setCurrentIndex(!this->defaultGameSettings.DisableExtraMem);
this->gameSaveTypeComboBox->setCurrentIndex(this->defaultGameSettings.SaveType);
this->gameCounterFactorComboBox->setCurrentIndex(this->defaultGameSettings.CountPerOp - 1);
this->gameTransferPakComboBox->setCurrentIndex(this->defaultGameSettings.TransferPak);
this->gameSiDmaDurationSpinBox->setValue(this->defaultGameSettings.SiDMADuration);
}
void SettingsDialog::loadDefaultGameCoreSettings(void)
{
this->gameOverrideCoreSettingsGroupBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::Game_OverrideCoreSettings));
this->gameCoreCpuEmulatorComboBox->setCurrentIndex(CoreSettingsGetDefaultIntValue(SettingsID::Game_CPU_Emulator));
this->gameOverclockingFactorSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::Game_CountPerOpDenomPot));
this->gameRandomizeTimingCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::Game_RandomizeInterrupt));
}
void SettingsDialog::loadDefaultGamePluginSettings(void)
{
QComboBox *comboBoxArray[] = {this->gameVideoPluginsComboBox, this->gameAudioPluginsComboBox,
this->gameInputPluginsComboBox, this->gameRspPluginsComboBox};
for (QComboBox *comboBox : comboBoxArray)
{
comboBox->setCurrentIndex(0);
}
}
void SettingsDialog::loadDefaultPluginSettings(void)
{
this->commonPluginSettings(SettingsDialogAction::LoadDefaultSettings);
}
void SettingsDialog::loadDefaultDirectorySettings(void)
{
this->screenshotDirLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_ScreenshotPath)));
this->saveStateDirLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_SaveStatePath)));
this->saveSramDirLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_SaveSRAMPath)));
}
void SettingsDialog::loadDefault64DDSettings(void)
{
this->japaneseIPLRomLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_64DD_JapaneseIPL)));
this->americanIPLRomLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_64DD_AmericanIPL)));
this->developmentIPLRomLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Core_64DD_DevelopmentIPL)));
this->diskSaveTypeComboBox->setCurrentIndex(CoreSettingsGetDefaultIntValue(SettingsID::Core_64DD_SaveDiskFormat));
}
void SettingsDialog::loadDefaultHotkeySettings(void)
{
this->commonHotkeySettings(SettingsDialogAction::LoadDefaultSettings);
}
void SettingsDialog::loadDefaultInterfaceGeneralSettings(void)
{
this->themeComboBox->setCurrentText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::GUI_Theme)));
this->iconThemeComboBox->setCurrentText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::GUI_IconTheme)));
#ifdef UPDATER
this->checkForUpdatesCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_CheckForUpdates));
#endif // UPDATER
}
void SettingsDialog::loadDefaultInterfaceEmulationSettings(void)
{
this->pauseEmulationOnFocusCheckbox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_PauseEmulationOnFocusLoss));
this->resumeEmulationOnFocusCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_ResumeEmulationOnFocus));
this->hideCursorCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_HideCursorInEmulation));
this->hideCursorFullscreenCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_HideCursorInFullscreenEmulation));
this->automaticFullscreenCheckbox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_AutomaticFullscreen));
this->confirmDragDropCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_ConfirmDragDrop));
this->confirmExitWhileInGameCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_ConfirmExitWhileInGame));
this->statusBarMessageDurationSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_StatusbarMessageDuration));
this->openglTypeComboBox->setCurrentIndex(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_OpenGLES));
}
void SettingsDialog::loadDefaultInterfaceRomBrowserSettings(void)
{
this->searchSubDirectoriesCheckbox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::RomBrowser_Recursive));
this->romSearchLimitSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::RomBrowser_MaxItems));
}
void SettingsDialog::loadDefaultInterfaceLogSettings(void)
{
this->showVerboseLogMessagesCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_ShowVerboseLogMessages));
}
void SettingsDialog::loadDefaultInterfaceOSDSettings(void)
{
this->osdEnabledCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::GUI_OnScreenDisplayEnabled));
this->osdLocationComboBox->setCurrentIndex(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayLocation));
this->osdVerticalPaddingSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayPaddingY));
this->osdHorizontalPaddingSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayPaddingX));
this->osdDurationSpinBox->setValue(CoreSettingsGetDefaultIntValue(SettingsID::GUI_OnScreenDisplayDuration));
const std::vector<int> backgroundColor = CoreSettingsGetDefaultIntListValue(SettingsID::GUI_OnScreenDisplayBackgroundColor);
const std::vector<int> textColor = CoreSettingsGetDefaultIntListValue(SettingsID::GUI_OnScreenDisplayTextColor);
if (backgroundColor.size() == 4)
{
this->currentBackgroundColor = QColor(backgroundColor.at(0), backgroundColor.at(1),
backgroundColor.at(2), backgroundColor.at(3));
this->chooseColor(this->changeBackgroundColorButton, &this->currentBackgroundColor, true);
}
if (textColor.size() == 4)
{
this->currentTextColor = QColor(textColor.at(0), textColor.at(1), textColor.at(2), textColor.at(3));
this->chooseColor(this->changeTextColorButton, &this->currentTextColor, true);
}
}
void SettingsDialog::loadDefaultInterfaceNetplaySettings(void)
{
this->netplayNicknameLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Netplay_Nickname)));
this->netplayServerUrlLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Netplay_ServerJsonUrl)));
this->netplayDispatcherUrlLineEdit->setText(QString::fromStdString(CoreSettingsGetDefaultStringValue(SettingsID::Netplay_DispatcherUrl)));
}
void SettingsDialog::saveSettings(void)
{
this->saveCoreSettings();
if (this->showGameSettings)
{
// clean 'game settings'
CoreSettingsDeleteSection(this->gameSection);
this->saveGameSettings();
this->saveGameCoreSettings();
this->saveGamePluginSettings();
}
this->savePluginSettings();
this->saveDirectorySettings();
this->save64DDSettings();
this->saveHotkeySettings();
this->saveInterfaceGeneralSettings();
this->saveInterfaceEmulationSettings();
this->saveInterfaceRomBrowserSettings();
this->saveInterfaceLogSettings();
this->saveInterfaceOSDSettings();
this->saveInterfaceNetplaySettings();
CoreSettingsSave();
}
void SettingsDialog::saveCoreSettings(void)
{
bool disableExtraMem = (this->coreMemorySizeComboBox->currentIndex() == 0);
int counterFactor = this->coreCounterFactorComboBox->currentIndex() + 1;
const int cpuEmulator = this->coreCpuEmulatorComboBox->currentIndex();
const int videoCaptureBackend = this->coreVideoCaptureBackendComboBox->currentIndex();
const int saveFilenameFormat = this->coreSaveFilenameFormatComboBox->currentIndex();
int siDmaDuration = this->coreSiDmaDurationSpinBox->value();
const bool randomizeInterrupt = this->coreRandomizeTimingCheckBox->isChecked();
const bool usePIF = this->usePifRomGroupBox->isChecked();
const QString ntscPifROM = this->ntscPifRomLineEdit->text();
const QString palPifROM = this->palPifRomLineEdit->text();
const bool overrideGameSettings = this->coreOverrideGameSettingsGroup->isChecked();
CoreSettingsSetValue(SettingsID::CoreOverlay_CPU_Emulator, cpuEmulator);
CoreSettingsSetValue(SettingsID::CoreOverlay_GbCameraVideoCaptureBackend1, std::string((videoCaptureBackend == 1) ? "sdl3" : ""));
CoreSettingsSetValue(SettingsID::CoreOverLay_SaveFileNameFormat, saveFilenameFormat);
CoreSettingsSetValue(SettingsID::CoreOverlay_RandomizeInterrupt, randomizeInterrupt);
CoreSettingsSetValue(SettingsID::Core_PIF_Use, usePIF);
CoreSettingsSetValue(SettingsID::Core_PIF_NTSC, ntscPifROM.toStdString());
CoreSettingsSetValue(SettingsID::Core_PIF_PAL, palPifROM.toStdString());
CoreSettingsSetValue(SettingsID::Core_OverrideGameSpecificSettings, overrideGameSettings);
if (!overrideGameSettings)
{
disableExtraMem = false;
counterFactor = 0;
siDmaDuration = -1;
}
CoreSettingsSetValue(SettingsID::CoreOverlay_DisableExtraMem, disableExtraMem);
CoreSettingsSetValue(SettingsID::CoreOverlay_CountPerOp, counterFactor);
CoreSettingsSetValue(SettingsID::CoreOverlay_SiDmaDuration, siDmaDuration);
}
void SettingsDialog::saveGameSettings(void)
{
const bool disableExtraMem = this->gameMemorySizeComboBox->currentIndex() == 0;
const int saveType = this->gameSaveTypeComboBox->currentIndex();
const int countPerOp = this->gameCounterFactorComboBox->currentIndex() + 1;
const bool transferPak = this->gameTransferPakComboBox->currentIndex() != 0;
const int siDmaDuration = this->gameSiDmaDurationSpinBox->value();
if ((this->defaultGameSettings.DisableExtraMem != disableExtraMem) ||
(this->defaultGameSettings.SaveType != saveType) ||
(this->defaultGameSettings.CountPerOp != countPerOp) ||
(this->defaultGameSettings.TransferPak != transferPak) ||
(this->defaultGameSettings.SiDMADuration != siDmaDuration))
{
CoreSettingsSetValue(SettingsID::Game_OverrideSettings, this->gameSection, true);
CoreSettingsSetValue(SettingsID::Game_TransferPak, this->gameSection, transferPak);
CoreSettingsSetValue(SettingsID::Game_DisableExtraMem, this->gameSection, disableExtraMem);
CoreSettingsSetValue(SettingsID::Game_SaveType, this->gameSection, saveType);
CoreSettingsSetValue(SettingsID::Game_CountPerOp, this->gameSection, countPerOp);
CoreSettingsSetValue(SettingsID::Game_SiDmaDuration, this->gameSection, siDmaDuration);
}
// update cache when needed
if (!this->currentGameFile.isEmpty())
{
CoreRomSettings romSettings = this->currentGameSettings;
romSettings.SaveType = saveType;
romSettings.DisableExtraMem = disableExtraMem;
romSettings.CountPerOp = countPerOp;
romSettings.TransferPak = transferPak;
romSettings.SiDMADuration = siDmaDuration;
CoreUpdateCachedRomHeaderAndSettings(this->currentGameFile.toStdU32String(), this->currentGameType, this->currentGameHeader, this->defaultGameSettings, romSettings);
}
}
void SettingsDialog::saveGameCoreSettings(void)
{
const bool overrideEnabled = gameOverrideCoreSettingsGroupBox->isChecked();
const int cpuEmulator = gameCoreCpuEmulatorComboBox->currentIndex();
const int overclockingFactor = gameOverclockingFactorSpinBox->value();
const bool randomizeInterrupt = gameRandomizeTimingCheckBox->isChecked();
const bool defaultOverrideEnabled = CoreSettingsGetDefaultBoolValue(SettingsID::Game_OverrideCoreSettings);
const int defaultCpuEmulator = CoreSettingsGetDefaultIntValue(SettingsID::Game_CPU_Emulator);
const int defaultoverclockingFactor = CoreSettingsGetDefaultIntValue(SettingsID::Game_CountPerOpDenomPot);
const bool defaultRandomizeInterrupt = CoreSettingsGetDefaultBoolValue(SettingsID::Game_RandomizeInterrupt);
if ((defaultOverrideEnabled != overrideEnabled) ||
(defaultCpuEmulator != cpuEmulator) ||
(defaultoverclockingFactor != overclockingFactor) ||
(defaultRandomizeInterrupt != randomizeInterrupt))
{
CoreSettingsSetValue(SettingsID::Game_OverrideCoreSettings, this->gameSection, overrideEnabled);
CoreSettingsSetValue(SettingsID::Game_CPU_Emulator, this->gameSection, cpuEmulator);
CoreSettingsSetValue(SettingsID::Game_CountPerOpDenomPot, this->gameSection, overclockingFactor);
CoreSettingsSetValue(SettingsID::Game_RandomizeInterrupt, this->gameSection, randomizeInterrupt);
}
}
void SettingsDialog::saveGamePluginSettings(void)
{
QComboBox *comboBoxArray[] = {this->gameVideoPluginsComboBox, this->gameAudioPluginsComboBox,
this->gameInputPluginsComboBox, this->gameRspPluginsComboBox};
SettingsID settingsIdArray[] = {SettingsID::Game_GFX_Plugin, SettingsID::Game_AUDIO_Plugin,
SettingsID::Game_INPUT_Plugin, SettingsID::Game_RSP_Plugin};
QComboBox *comboBox;
SettingsID id;
for (int i = 0; i < 4; i++)
{
comboBox = comboBoxArray[i];
id = settingsIdArray[i];
if (comboBox->currentIndex() != 0)
{
CoreSettingsSetValue(id, this->gameSection, comboBox->currentData().toString().toStdString());
}
}
}
void SettingsDialog::savePluginSettings(void)
{
QComboBox *comboBoxArray[] = {this->videoPluginsComboBox, this->audioPluginsComboBox, this->inputPluginsComboBox,
this->rspPluginsComboBox};
SettingsID settings[] = {SettingsID::Core_GFX_Plugin, SettingsID::Core_AUDIO_Plugin,
SettingsID::Core_INPUT_Plugin, SettingsID::Core_RSP_Plugin};
QComboBox *comboBox;
SettingsID settingId;
for (int i = 0; i < 4; i++)
{
comboBox = comboBoxArray[i];
settingId = settings[i];
CoreSettingsSetValue(settingId, comboBox->currentData().toString().toStdString());
}
}
void SettingsDialog::saveDirectorySettings(void)
{
CoreSettingsSetValue(SettingsID::Core_ScreenshotPath, this->screenshotDirLineEdit->text().toStdString());
CoreSettingsSetValue(SettingsID::Core_SaveStatePath, this->saveStateDirLineEdit->text().toStdString());
CoreSettingsSetValue(SettingsID::Core_SaveSRAMPath, this->saveSramDirLineEdit->text().toStdString());
}
void SettingsDialog::save64DDSettings(void)
{
CoreSettingsSetValue(SettingsID::Core_64DD_JapaneseIPL, this->japaneseIPLRomLineEdit->text().toStdString());
CoreSettingsSetValue(SettingsID::Core_64DD_AmericanIPL, this->americanIPLRomLineEdit->text().toStdString());
CoreSettingsSetValue(SettingsID::Core_64DD_DevelopmentIPL, this->developmentIPLRomLineEdit->text().toStdString());
CoreSettingsSetValue(SettingsID::Core_64DD_SaveDiskFormat, this->diskSaveTypeComboBox->currentIndex());
}
void SettingsDialog::saveHotkeySettings(void)
{
this->commonHotkeySettings(SettingsDialogAction::SaveSettings);
}
void SettingsDialog::saveInterfaceGeneralSettings(void)
{
CoreSettingsSetValue(SettingsID::GUI_Theme, this->themeComboBox->currentText().toStdString());
CoreSettingsSetValue(SettingsID::GUI_IconTheme, this->iconThemeComboBox->currentText().toStdString());
#ifdef UPDATER
CoreSettingsSetValue(SettingsID::GUI_CheckForUpdates, this->checkForUpdatesCheckBox->isChecked());
#endif // UPDATER
}
void SettingsDialog::saveInterfaceEmulationSettings(void)
{
CoreSettingsSetValue(SettingsID::GUI_HideCursorInEmulation, this->hideCursorCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_HideCursorInFullscreenEmulation, this->hideCursorFullscreenCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_PauseEmulationOnFocusLoss, this->pauseEmulationOnFocusCheckbox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_ResumeEmulationOnFocus, this->resumeEmulationOnFocusCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_AutomaticFullscreen, this->automaticFullscreenCheckbox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_ConfirmDragDrop, this->confirmDragDropCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_ConfirmExitWhileInGame, this->confirmExitWhileInGameCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_StatusbarMessageDuration, this->statusBarMessageDurationSpinBox->value());
CoreSettingsSetValue(SettingsID::GUI_OpenGLES, this->openglTypeComboBox->currentIndex() == 1);
}
void SettingsDialog::saveInterfaceRomBrowserSettings(void)
{
CoreSettingsSetValue(SettingsID::RomBrowser_Recursive, this->searchSubDirectoriesCheckbox->isChecked());
CoreSettingsSetValue(SettingsID::RomBrowser_MaxItems, this->romSearchLimitSpinBox->value());
}
void SettingsDialog::saveInterfaceLogSettings(void)
{
CoreSettingsSetValue(SettingsID::GUI_ShowVerboseLogMessages, this->showVerboseLogMessagesCheckBox->isChecked());
}
void SettingsDialog::saveInterfaceOSDSettings(void)
{
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayEnabled, this->osdEnabledCheckBox->isChecked());
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayLocation, this->osdLocationComboBox->currentIndex());
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayPaddingY, this->osdVerticalPaddingSpinBox->value());
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayPaddingX, this->osdHorizontalPaddingSpinBox->value());
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayDuration, this->osdDurationSpinBox->value());
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayBackgroundColor, std::vector<int>({ this->currentBackgroundColor.red(),
this->currentBackgroundColor.green(),
this->currentBackgroundColor.blue(),
this->currentBackgroundColor.alpha()
}));
CoreSettingsSetValue(SettingsID::GUI_OnScreenDisplayTextColor, std::vector<int>({ this->currentTextColor.red(),
this->currentTextColor.green(),
this->currentTextColor.blue(),
this->currentTextColor.alpha()
}));
}
void SettingsDialog::saveInterfaceNetplaySettings(void)
{
CoreSettingsSetValue(SettingsID::Netplay_Nickname, this->netplayNicknameLineEdit->text().toStdString());
CoreSettingsSetValue(SettingsID::Netplay_ServerJsonUrl, this->netplayServerUrlLineEdit->text().toStdString());
CoreSettingsSetValue(SettingsID::Netplay_DispatcherUrl, this->netplayDispatcherUrlLineEdit->text().toStdString());
}
void SettingsDialog::commonHotkeySettings(SettingsDialogAction action)
{
struct keybinding
{
KeybindButton* button;
SettingsID settingId;
};
std::vector<keybinding> keybindings;
std::vector<keybinding> keybindings_System =
{
{ this->startRomKeyButton, SettingsID::KeyBinding_StartROM },
{ this->startComboKeyButton, SettingsID::KeyBinding_StartCombo },
{ this->shutdownKeyButton, SettingsID::KeyBinding_Shutdown },
{ this->refreshRomListKeyButton, SettingsID::KeyBinding_RefreshROMList },
{ this->exitKeyButton, SettingsID::KeyBinding_Exit },
{ this->softResetKeyButton, SettingsID::KeyBinding_SoftReset },
{ this->hardResetKeyButton, SettingsID::KeyBinding_HardReset },
{ this->pauseKeyButton, SettingsID::KeyBinding_Resume },
{ this->generateBitmapKeyButton, SettingsID::KeyBinding_Screenshot },
{ this->limitFPSKeyButton, SettingsID::KeyBinding_LimitFPS },
{ this->saveStateKeyButton, SettingsID::KeyBinding_SaveState },
{ this->saveAsKeyButton, SettingsID::KeyBinding_SaveAs },
{ this->loadStateKeyButton, SettingsID::KeyBinding_LoadState },
{ this->loadKeyButton, SettingsID::KeyBinding_Load },
{ this->cheatsKeyButton, SettingsID::KeyBinding_Cheats },
{ this->gsButtonKeyButton, SettingsID::KeyBinding_GSButton },
};
std::vector<keybinding> keybindings_SpeedFactor =
{
{ this->speedFactor25KeyButton, SettingsID::KeyBinding_SpeedFactor25 },
{ this->speedFactor50KeyButton, SettingsID::KeyBinding_SpeedFactor50 },
{ this->speedFactor75KeyButton, SettingsID::KeyBinding_SpeedFactor75 },
{ this->speedFactor100KeyButton, SettingsID::KeyBinding_SpeedFactor100 },
{ this->speedFactor125KeyButton, SettingsID::KeyBinding_SpeedFactor125 },
{ this->speedFactor150KeyButton, SettingsID::KeyBinding_SpeedFactor150 },
{ this->speedFactor175KeyButton, SettingsID::KeyBinding_SpeedFactor175 },
{ this->speedFactor200KeyButton, SettingsID::KeyBinding_SpeedFactor200 },
{ this->speedFactor225KeyButton, SettingsID::KeyBinding_SpeedFactor225 },
{ this->speedFactor250KeyButton, SettingsID::KeyBinding_SpeedFactor250 },
{ this->speedFactor275KeyButton, SettingsID::KeyBinding_SpeedFactor275 },
{ this->speedFactor300KeyButton, SettingsID::KeyBinding_SpeedFactor300 },
};
std::vector<keybinding> keybindings_CurrentSaveState =
{
{ this->saveState0KeyButton, SettingsID::KeyBinding_SaveStateSlot0 },
{ this->saveState1KeyButton, SettingsID::KeyBinding_SaveStateSlot1 },
{ this->saveState2KeyButton, SettingsID::KeyBinding_SaveStateSlot2 },
{ this->saveState3KeyButton, SettingsID::KeyBinding_SaveStateSlot3 },
{ this->saveState4KeyButton, SettingsID::KeyBinding_SaveStateSlot4 },
{ this->saveState5KeyButton, SettingsID::KeyBinding_SaveStateSlot5 },
{ this->saveState6KeyButton, SettingsID::KeyBinding_SaveStateSlot6 },
{ this->saveState7KeyButton, SettingsID::KeyBinding_SaveStateSlot7 },
{ this->saveState8KeyButton, SettingsID::KeyBinding_SaveStateSlot8 },
{ this->saveState9KeyButton, SettingsID::KeyBinding_SaveStateSlot9 },
};
std::vector<keybinding> keybindings_Audio =
{
{ this->increaseVolumeKeyButton, SettingsID::KeyBinding_IncreaseVolume },
{ this->decreaseVolumeKeyButton, SettingsID::KeyBinding_DecreaseVolume },
{ this->muteVolumeKeyButton, SettingsID::KeyBinding_ToggleMuteVolume },
};
std::vector<keybinding> keybindings_Settings =
{
{ this->graphicsSettingsKeyButton, SettingsID::KeyBinding_GraphicsSettings },
{ this->audioSettingsKeyButton, SettingsID::KeyBinding_AudioSettings },
{ this->rspSettingsKeyButton, SettingsID::KeyBinding_RspSettings },
{ this->inputSettingsKeyButton, SettingsID::KeyBinding_InputSettings },
{ this->settingsKeyButton, SettingsID::KeyBinding_Settings },
};
std::vector<keybinding> keybindings_View =
{
{ this->fullscreenKeyButton, SettingsID::KeyBinding_Fullscreen },
{ this->logKeyButton, SettingsID::KeyBinding_ViewLog },
{ this->refreshRomListKeyButton, SettingsID::KeyBinding_RefreshROMList },
{ this->searchKeyButton, SettingsID::KeyBinding_ViewSearch }
};
if (action == SettingsDialogAction::LoadDefaultSettings)
{
int index = this->keybindingsMenuTabWidget->currentIndex();
switch (index)
{
default:
case 0:
keybindings.insert(keybindings.end(), keybindings_System.begin(), keybindings_System.end());
break;
case 1:
keybindings.insert(keybindings.end(), keybindings_SpeedFactor.begin(), keybindings_SpeedFactor.end());
break;
case 2:
keybindings.insert(keybindings.end(), keybindings_CurrentSaveState.begin(), keybindings_CurrentSaveState.end());
break;
case 3:
keybindings.insert(keybindings.end(), keybindings_Audio.begin(), keybindings_Audio.end());
break;
case 4:
keybindings.insert(keybindings.end(), keybindings_Settings.begin(), keybindings_Settings.end());
break;
case 5:
keybindings.insert(keybindings.end(), keybindings_View.begin(), keybindings_View.end());
break;
}
}
else
{
keybindings.insert(keybindings.end(), keybindings_System.begin(), keybindings_System.end());
keybindings.insert(keybindings.end(), keybindings_SpeedFactor.begin(), keybindings_SpeedFactor.end());
keybindings.insert(keybindings.end(), keybindings_CurrentSaveState.begin(), keybindings_CurrentSaveState.end());
keybindings.insert(keybindings.end(), keybindings_Audio.begin(), keybindings_Audio.end());
keybindings.insert(keybindings.end(), keybindings_Settings.begin(), keybindings_Settings.end());
keybindings.insert(keybindings.end(), keybindings_View.begin(), keybindings_View.end());
}
switch (action)
{
default:
break;
case SettingsDialogAction::LoadSettings:
this->removeDuplicateHotkeysCheckBox->setChecked(CoreSettingsGetBoolValue(SettingsID::KeyBinding_RemoveDuplicates));
break;
case SettingsDialogAction::LoadDefaultSettings:
this->removeDuplicateHotkeysCheckBox->setChecked(CoreSettingsGetDefaultBoolValue(SettingsID::KeyBinding_RemoveDuplicates));
break;
case SettingsDialogAction::SaveSettings:
CoreSettingsSetValue(SettingsID::KeyBinding_RemoveDuplicates, this->removeDuplicateHotkeysCheckBox->isChecked());
break;
}
for (const auto& keybinding : keybindings)
{
switch (action)
{
default:
case SettingsDialogAction::ConnectSignals:
connect(keybinding.button, &KeybindButton::KeybindingChanged, this, &SettingsDialog::on_KeybindButton_KeybindingChanged);
connect(keybinding.button, &KeybindButton::Clicked, this, &SettingsDialog::on_KeybindButton_Clicked);
break;
case SettingsDialogAction::LoadSettings:
keybinding.button->SetText(QString::fromStdString(CoreSettingsGetStringValue(keybinding.settingId)));
break;
case SettingsDialogAction::LoadDefaultSettings:
keybinding.button->SetText(QString::fromStdString(CoreSettingsGetDefaultStringValue(keybinding.settingId)));
break;
case SettingsDialogAction::SaveSettings:
CoreSettingsSetValue(keybinding.settingId, keybinding.button->GetCurrentText().toStdString());
break;
}
}
}
void SettingsDialog::commonPluginSettings(SettingsDialogAction action)
{
QComboBox *comboBoxArray[] = {this->rspPluginsComboBox, this->videoPluginsComboBox,
this->audioPluginsComboBox, this->inputPluginsComboBox};
SettingsID settingsIdArray[] = {SettingsID::Core_RSP_Plugin, SettingsID::Core_GFX_Plugin,
SettingsID::Core_AUDIO_Plugin, SettingsID::Core_INPUT_Plugin};
bool pluginFound[] = {false, false, false, false};
QString pluginFileNames[4];
QComboBox *comboBox;
QString pluginName;
QString pluginFileName;
int index = 0;
// clear combobox items
for (const auto& c : comboBoxArray)
{
c->clear();
}
for (int i = 0; i < 4; i++)
{
pluginFileName = action == SettingsDialogAction::LoadSettings ?
QString::fromStdString(CoreSettingsGetStringValue(settingsIdArray[i])) :
QString::fromStdString(CoreSettingsGetDefaultStringValue(settingsIdArray[i]));
// account for full path (<v0.3.5 we used the full path)
pluginFileName = QFileInfo(pluginFileName).fileName();
pluginFileNames[i] = pluginFileName;
}
for (const auto &p : this->pluginList)
{
index = (static_cast<int>(p.Type) - 1);
comboBox = comboBoxArray[index];
pluginFileName = pluginFileNames[index];
pluginName = QString::fromStdString(p.Name);
comboBox->addItem(pluginName, QString::fromStdString(p.File));
if (pluginFileName == QString::fromStdString(p.File))
{
comboBox->setCurrentText(pluginName);
pluginFound[index] = true;
}
}
for (int i = 0; i < 4; i++)
{
comboBox = comboBoxArray[i];
if (!pluginFound[i])
{
pluginName = pluginFileNames[i] + " (not found)";
comboBox->addItem(pluginName, pluginFileNames[i]);
comboBox->setCurrentText(pluginName);
}
else
{ // find duplicates and append filename
for (int i = 0; i < comboBox->count(); i++)
{
pluginName = comboBox->itemText(i);
bool foundDuplicate = false;
for (int x = i + 1; x < comboBox->count(); x++)
{
if (comboBox->itemText(x) == pluginName)
{
pluginFileName = QFileInfo(comboBox->itemData(x).toString()).fileName();
comboBox->setItemText(x, pluginName + " (" + pluginFileName + ")");
foundDuplicate = true;
}
}
if (foundDuplicate)
{
pluginFileName = QFileInfo(comboBox->itemData(i).toString()).fileName();
comboBox->setItemText(i, pluginName + " (" + pluginFileName + ")");
}
}
}
}
}
void SettingsDialog::setIconsForEmulationInfoText(void)
{
QLabel* labels[] = {
this->infoIconLabel_0, this->infoIconLabel_1, this->infoIconLabel_2,
this->infoIconLabel_3, this->infoIconLabel_4, this->infoIconLabel_5,
this->infoIconLabel_7, this->infoIconLabel_6, this->infoIconLabel_8,
this->infoIconLabel_9
};
QIcon infoIcon = QIcon::fromTheme("information-line");
QPixmap infoIconPixmap = infoIcon.pixmap(16, 16);
for (QLabel* label : labels)
{
label->setPixmap(infoIconPixmap);
}
}
void SettingsDialog::hideEmulationInfoText(void)
{
QHBoxLayout *layouts[] = {this->emulationInfoLayout_0, this->emulationInfoLayout_1,
this->emulationInfoLayout_2, this->emulationInfoLayout_3,
this->emulationInfoLayout_9};
for (const auto &layout : layouts)
{
for (int i = 0; i < layout->count(); i++)
{
QWidget *widget = layout->itemAt(i)->widget();
widget->hide();
}
}
}
void SettingsDialog::chooseDirectory(QLineEdit *lineEdit, QString caption)
{
QString currentDir = lineEdit->text();
if (!QDir(currentDir).exists())
{
currentDir = "";
}
QString dir = QFileDialog::getExistingDirectory(this, caption, currentDir);
if (dir.isEmpty())
{
return;
}
lineEdit->setText(QDir::toNativeSeparators(dir));
}
void SettingsDialog::chooseFile(QLineEdit *lineEdit, QString caption, QString filter, QStringList md5List)
{
QString file = QFileDialog::getOpenFileName(this, caption, "", filter);
if (file.isEmpty())
{
return;
}
if (!md5List.isEmpty())
{
QFile qFile(file);
if (!qFile.open(QFile::ReadOnly))
{
QtMessageBox::Error(this, "Failed to open file", "QFile::open() Failed");
return;
}
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
if (!hash.addData(&qFile))
{
QtMessageBox::Error(this, "MD5 hashing failed", "QCryptographicHash::addData() Failed");
return;
}
QString md5Hash = QString(hash.result().toHex());
bool hashFound = false;
for (const QString& md5 : md5List)
{
if (md5Hash == md5)
{
hashFound = true;
break;
}
}
if (!hashFound)
{
QtMessageBox::Error(this, "MD5 mismatch", "Expected file with MD5: \"" + md5List.first() + "\"");
return;
}
}
lineEdit->setText(QDir::toNativeSeparators(file));
}
void SettingsDialog::chooseColor(QPushButton *pushButton, QColor *initialColor, bool skipChoice)
{
QColor color = QColor::Invalid;
if (skipChoice)
{
color = *initialColor;
}
else
{
color = QColorDialog::getColor(*initialColor, this, "", QColorDialog::ColorDialogOption::ShowAlphaChannel);
}
if (!color.isValid())
{
return;
}
pushButton->setStyleSheet("background-color: " + color.name());
*initialColor = color;
}
bool SettingsDialog::applyPluginSettings(void)
{
// attempt to apply plugin settings when emulation
// isn't running, when it fails, show the user the error and
// don't allow the user to save invalid settings
if (!CoreIsEmulationPaused() && !CoreIsEmulationRunning())
{
if (!CoreApplyPluginSettings())
{
QtMessageBox::Error(this, "CoreApplyPluginSettings() Failed", QString::fromStdString(CoreGetError()));
return false;
}
}
return true;
}
void SettingsDialog::closeEvent(QCloseEvent* event)
{
if (this->applyPluginSettings())
{
event->accept();
}
else
{
event->ignore();
}
}
void SettingsDialog::timerEvent(QTimerEvent* event)
{
this->keybindButtonTimeLeft--;
if (this->currentKeybindButton != nullptr)
{
this->currentKeybindButton->SetSecondsLeft(this->keybindButtonTimeLeft);
}
if (this->keybindButtonTimeLeft == 0)
{
this->killTimer(this->keybindButtonTimerId);
this->keybindButtonTimerId = -1;
this->currentKeybindButton = nullptr;
}
}
void SettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
{
QPushButton *pushButton = (QPushButton *)button;
QPushButton *defaultButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
QPushButton *cancelButton = this->buttonBox->button(QDialogButtonBox::Cancel);
QPushButton *okButton = this->buttonBox->button(QDialogButtonBox::Ok);
if (pushButton == cancelButton || pushButton == okButton)
{
if (pushButton == okButton)
{
this->saveSettings();
// re-load OSD settings
OnScreenDisplayLoadSettings();
}
if (!this->applyPluginSettings())
{
return;
}
}
if (pushButton == defaultButton)
{
this->restoreDefaults(this->currentIndex());
}
else if (pushButton == cancelButton)
{
this->reject();
}
else if (pushButton == okButton)
{
this->accept();
}
}
void SettingsDialog::on_changeScreenShotDirButton_clicked(void)
{
this->chooseDirectory(this->screenshotDirLineEdit, tr("Select Screenshot Directory"));
}
void SettingsDialog::on_changeSaveStateDirButton_clicked(void)
{
this->chooseDirectory(this->saveStateDirLineEdit, tr("Select Save (State) Directory"));
}
void SettingsDialog::on_changeSaveSramDirButton_clicked(void)
{
this->chooseDirectory(this->saveSramDirLineEdit, tr("Select Save (SRAM) Directory"));
}
void SettingsDialog::on_changeJapaneseIPLRomPathButton_clicked(void)
{
this->chooseFile(this->japaneseIPLRomLineEdit, tr("Open Japanese Retail 64DD IPL"), "IPL ROMs (*.n64)");
}
void SettingsDialog::on_changeAmericanIPLRomPathButton_clicked(void)
{
this->chooseFile(this->americanIPLRomLineEdit, tr("Open American Retail 64DD IPL"), "IPL ROMs (*.n64)");
}
void SettingsDialog::on_changeDevelopmentIPLRomPathButton_clicked(void)
{
this->chooseFile(this->developmentIPLRomLineEdit, tr("Open Japanese Development 64DD IPL"), "IPL ROMs (*.n64)");
}
void SettingsDialog::on_clearJapaneseIPLRomPathButton_clicked(void)
{
this->japaneseIPLRomLineEdit->clear();
}
void SettingsDialog::on_clearAmericanIPLRomPathButton_clicked(void)
{
this->americanIPLRomLineEdit->clear();
}
void SettingsDialog::on_clearDevelopmentIPLRomPathButton_clicked(void)
{
this->developmentIPLRomLineEdit->clear();
}
void SettingsDialog::on_changeBackgroundColorButton_clicked(void)
{
this->chooseColor(this->changeBackgroundColorButton, &this->currentBackgroundColor);
}
void SettingsDialog::on_changeTextColorButton_clicked(void)
{
this->chooseColor(this->changeTextColorButton, &this->currentTextColor);
}
void SettingsDialog::on_KeybindButton_KeybindingChanged(KeybindButton* button)
{
if (this->keybindButtonTimerId != -1)
{
this->killTimer(this->keybindButtonTimerId);
this->keybindButtonTimerId = -1;
}
if (this->currentKeybindButton != nullptr)
{
this->currentKeybindButton->Reset();
this->currentKeybindButton = nullptr;
}
if (!this->removeDuplicateHotkeysCheckBox->isChecked())
{
return;
}
QString text = button->GetCurrentText();
if (text.isEmpty())
{
return;
}
QList<KeybindButton*> rombrowserKeybindButtons =
{
this->startRomKeyButton,
this->startComboKeyButton,
this->shutdownKeyButton,
this->exitKeyButton,
this->graphicsSettingsKeyButton,
this->audioSettingsKeyButton,
this->rspSettingsKeyButton,
this->inputSettingsKeyButton,
this->settingsKeyButton,
this->logKeyButton,
this->refreshRomListKeyButton,
};
QList<KeybindButton*> emulationKeybindButtons =
{
this->shutdownKeyButton,
this->softResetKeyButton,
this->hardResetKeyButton,
this->pauseKeyButton,
this->generateBitmapKeyButton,
this->limitFPSKeyButton,
this->speedFactor25KeyButton,
this->speedFactor50KeyButton,
this->speedFactor75KeyButton,
this->speedFactor100KeyButton,
this->speedFactor125KeyButton,
this->speedFactor150KeyButton,
this->speedFactor175KeyButton,
this->speedFactor200KeyButton,
this->speedFactor225KeyButton,
this->speedFactor250KeyButton,
this->speedFactor275KeyButton,
this->speedFactor300KeyButton,
this->saveStateKeyButton,
this->saveAsKeyButton,
this->loadStateKeyButton,
this->loadKeyButton,
this->cheatsKeyButton,
this->gsButtonKeyButton,
this->saveState0KeyButton,
this->saveState1KeyButton,
this->saveState2KeyButton,
this->saveState3KeyButton,
this->saveState4KeyButton,
this->saveState5KeyButton,
this->saveState6KeyButton,
this->saveState7KeyButton,
this->saveState8KeyButton,
this->saveState9KeyButton,
this->increaseVolumeKeyButton,
this->decreaseVolumeKeyButton,
this->muteVolumeKeyButton,
this->exitKeyButton,
this->graphicsSettingsKeyButton,
this->audioSettingsKeyButton,
this->rspSettingsKeyButton,
this->inputSettingsKeyButton,
this->settingsKeyButton,
this->logKeyButton,
this->fullscreenKeyButton,
};
QList<KeybindButton*> keybindButtons;
if (rombrowserKeybindButtons.contains(button))
{
keybindButtons.append(rombrowserKeybindButtons);
}
if (emulationKeybindButtons.contains(button))
{
keybindButtons.append(emulationKeybindButtons);
}
for (KeybindButton* keybindButton : keybindButtons)
{
if (keybindButton != button)
{
if (keybindButton->GetCurrentText() == text)
{
keybindButton->Clear();
}
}
}
}
void SettingsDialog::on_KeybindButton_Clicked(KeybindButton* button)
{
if (this->currentKeybindButton == button)
{
return;
}
if (this->currentKeybindButton != nullptr)
{
this->currentKeybindButton->Reset();
this->currentKeybindButton = nullptr;
}
if (this->keybindButtonTimerId != -1)
{
this->killTimer(this->keybindButtonTimerId);
this->keybindButtonTimerId = -1;
}
this->currentKeybindButton = button;
this->keybindButtonTimeLeft = 5;
this->keybindButtonTimerId = this->startTimer(1000);
// notify button
this->currentKeybindButton->SetSecondsLeft(5);
}
void SettingsDialog::on_coreCpuEmulatorComboBox_currentIndexChanged(int index)
{
// hide PIF ROM options when using dynamic recompiler
// because the dynarec crashes when using a PIF ROM
this->usePifRomGroupBox->setVisible(index != 2);
}
void SettingsDialog::on_changeNTSCPifRomButton_clicked(void)
{
this->chooseFile(this->ntscPifRomLineEdit, tr("Open NTSC PIF ROM"), "PIF ROMs (*.rom)", { "5C124E7948ADA85DA603A522782940D0", "4921D5F2165DEE6E2496F4388C4C81DA" });
}
void SettingsDialog::on_changePALPifRomButton_clicked(void)
{
this->chooseFile(this->palPifRomLineEdit, tr("Open PAL PIF ROM"), "PIF ROMs (*.rom)", { "D4232DC935CAD0650AC2664D52281F3A", "2B6EEC586FAA43F3462333B844834554" });
}