dolphin/Source/Core/DolphinWX/Config/AdvancedConfigPane.cpp
MaJoR 4112936bae Adjust CPU Override Text
There has been a lot of confusion about what the CPU clock override
section does among users, and looking at it… I’m not surprised! It
doesn’t directly state which CPU clock rate is being overridden!

This small change adjusts the language to clarify that the emulated CPU
is being adjusted.
2017-11-06 22:39:12 -08:00

255 lines
9.8 KiB
C++

// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "DolphinWX/Config/AdvancedConfigPane.h"
#include <cmath>
#include <wx/checkbox.h>
#include <wx/datectrl.h>
#include <wx/dateevt.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/time.h>
#include <wx/timectrl.h>
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/SystemTimers.h"
#include "DolphinWX/DolphinSlider.h"
#include "DolphinWX/WxEventUtils.h"
AdvancedConfigPane::AdvancedConfigPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id)
{
InitializeGUI();
LoadGUIValues();
BindEvents();
}
void AdvancedConfigPane::InitializeGUI()
{
m_clock_override_checkbox =
new wxCheckBox(this, wxID_ANY, _("Enable Emulated CPU Clock Override"));
m_clock_override_slider =
new DolphinSlider(this, wxID_ANY, 100, 0, 150, wxDefaultPosition, FromDIP(wxSize(200, -1)));
m_clock_override_text = new wxStaticText(this, wxID_ANY, "");
m_custom_rtc_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Custom RTC"));
m_custom_rtc_date_picker = new wxDatePickerCtrl(this, wxID_ANY);
// The Wii System Menu only allows configuring a year between 2000 and 2035.
// However, the GameCube main menu (IPL) allows setting a year between 2000 and 2099,
// which is why we use that range here. The Wii still deals OK with dates beyond 2035
// and simply clamps them to 2035-12-31.
m_custom_rtc_date_picker->SetRange(wxDateTime(1, wxDateTime::Jan, 2000),
wxDateTime(31, wxDateTime::Dec, 2099));
m_custom_rtc_time_picker = new wxTimePickerCtrl(this, wxID_ANY);
wxStaticText* const clock_override_description =
new wxStaticText(this, wxID_ANY, _("Adjusts the emulated CPU's clock rate.\n\n"
"Higher values may make variable-framerate games run "
"at a higher framerate, at the expense of performance. "
"Lower values may activate a game's internal "
"frameskip, potentially improving performance.\n\n"
"WARNING: 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. "));
wxStaticText* const custom_rtc_description = new wxStaticText(
this, wxID_ANY,
_("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."));
#ifdef __APPLE__
clock_override_description->Wrap(550);
custom_rtc_description->Wrap(550);
#else
clock_override_description->Wrap(FromDIP(400));
custom_rtc_description->Wrap(FromDIP(400));
#endif
const int space5 = FromDIP(5);
wxBoxSizer* const clock_override_slider_sizer = new wxBoxSizer(wxHORIZONTAL);
clock_override_slider_sizer->Add(m_clock_override_slider, 1);
clock_override_slider_sizer->Add(m_clock_override_text, 1, wxLEFT, space5);
wxStaticBoxSizer* const cpu_options_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("CPU Options"));
cpu_options_sizer->AddSpacer(space5);
cpu_options_sizer->Add(m_clock_override_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
cpu_options_sizer->AddSpacer(space5);
cpu_options_sizer->Add(clock_override_slider_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
cpu_options_sizer->AddSpacer(space5);
cpu_options_sizer->Add(clock_override_description, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
cpu_options_sizer->AddSpacer(space5);
wxFlexGridSizer* const custom_rtc_date_time_sizer =
new wxFlexGridSizer(2, wxSize(space5, space5));
custom_rtc_date_time_sizer->Add(m_custom_rtc_date_picker, 0, wxEXPAND);
custom_rtc_date_time_sizer->Add(m_custom_rtc_time_picker, 0, wxEXPAND);
wxStaticBoxSizer* const custom_rtc_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("Custom RTC Options"));
custom_rtc_sizer->AddSpacer(space5);
custom_rtc_sizer->Add(m_custom_rtc_checkbox, 0, wxLEFT | wxRIGHT, space5);
custom_rtc_sizer->AddSpacer(space5);
custom_rtc_sizer->Add(custom_rtc_date_time_sizer, 0, wxLEFT | wxRIGHT, space5);
custom_rtc_sizer->AddSpacer(space5);
custom_rtc_sizer->Add(custom_rtc_description, 0, wxLEFT | wxRIGHT, space5);
custom_rtc_sizer->AddSpacer(space5);
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->AddSpacer(space5);
main_sizer->Add(cpu_options_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
main_sizer->AddSpacer(space5);
main_sizer->Add(custom_rtc_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
main_sizer->AddSpacer(space5);
SetSizer(main_sizer);
}
void AdvancedConfigPane::LoadGUIValues()
{
int ocFactor =
static_cast<int>(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);
m_clock_override_slider->Enable(oc_enabled);
UpdateCPUClock();
LoadCustomRTC();
}
void AdvancedConfigPane::BindEvents()
{
m_clock_override_checkbox->Bind(wxEVT_CHECKBOX,
&AdvancedConfigPane::OnClockOverrideCheckBoxChanged, this);
m_clock_override_checkbox->Bind(wxEVT_UPDATE_UI, &AdvancedConfigPane::OnUpdateCPUClockControls,
this);
m_clock_override_slider->Bind(wxEVT_SLIDER, &AdvancedConfigPane::OnClockOverrideSliderChanged,
this);
m_clock_override_slider->Bind(wxEVT_UPDATE_UI, &AdvancedConfigPane::OnUpdateCPUClockControls,
this);
m_custom_rtc_checkbox->Bind(wxEVT_CHECKBOX, &AdvancedConfigPane::OnCustomRTCCheckBoxChanged,
this);
m_custom_rtc_checkbox->Bind(wxEVT_UPDATE_UI, &WxEventUtils::OnEnableIfCoreNotRunning);
m_custom_rtc_date_picker->Bind(wxEVT_DATE_CHANGED, &AdvancedConfigPane::OnCustomRTCDateChanged,
this);
m_custom_rtc_date_picker->Bind(wxEVT_UPDATE_UI, &AdvancedConfigPane::OnUpdateRTCDateTimeEntries,
this);
m_custom_rtc_time_picker->Bind(wxEVT_TIME_CHANGED, &AdvancedConfigPane::OnCustomRTCTimeChanged,
this);
m_custom_rtc_time_picker->Bind(wxEVT_UPDATE_UI, &AdvancedConfigPane::OnUpdateRTCDateTimeEntries,
this);
}
void AdvancedConfigPane::OnClockOverrideCheckBoxChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_OCEnable = m_clock_override_checkbox->IsChecked();
m_clock_override_slider->Enable(SConfig::GetInstance().m_OCEnable);
UpdateCPUClock();
}
void AdvancedConfigPane::OnClockOverrideSliderChanged(wxCommandEvent& event)
{
// Vaguely exponential scaling?
SConfig::GetInstance().m_OCFactor =
std::exp2f((m_clock_override_slider->GetValue() - 100.f) / 25.f);
UpdateCPUClock();
}
static wxDateTime GetCustomRTCDateTime()
{
time_t timestamp = SConfig::GetInstance().m_customRTCValue;
return wxDateTime(timestamp).ToUTC();
}
static wxDateTime CombineDateAndTime(const wxDateTime& date, const wxDateTime& time)
{
wxDateTime datetime = date;
datetime.SetHour(time.GetHour());
datetime.SetMinute(time.GetMinute());
datetime.SetSecond(time.GetSecond());
return datetime;
}
void AdvancedConfigPane::OnCustomRTCCheckBoxChanged(wxCommandEvent& event)
{
const bool checked = m_custom_rtc_checkbox->IsChecked();
SConfig::GetInstance().bEnableCustomRTC = checked;
m_custom_rtc_date_picker->Enable(checked);
m_custom_rtc_time_picker->Enable(checked);
}
void AdvancedConfigPane::OnCustomRTCDateChanged(wxDateEvent& event)
{
wxDateTime datetime = CombineDateAndTime(event.GetDate(), GetCustomRTCDateTime());
UpdateCustomRTC(datetime);
}
void AdvancedConfigPane::OnCustomRTCTimeChanged(wxDateEvent& event)
{
wxDateTime datetime = CombineDateAndTime(GetCustomRTCDateTime(), event.GetDate());
UpdateCustomRTC(datetime);
}
void AdvancedConfigPane::UpdateCPUClock()
{
int core_clock = SystemTimers::GetTicksPerSecond() / std::pow(10, 6);
int percent = static_cast<int>(std::round(SConfig::GetInstance().m_OCFactor * 100.f));
int clock = static_cast<int>(std::round(SConfig::GetInstance().m_OCFactor * core_clock));
m_clock_override_text->SetLabel(SConfig::GetInstance().m_OCEnable ?
wxString::Format("%d %% (%d MHz)", percent, clock) :
wxString());
}
void AdvancedConfigPane::LoadCustomRTC()
{
bool custom_rtc_enabled = SConfig::GetInstance().bEnableCustomRTC;
m_custom_rtc_checkbox->SetValue(custom_rtc_enabled);
wxDateTime datetime = GetCustomRTCDateTime();
if (datetime.IsValid())
{
m_custom_rtc_date_picker->SetValue(datetime);
m_custom_rtc_time_picker->SetValue(datetime);
}
// Make sure we have a valid custom RTC date and time
// both when it was out of range as well as when it was invalid to begin with.
datetime = CombineDateAndTime(m_custom_rtc_date_picker->GetValue(),
m_custom_rtc_time_picker->GetValue());
UpdateCustomRTC(datetime);
}
void AdvancedConfigPane::UpdateCustomRTC(const wxDateTime& datetime)
{
// We need GetValue() as GetTicks() only works up to 0x7ffffffe, which is in 2038.
u32 timestamp = datetime.FromUTC().GetValue().GetValue() / 1000;
SConfig::GetInstance().m_customRTCValue = timestamp;
}
void AdvancedConfigPane::OnUpdateCPUClockControls(wxUpdateUIEvent& event)
{
if (!Core::IsRunning())
{
event.Enable(true);
return;
}
event.Enable(!Core::WantsDeterminism());
}
void AdvancedConfigPane::OnUpdateRTCDateTimeEntries(wxUpdateUIEvent& event)
{
event.Enable(!Core::IsRunning() && m_custom_rtc_checkbox->IsChecked());
}