1 // Copyright 2016 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4
5 #include <array>
6 #include <chrono>
7 #include <optional>
8
9 #include <QFileDialog>
10 #include <QGraphicsItem>
11 #include <QMessageBox>
12 #include "common/assert.h"
13 #include "common/file_util.h"
14 #include "core/core.h"
15 #include "core/hle/service/time/time.h"
16 #include "core/settings.h"
17 #include "ui_configure_system.h"
18 #include "yuzu/configuration/configuration_shared.h"
19 #include "yuzu/configuration/configure_system.h"
20
ConfigureSystem(QWidget * parent)21 ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) {
22 ui->setupUi(this);
23 connect(ui->button_regenerate_console_id, &QPushButton::clicked, this,
24 &ConfigureSystem::RefreshConsoleID);
25
26 connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](int state) {
27 ui->rng_seed_edit->setEnabled(state == Qt::Checked);
28 if (state != Qt::Checked) {
29 ui->rng_seed_edit->setText(QStringLiteral("00000000"));
30 }
31 });
32
33 connect(ui->custom_rtc_checkbox, &QCheckBox::stateChanged, this, [this](int state) {
34 ui->custom_rtc_edit->setEnabled(state == Qt::Checked);
35 if (state != Qt::Checked) {
36 ui->custom_rtc_edit->setDateTime(QDateTime::currentDateTime());
37 }
38 });
39
40 ui->label_console_id->setVisible(Settings::IsConfiguringGlobal());
41 ui->button_regenerate_console_id->setVisible(Settings::IsConfiguringGlobal());
42
43 SetupPerGameUI();
44
45 SetConfiguration();
46 }
47
48 ConfigureSystem::~ConfigureSystem() = default;
49
changeEvent(QEvent * event)50 void ConfigureSystem::changeEvent(QEvent* event) {
51 if (event->type() == QEvent::LanguageChange) {
52 RetranslateUI();
53 }
54
55 QWidget::changeEvent(event);
56 }
57
RetranslateUI()58 void ConfigureSystem::RetranslateUI() {
59 ui->retranslateUi(this);
60 }
61
SetConfiguration()62 void ConfigureSystem::SetConfiguration() {
63 enabled = !Core::System::GetInstance().IsPoweredOn();
64 const auto rng_seed =
65 QStringLiteral("%1")
66 .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'})
67 .toUpper();
68 const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or(
69 std::chrono::seconds(QDateTime::currentSecsSinceEpoch()));
70
71 ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value());
72 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() &&
73 Settings::values.rng_seed.UsingGlobal());
74 ui->rng_seed_edit->setText(rng_seed);
75
76 ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value());
77 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() &&
78 Settings::values.rng_seed.UsingGlobal());
79 ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
80
81 if (Settings::IsConfiguringGlobal()) {
82 ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue());
83 ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue());
84 ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue());
85 ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue());
86 } else {
87 ConfigurationShared::SetPerGameSetting(ui->combo_language,
88 &Settings::values.language_index);
89 ConfigurationShared::SetPerGameSetting(ui->combo_region, &Settings::values.region_index);
90 ConfigurationShared::SetPerGameSetting(ui->combo_time_zone,
91 &Settings::values.time_zone_index);
92 ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index);
93
94 ConfigurationShared::SetHighlight(ui->label_language,
95 !Settings::values.language_index.UsingGlobal());
96 ConfigurationShared::SetHighlight(ui->label_region,
97 !Settings::values.region_index.UsingGlobal());
98 ConfigurationShared::SetHighlight(ui->label_timezone,
99 !Settings::values.time_zone_index.UsingGlobal());
100 ConfigurationShared::SetHighlight(ui->label_sound,
101 !Settings::values.sound_index.UsingGlobal());
102 }
103 }
104
ReadSystemSettings()105 void ConfigureSystem::ReadSystemSettings() {}
106
ApplyConfiguration()107 void ConfigureSystem::ApplyConfiguration() {
108 auto& system = Core::System::GetInstance();
109
110 // Allow setting custom RTC even if system is powered on,
111 // to allow in-game time to be fast forwarded
112 if (Settings::values.custom_rtc.UsingGlobal()) {
113 if (ui->custom_rtc_checkbox->isChecked()) {
114 Settings::values.custom_rtc.SetValue(
115 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
116 if (system.IsPoweredOn()) {
117 const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() +
118 Service::Time::TimeManager::GetExternalTimeZoneOffset()};
119 system.GetTimeManager().UpdateLocalSystemClockTime(posix_time);
120 }
121 } else {
122 Settings::values.custom_rtc.SetValue(std::nullopt);
123 }
124 }
125
126 if (!enabled) {
127 return;
128 }
129
130 if (Settings::IsConfiguringGlobal()) {
131 // Guard if during game and set to game-specific value
132 if (Settings::values.language_index.UsingGlobal()) {
133 Settings::values.language_index.SetValue(ui->combo_language->currentIndex());
134 }
135 if (Settings::values.region_index.UsingGlobal()) {
136 Settings::values.region_index.SetValue(ui->combo_region->currentIndex());
137 }
138 if (Settings::values.time_zone_index.UsingGlobal()) {
139 Settings::values.time_zone_index.SetValue(ui->combo_time_zone->currentIndex());
140 }
141 if (Settings::values.sound_index.UsingGlobal()) {
142 Settings::values.sound_index.SetValue(ui->combo_sound->currentIndex());
143 }
144
145 if (Settings::values.rng_seed.UsingGlobal()) {
146 if (ui->rng_seed_checkbox->isChecked()) {
147 Settings::values.rng_seed.SetValue(
148 ui->rng_seed_edit->text().toULongLong(nullptr, 16));
149 } else {
150 Settings::values.rng_seed.SetValue(std::nullopt);
151 }
152 }
153 } else {
154 ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index,
155 ui->combo_language);
156 ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region);
157 ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index,
158 ui->combo_time_zone);
159 ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
160
161 switch (use_rng_seed) {
162 case ConfigurationShared::CheckState::On:
163 case ConfigurationShared::CheckState::Off:
164 Settings::values.rng_seed.SetGlobal(false);
165 if (ui->rng_seed_checkbox->isChecked()) {
166 Settings::values.rng_seed.SetValue(
167 ui->rng_seed_edit->text().toULongLong(nullptr, 16));
168 } else {
169 Settings::values.rng_seed.SetValue(std::nullopt);
170 }
171 break;
172 case ConfigurationShared::CheckState::Global:
173 Settings::values.rng_seed.SetGlobal(false);
174 Settings::values.rng_seed.SetValue(std::nullopt);
175 Settings::values.rng_seed.SetGlobal(true);
176 break;
177 case ConfigurationShared::CheckState::Count:
178 break;
179 }
180
181 switch (use_custom_rtc) {
182 case ConfigurationShared::CheckState::On:
183 case ConfigurationShared::CheckState::Off:
184 Settings::values.custom_rtc.SetGlobal(false);
185 if (ui->custom_rtc_checkbox->isChecked()) {
186 Settings::values.custom_rtc.SetValue(
187 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
188 } else {
189 Settings::values.custom_rtc.SetValue(std::nullopt);
190 }
191 break;
192 case ConfigurationShared::CheckState::Global:
193 Settings::values.custom_rtc.SetGlobal(false);
194 Settings::values.custom_rtc.SetValue(std::nullopt);
195 Settings::values.custom_rtc.SetGlobal(true);
196 break;
197 case ConfigurationShared::CheckState::Count:
198 break;
199 }
200 }
201
202 Settings::Apply(system);
203 }
204
RefreshConsoleID()205 void ConfigureSystem::RefreshConsoleID() {
206 QMessageBox::StandardButton reply;
207 QString warning_text = tr("This will replace your current virtual Switch with a new one. "
208 "Your current virtual Switch will not be recoverable. "
209 "This might have unexpected effects in games. This might fail, "
210 "if you use an outdated config savegame. Continue?");
211 reply = QMessageBox::critical(this, tr("Warning"), warning_text,
212 QMessageBox::No | QMessageBox::Yes);
213 if (reply == QMessageBox::No) {
214 return;
215 }
216
217 u64 console_id{};
218 ui->label_console_id->setText(
219 tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
220 }
221
SetupPerGameUI()222 void ConfigureSystem::SetupPerGameUI() {
223 if (Settings::IsConfiguringGlobal()) {
224 ui->combo_language->setEnabled(Settings::values.language_index.UsingGlobal());
225 ui->combo_region->setEnabled(Settings::values.region_index.UsingGlobal());
226 ui->combo_time_zone->setEnabled(Settings::values.time_zone_index.UsingGlobal());
227 ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal());
228 ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal());
229 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal());
230 ui->custom_rtc_checkbox->setEnabled(Settings::values.custom_rtc.UsingGlobal());
231 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.UsingGlobal());
232
233 return;
234 }
235
236 ConfigurationShared::SetColoredComboBox(ui->combo_language, ui->label_language,
237 Settings::values.language_index.GetValue(true));
238 ConfigurationShared::SetColoredComboBox(ui->combo_region, ui->label_region,
239 Settings::values.region_index.GetValue(true));
240 ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone,
241 Settings::values.time_zone_index.GetValue(true));
242 ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound,
243 Settings::values.sound_index.GetValue(true));
244
245 ConfigurationShared::SetColoredTristate(
246 ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(),
247 Settings::values.rng_seed.GetValue().has_value(),
248 Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed);
249 ConfigurationShared::SetColoredTristate(
250 ui->custom_rtc_checkbox, Settings::values.custom_rtc.UsingGlobal(),
251 Settings::values.custom_rtc.GetValue().has_value(),
252 Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc);
253 }
254