diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index 73fd776468..63eefe3938 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -84,6 +84,7 @@ set(SRCS QtUtils/ElidedButton.cpp QtUtils/ListTabWidget.cpp QtUtils/WindowActivationEventFilter.cpp + Settings/AdvancedPane.cpp Settings/AudioPane.cpp Settings/GeneralPane.cpp Settings/InterfacePane.cpp diff --git a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp index 0ac1fe5cc6..7bc5071527 100644 --- a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp @@ -10,6 +10,7 @@ #include "DolphinQt2/QtUtils/ListTabWidget.h" #include "DolphinQt2/Resources.h" #include "DolphinQt2/Settings.h" +#include "DolphinQt2/Settings/AdvancedPane.h" #include "DolphinQt2/Settings/AudioPane.h" #include "DolphinQt2/Settings/GeneralPane.h" #include "DolphinQt2/Settings/InterfacePane.h" @@ -42,6 +43,7 @@ SettingsWindow::SettingsWindow(QWidget* parent) : QDialog(parent) AddTab(m_tabs, tr("Interface"), new InterfacePane(), "browse"); m_audio_pane_index = AddTab(m_tabs, tr("Audio"), new AudioPane(), "play"); AddTab(m_tabs, tr("Paths"), new PathPane(), "browse"); + AddTab(m_tabs, tr("Advanced"), new AdvancedPane(), "config"); // Dialog box buttons QDialogButtonBox* ok_box = new QDialogButtonBox(QDialogButtonBox::Ok); diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index be07c59b2a..e6fc2256c9 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -103,12 +103,14 @@ + + @@ -216,6 +218,7 @@ + diff --git a/Source/Core/DolphinQt2/Settings/AdvancedPane.cpp b/Source/Core/DolphinQt2/Settings/AdvancedPane.cpp new file mode 100644 index 0000000000..b73ce582bd --- /dev/null +++ b/Source/Core/DolphinQt2/Settings/AdvancedPane.cpp @@ -0,0 +1,141 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Settings/AdvancedPane.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/HW/SystemTimers.h" +#include "DolphinQt2/Settings.h" + +AdvancedPane::AdvancedPane(QWidget* parent) : QWidget(parent) +{ + CreateLayout(); + ConnectLayout(); + + connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, &AdvancedPane::Update); + Update(); +} + +void AdvancedPane::CreateLayout() +{ + auto* main_layout = new QVBoxLayout(); + setLayout(main_layout); + + auto* cpu_options = new QGroupBox(tr("CPU Options")); + auto* cpu_options_layout = new QVBoxLayout(); + cpu_options->setLayout(cpu_options_layout); + main_layout->addWidget(cpu_options); + + m_cpu_clock_override_checkbox = new QCheckBox(tr("Enable CPU Clock Override")); + cpu_options_layout->addWidget(m_cpu_clock_override_checkbox); + + auto* cpu_clock_override_slider_layout = new QHBoxLayout(); + cpu_clock_override_slider_layout->setContentsMargins(0, 0, 0, 0); + cpu_options_layout->addLayout(cpu_clock_override_slider_layout); + + m_cpu_clock_override_slider = new QSlider(Qt::Horizontal); + m_cpu_clock_override_slider->setRange(0, 150); + cpu_clock_override_slider_layout->addWidget(m_cpu_clock_override_slider); + + m_cpu_clock_override_slider_label = new QLabel(); + cpu_clock_override_slider_layout->addWidget(m_cpu_clock_override_slider_label); + + auto* cpu_clock_override_description = + new QLabel(tr("Higher values can make variable-framerate games run at a higher framerate, at " + "the expense of CPU. Lower values can make variable-framerate games run at a " + "lower framerate, saving CPU.\n\nWARNING: Changing this from the default " + "(100%) can and will break games and cause glitches. Do so at your own risk. " + "Please do not report bugs that occur with a non-default clock.")); + cpu_clock_override_description->setWordWrap(true); + cpu_options_layout->addWidget(cpu_clock_override_description); + + auto* rtc_options = new QGroupBox(tr("Custom RTC Options")); + rtc_options->setLayout(new QVBoxLayout()); + main_layout->addWidget(rtc_options); + + m_custom_rtc_checkbox = new QCheckBox(tr("Enable Custom RTC")); + rtc_options->layout()->addWidget(m_custom_rtc_checkbox); + + m_custom_rtc_datetime = new QDateTimeEdit(); + if (!m_custom_rtc_datetime->displayFormat().contains(QStringLiteral("yyyy"))) + { + // Always show the full year, no matter what the locale specifies. Otherwise, two-digit years + // will always be interpreted as in the 21st century. + m_custom_rtc_datetime->setDisplayFormat(m_custom_rtc_datetime->displayFormat().replace( + QStringLiteral("yy"), QStringLiteral("yyyy"))); + } + m_custom_rtc_datetime->setDateRange({2000, 1, 1}, {2099, 12, 31}); + rtc_options->layout()->addWidget(m_custom_rtc_datetime); + + auto* custom_rtc_description = + new QLabel(tr("This setting allows you to set a custom real time clock (RTC) separate from " + "your current system time.\n\nIf you're unsure, leave this disabled.")); + custom_rtc_description->setWordWrap(true); + rtc_options->layout()->addWidget(custom_rtc_description); + + main_layout->addStretch(1); +} + +void AdvancedPane::ConnectLayout() +{ + m_cpu_clock_override_checkbox->setChecked(SConfig::GetInstance().m_OCEnable); + connect(m_cpu_clock_override_checkbox, &QCheckBox::toggled, [this](bool enable_clock_override) { + SConfig::GetInstance().m_OCEnable = enable_clock_override; + Update(); + }); + + m_cpu_clock_override_slider->setValue( + static_cast(std::ceil(std::log2f(SConfig::GetInstance().m_OCFactor) * 25.f + 100.f))); + connect(m_cpu_clock_override_slider, &QSlider::valueChanged, [this](int oc_factor) { + // Vaguely exponential scaling? + SConfig::GetInstance().m_OCFactor = + std::exp2f((m_cpu_clock_override_slider->value() - 100.f) / 25.f); + Update(); + }); + + m_custom_rtc_checkbox->setChecked(SConfig::GetInstance().bEnableCustomRTC); + connect(m_custom_rtc_checkbox, &QCheckBox::toggled, [this](bool enable_custom_rtc) { + SConfig::GetInstance().bEnableCustomRTC = enable_custom_rtc; + Update(); + }); + + QDateTime initial_date_time; + initial_date_time.setTime_t(SConfig::GetInstance().m_customRTCValue); + m_custom_rtc_datetime->setDateTime(initial_date_time); + connect(m_custom_rtc_datetime, &QDateTimeEdit::dateTimeChanged, [this](QDateTime date_time) { + SConfig::GetInstance().m_customRTCValue = date_time.toTime_t(); + Update(); + }); +} + +void AdvancedPane::Update() +{ + const bool running = Core::GetState() != Core::State::Uninitialized; + const bool enable_cpu_clock_override_widgets = SConfig::GetInstance().m_OCEnable && !running; + const bool enable_custom_rtc_widgets = SConfig::GetInstance().bEnableCustomRTC && !running; + + m_cpu_clock_override_checkbox->setEnabled(!running); + m_cpu_clock_override_slider->setEnabled(enable_cpu_clock_override_widgets); + m_cpu_clock_override_slider_label->setEnabled(enable_cpu_clock_override_widgets); + + m_cpu_clock_override_slider_label->setText([] { + int core_clock = SystemTimers::GetTicksPerSecond() / std::pow(10, 6); + int percent = static_cast(std::round(SConfig::GetInstance().m_OCFactor * 100.f)); + int clock = static_cast(std::round(SConfig::GetInstance().m_OCFactor * core_clock)); + return tr("%1 % (%2 MHz)").arg(QString::number(percent), QString::number(clock)); + }()); + + m_custom_rtc_checkbox->setEnabled(!running); + m_custom_rtc_datetime->setEnabled(enable_custom_rtc_widgets); +} diff --git a/Source/Core/DolphinQt2/Settings/AdvancedPane.h b/Source/Core/DolphinQt2/Settings/AdvancedPane.h new file mode 100644 index 0000000000..2e7120ae62 --- /dev/null +++ b/Source/Core/DolphinQt2/Settings/AdvancedPane.h @@ -0,0 +1,32 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class QCheckBox; +class QLabel; +class QSlider; +class QDateTimeEdit; + +class AdvancedPane final : public QWidget +{ + Q_OBJECT +public: + explicit AdvancedPane(QWidget* parent = nullptr); + +private: + void CreateLayout(); + void ConnectLayout(); + void Update(); + + QCheckBox* m_cpu_clock_override_checkbox; + QSlider* m_cpu_clock_override_slider; + QLabel* m_cpu_clock_override_slider_label; + QLabel* m_cpu_clock_override_description; + + QCheckBox* m_custom_rtc_checkbox; + QDateTimeEdit* m_custom_rtc_datetime; +}; diff --git a/Source/Core/DolphinWX/Config/AdvancedConfigPane.cpp b/Source/Core/DolphinWX/Config/AdvancedConfigPane.cpp index 5a194d9c20..423c95eb59 100644 --- a/Source/Core/DolphinWX/Config/AdvancedConfigPane.cpp +++ b/Source/Core/DolphinWX/Config/AdvancedConfigPane.cpp @@ -110,7 +110,8 @@ void AdvancedConfigPane::InitializeGUI() void AdvancedConfigPane::LoadGUIValues() { - int ocFactor = (int)(std::log2f(SConfig::GetInstance().m_OCFactor) * 25.f + 100.f + 0.5f); + int ocFactor = + static_cast(std::ceil(std::log2f(SConfig::GetInstance().m_OCFactor) * 25.f + 100.f)); bool oc_enabled = SConfig::GetInstance().m_OCEnable; m_clock_override_checkbox->SetValue(oc_enabled); m_clock_override_slider->SetValue(ocFactor); @@ -199,7 +200,7 @@ void AdvancedConfigPane::OnCustomRTCTimeChanged(wxDateEvent& event) void AdvancedConfigPane::UpdateCPUClock() { - int core_clock = SystemTimers::GetTicksPerSecond() / pow(10, 6); + int core_clock = SystemTimers::GetTicksPerSecond() / std::pow(10, 6); int percent = static_cast(std::round(SConfig::GetInstance().m_OCFactor * 100.f)); int clock = static_cast(std::round(SConfig::GetInstance().m_OCFactor * core_clock));