summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/android/app/src/main/jni/config.cpp2
-rw-r--r--src/common/settings_common.h10
-rw-r--r--src/common/settings_setting.h33
-rw-r--r--src/core/crypto/key_manager.cpp8
-rw-r--r--src/core/file_sys/ips_layer.cpp4
-rw-r--r--src/core/memory/cheat_engine.cpp2
-rw-r--r--src/yuzu/configuration/configure_ui.cpp7
-rw-r--r--src/yuzu/configuration/shared_widget.cpp171
-rw-r--r--src/yuzu/configuration/shared_widget.h21
-rw-r--r--src/yuzu_cmd/config.cpp2
-rw-r--r--src/yuzu_cmd/yuzu.cpp5
11 files changed, 200 insertions, 65 deletions
diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index 34b425cb4..81120ab0f 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -282,7 +282,7 @@ void Config::ReadValues() {
282 std::stringstream ss(title_list); 282 std::stringstream ss(title_list);
283 std::string line; 283 std::string line;
284 while (std::getline(ss, line, '|')) { 284 while (std::getline(ss, line, '|')) {
285 const auto title_id = std::stoul(line, nullptr, 16); 285 const auto title_id = std::strtoul(line.c_str(), nullptr, 16);
286 const auto disabled_list = config->Get("AddOns", "disabled_" + line, ""); 286 const auto disabled_list = config->Get("AddOns", "disabled_" + line, "");
287 287
288 std::stringstream inner_ss(disabled_list); 288 std::stringstream inner_ss(disabled_list);
diff --git a/src/common/settings_common.h b/src/common/settings_common.h
index 5b170dfd5..1800ab10d 100644
--- a/src/common/settings_common.h
+++ b/src/common/settings_common.h
@@ -225,6 +225,16 @@ public:
225 */ 225 */
226 [[nodiscard]] virtual constexpr u32 EnumIndex() const = 0; 226 [[nodiscard]] virtual constexpr u32 EnumIndex() const = 0;
227 227
228 /**
229 * @returns True if the underlying type is a floating point storage
230 */
231 [[nodiscard]] virtual constexpr bool IsFloatingPoint() const = 0;
232
233 /**
234 * @returns True if the underlying type is an integer storage
235 */
236 [[nodiscard]] virtual constexpr bool IsIntegral() const = 0;
237
228 /* 238 /*
229 * Switchable settings 239 * Switchable settings
230 */ 240 */
diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h
index e10843c73..7be6f26f7 100644
--- a/src/common/settings_setting.h
+++ b/src/common/settings_setting.h
@@ -10,6 +10,7 @@
10#include <string> 10#include <string>
11#include <typeindex> 11#include <typeindex>
12#include <typeinfo> 12#include <typeinfo>
13#include <fmt/core.h>
13#include "common/common_types.h" 14#include "common/common_types.h"
14#include "common/settings_common.h" 15#include "common/settings_common.h"
15#include "common/settings_enums.h" 16#include "common/settings_enums.h"
@@ -115,8 +116,12 @@ protected:
115 } else if constexpr (std::is_same_v<Type, AudioEngine>) { 116 } else if constexpr (std::is_same_v<Type, AudioEngine>) {
116 // Compatibility with old AudioEngine setting being a string 117 // Compatibility with old AudioEngine setting being a string
117 return CanonicalizeEnum(value_); 118 return CanonicalizeEnum(value_);
119 } else if constexpr (std::is_floating_point_v<Type>) {
120 return fmt::format("{:f}", value_);
121 } else if constexpr (std::is_enum_v<Type>) {
122 return std::to_string(static_cast<u32>(value_));
118 } else { 123 } else {
119 return std::to_string(static_cast<u64>(value_)); 124 return std::to_string(value_);
120 } 125 }
121 } 126 }
122 127
@@ -180,13 +185,15 @@ public:
180 this->SetValue(static_cast<u32>(std::stoul(input))); 185 this->SetValue(static_cast<u32>(std::stoul(input)));
181 } else if constexpr (std::is_same_v<Type, bool>) { 186 } else if constexpr (std::is_same_v<Type, bool>) {
182 this->SetValue(input == "true"); 187 this->SetValue(input == "true");
183 } else if constexpr (std::is_same_v<Type, AudioEngine>) { 188 } else if constexpr (std::is_same_v<Type, float>) {
184 this->SetValue(ToEnum<Type>(input)); 189 this->SetValue(std::stof(input));
185 } else { 190 } else {
186 this->SetValue(static_cast<Type>(std::stoll(input))); 191 this->SetValue(static_cast<Type>(std::stoll(input)));
187 } 192 }
188 } catch (std::invalid_argument&) { 193 } catch (std::invalid_argument&) {
189 this->SetValue(this->GetDefault()); 194 this->SetValue(this->GetDefault());
195 } catch (std::out_of_range&) {
196 this->SetValue(this->GetDefault());
190 } 197 }
191 } 198 }
192 199
@@ -215,11 +222,27 @@ public:
215 } 222 }
216 } 223 }
217 224
225 [[nodiscard]] constexpr bool IsFloatingPoint() const final {
226 return std::is_floating_point_v<Type>;
227 }
228
229 [[nodiscard]] constexpr bool IsIntegral() const final {
230 return std::is_integral_v<Type>;
231 }
232
218 [[nodiscard]] std::string MinVal() const override final { 233 [[nodiscard]] std::string MinVal() const override final {
219 return this->ToString(minimum); 234 if constexpr (std::is_arithmetic_v<Type> && !ranged) {
235 return this->ToString(std::numeric_limits<Type>::min());
236 } else {
237 return this->ToString(minimum);
238 }
220 } 239 }
221 [[nodiscard]] std::string MaxVal() const override final { 240 [[nodiscard]] std::string MaxVal() const override final {
222 return this->ToString(maximum); 241 if constexpr (std::is_arithmetic_v<Type> && !ranged) {
242 return this->ToString(std::numeric_limits<Type>::max());
243 } else {
244 return this->ToString(maximum);
245 }
223 } 246 }
224 247
225 [[nodiscard]] constexpr bool Ranged() const override { 248 [[nodiscard]] constexpr bool Ranged() const override {
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index e13c5cdc7..43a3c5ffd 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -724,14 +724,14 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti
724 continue; 724 continue;
725 } 725 }
726 726
727 const auto index = std::stoul(out[0].substr(8, 2), nullptr, 16); 727 const auto index = std::strtoul(out[0].substr(8, 2).c_str(), nullptr, 16);
728 keyblobs[index] = Common::HexStringToArray<0x90>(out[1]); 728 keyblobs[index] = Common::HexStringToArray<0x90>(out[1]);
729 } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) { 729 } else if (out[0].compare(0, 18, "encrypted_keyblob_") == 0) {
730 if (!ValidCryptoRevisionString(out[0], 18, 2)) { 730 if (!ValidCryptoRevisionString(out[0], 18, 2)) {
731 continue; 731 continue;
732 } 732 }
733 733
734 const auto index = std::stoul(out[0].substr(18, 2), nullptr, 16); 734 const auto index = std::strtoul(out[0].substr(18, 2).c_str(), nullptr, 16);
735 encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]); 735 encrypted_keyblobs[index] = Common::HexStringToArray<0xB0>(out[1]);
736 } else if (out[0].compare(0, 20, "eticket_extended_kek") == 0) { 736 } else if (out[0].compare(0, 20, "eticket_extended_kek") == 0) {
737 eticket_extended_kek = Common::HexStringToArray<576>(out[1]); 737 eticket_extended_kek = Common::HexStringToArray<576>(out[1]);
@@ -750,7 +750,7 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti
750 } 750 }
751 if (out[0].compare(0, kv.second.size(), kv.second) == 0) { 751 if (out[0].compare(0, kv.second.size(), kv.second) == 0) {
752 const auto index = 752 const auto index =
753 std::stoul(out[0].substr(kv.second.size(), 2), nullptr, 16); 753 std::strtoul(out[0].substr(kv.second.size(), 2).c_str(), nullptr, 16);
754 const auto sub = kv.first.second; 754 const auto sub = kv.first.second;
755 if (sub == 0) { 755 if (sub == 0) {
756 s128_keys[{kv.first.first, index, 0}] = 756 s128_keys[{kv.first.first, index, 0}] =
@@ -770,7 +770,7 @@ void KeyManager::LoadFromFile(const std::filesystem::path& file_path, bool is_ti
770 const auto& match = kak_names[j]; 770 const auto& match = kak_names[j];
771 if (out[0].compare(0, std::strlen(match), match) == 0) { 771 if (out[0].compare(0, std::strlen(match), match) == 0) {
772 const auto index = 772 const auto index =
773 std::stoul(out[0].substr(std::strlen(match), 2), nullptr, 16); 773 std::strtoul(out[0].substr(std::strlen(match), 2).c_str(), nullptr, 16);
774 s128_keys[{S128KeyType::KeyArea, index, j}] = 774 s128_keys[{S128KeyType::KeyArea, index, j}] =
775 Common::HexStringToArray<16>(out[1]); 775 Common::HexStringToArray<16>(out[1]);
776 } 776 }
diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp
index efdf18cee..7be1322cc 100644
--- a/src/core/file_sys/ips_layer.cpp
+++ b/src/core/file_sys/ips_layer.cpp
@@ -165,7 +165,7 @@ static std::string EscapeStringSequences(std::string in) {
165void IPSwitchCompiler::ParseFlag(const std::string& line) { 165void IPSwitchCompiler::ParseFlag(const std::string& line) {
166 if (StartsWith(line, "@flag offset_shift ")) { 166 if (StartsWith(line, "@flag offset_shift ")) {
167 // Offset Shift Flag 167 // Offset Shift Flag
168 offset_shift = std::stoll(line.substr(19), nullptr, 0); 168 offset_shift = std::strtoll(line.substr(19).c_str(), nullptr, 0);
169 } else if (StartsWith(line, "@little-endian")) { 169 } else if (StartsWith(line, "@little-endian")) {
170 // Set values to read as little endian 170 // Set values to read as little endian
171 is_little_endian = true; 171 is_little_endian = true;
@@ -263,7 +263,7 @@ void IPSwitchCompiler::Parse() {
263 // 11 - 8 hex digit offset + space + minimum two digit overwrite val 263 // 11 - 8 hex digit offset + space + minimum two digit overwrite val
264 if (patch_line.length() < 11) 264 if (patch_line.length() < 11)
265 break; 265 break;
266 auto offset = std::stoul(patch_line.substr(0, 8), nullptr, 16); 266 auto offset = std::strtoul(patch_line.substr(0, 8).c_str(), nullptr, 16);
267 offset += static_cast<unsigned long>(offset_shift); 267 offset += static_cast<unsigned long>(offset_shift);
268 268
269 std::vector<u8> replace; 269 std::vector<u8> replace;
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index 7b52f61a7..a06e99166 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -154,7 +154,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
154 return {}; 154 return {};
155 } 155 }
156 156
157 const auto value = static_cast<u32>(std::stoul(hex, nullptr, 0x10)); 157 const auto value = static_cast<u32>(std::strtoul(hex.c_str(), nullptr, 0x10));
158 out[*current_entry].definition.opcodes[out[*current_entry].definition.num_opcodes++] = 158 out[*current_entry].definition.opcodes[out[*current_entry].definition.num_opcodes++] =
159 value; 159 value;
160 160
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 34ab01617..a9fde9f4f 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -4,6 +4,7 @@
4#include "yuzu/configuration/configure_ui.h" 4#include "yuzu/configuration/configure_ui.h"
5 5
6#include <array> 6#include <array>
7#include <cstdlib>
7#include <set> 8#include <set>
8#include <stdexcept> 9#include <stdexcept>
9#include <string> 10#include <string>
@@ -94,11 +95,7 @@ static void PopulateResolutionComboBox(QComboBox* screenshot_height, QWidget* pa
94} 95}
95 96
96static u32 ScreenshotDimensionToInt(const QString& height) { 97static u32 ScreenshotDimensionToInt(const QString& height) {
97 try { 98 return std::strtoul(height.toUtf8(), nullptr, 0);
98 return std::stoi(height.toStdString());
99 } catch (std::invalid_argument&) {
100 return 0;
101 }
102} 99}
103 100
104ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent) 101ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent)
diff --git a/src/yuzu/configuration/shared_widget.cpp b/src/yuzu/configuration/shared_widget.cpp
index d63093985..ea8d7add4 100644
--- a/src/yuzu/configuration/shared_widget.cpp
+++ b/src/yuzu/configuration/shared_widget.cpp
@@ -63,7 +63,7 @@ static QString DefaultSuffix(QWidget* parent, Settings::BasicSetting& setting) {
63 return tr("%", context.c_str()); 63 return tr("%", context.c_str());
64 } 64 }
65 65
66 return QStringLiteral(""); 66 return default_suffix;
67} 67}
68 68
69QPushButton* Widget::CreateRestoreGlobalButton(bool using_global, QWidget* parent) { 69QPushButton* Widget::CreateRestoreGlobalButton(bool using_global, QWidget* parent) {
@@ -71,7 +71,7 @@ QPushButton* Widget::CreateRestoreGlobalButton(bool using_global, QWidget* paren
71 71
72 QStyle* style = parent->style(); 72 QStyle* style = parent->style();
73 QIcon* icon = new QIcon(style->standardIcon(QStyle::SP_LineEditClearButton)); 73 QIcon* icon = new QIcon(style->standardIcon(QStyle::SP_LineEditClearButton));
74 QPushButton* restore_button = new QPushButton(*icon, QStringLiteral(""), parent); 74 QPushButton* restore_button = new QPushButton(*icon, QStringLiteral(), parent);
75 restore_button->setObjectName(QStringLiteral("RestoreButton%1").arg(restore_button_count)); 75 restore_button->setObjectName(QStringLiteral("RestoreButton%1").arg(restore_button_count));
76 restore_button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 76 restore_button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
77 77
@@ -151,7 +151,7 @@ QWidget* Widget::CreateCombobox(std::function<std::string()>& serializer,
151 return -1; 151 return -1;
152 }; 152 };
153 153
154 const u32 setting_value = std::stoi(setting.ToString()); 154 const u32 setting_value = std::strtoul(setting.ToString().c_str(), nullptr, 0);
155 combobox->setCurrentIndex(find_index(setting_value)); 155 combobox->setCurrentIndex(find_index(setting_value));
156 156
157 serializer = [this, enumeration]() { 157 serializer = [this, enumeration]() {
@@ -160,7 +160,7 @@ QWidget* Widget::CreateCombobox(std::function<std::string()>& serializer,
160 }; 160 };
161 161
162 restore_func = [this, find_index]() { 162 restore_func = [this, find_index]() {
163 const u32 global_value = std::stoi(RelevantDefault(setting)); 163 const u32 global_value = std::strtoul(RelevantDefault(setting).c_str(), nullptr, 0);
164 combobox->setCurrentIndex(find_index(global_value)); 164 combobox->setCurrentIndex(find_index(global_value));
165 }; 165 };
166 166
@@ -209,7 +209,7 @@ QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
209 } 209 }
210 }; 210 };
211 211
212 const u32 setting_value = std::stoi(setting.ToString()); 212 const u32 setting_value = std::strtoul(setting.ToString().c_str(), nullptr, 0);
213 set_index(setting_value); 213 set_index(setting_value);
214 214
215 serializer = [get_selected]() { 215 serializer = [get_selected]() {
@@ -218,7 +218,7 @@ QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
218 }; 218 };
219 219
220 restore_func = [this, set_index]() { 220 restore_func = [this, set_index]() {
221 const u32 global_value = std::stoi(RelevantDefault(setting)); 221 const u32 global_value = std::strtoul(RelevantDefault(setting).c_str(), nullptr, 0);
222 set_index(global_value); 222 set_index(global_value);
223 }; 223 };
224 224
@@ -255,6 +255,59 @@ QWidget* Widget::CreateLineEdit(std::function<std::string()>& serializer,
255 return line_edit; 255 return line_edit;
256} 256}
257 257
258static void CreateIntSlider(Settings::BasicSetting& setting, bool reversed, float multiplier,
259 QLabel* feedback, const QString& use_format, QSlider* slider,
260 std::function<std::string()>& serializer,
261 std::function<void()>& restore_func) {
262 const int max_val = std::strtol(setting.MaxVal().c_str(), nullptr, 0);
263
264 const auto update_feedback = [=](int value) {
265 int present = (reversed ? max_val - value : value) * multiplier + 0.5f;
266 feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>()));
267 };
268
269 QObject::connect(slider, &QAbstractSlider::valueChanged, update_feedback);
270 update_feedback(std::strtol(setting.ToString().c_str(), nullptr, 0));
271
272 slider->setMinimum(std::strtol(setting.MinVal().c_str(), nullptr, 0));
273 slider->setMaximum(max_val);
274 slider->setValue(std::strtol(setting.ToString().c_str(), nullptr, 0));
275
276 serializer = [slider]() { return std::to_string(slider->value()); };
277 restore_func = [slider, &setting]() {
278 slider->setValue(std::strtol(RelevantDefault(setting).c_str(), nullptr, 0));
279 };
280}
281
282static void CreateFloatSlider(Settings::BasicSetting& setting, bool reversed, float multiplier,
283 QLabel* feedback, const QString& use_format, QSlider* slider,
284 std::function<std::string()>& serializer,
285 std::function<void()>& restore_func) {
286 const float max_val = std::strtof(setting.MaxVal().c_str(), nullptr);
287 const float min_val = std::strtof(setting.MinVal().c_str(), nullptr);
288 const float use_multiplier =
289 multiplier == default_multiplier ? default_float_multiplier : multiplier;
290
291 const auto update_feedback = [=](float value) {
292 int present = (reversed ? max_val - value : value) + 0.5f;
293 feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>()));
294 };
295
296 QObject::connect(slider, &QAbstractSlider::valueChanged, update_feedback);
297 update_feedback(std::strtof(setting.ToString().c_str(), nullptr));
298
299 slider->setMinimum(min_val * use_multiplier);
300 slider->setMaximum(max_val * use_multiplier);
301 slider->setValue(std::strtof(setting.ToString().c_str(), nullptr) * use_multiplier);
302
303 serializer = [slider, use_multiplier]() {
304 return std::to_string(slider->value() / use_multiplier);
305 };
306 restore_func = [slider, &setting, use_multiplier]() {
307 slider->setValue(std::strtof(RelevantDefault(setting).c_str(), nullptr) * use_multiplier);
308 };
309}
310
258QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& given_suffix, 311QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& given_suffix,
259 std::function<std::string()>& serializer, 312 std::function<std::string()>& serializer,
260 std::function<void()>& restore_func, 313 std::function<void()>& restore_func,
@@ -278,27 +331,19 @@ QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& gi
278 331
279 layout->setContentsMargins(0, 0, 0, 0); 332 layout->setContentsMargins(0, 0, 0, 0);
280 333
281 int max_val = std::stoi(setting.MaxVal()); 334 QString suffix = given_suffix == default_suffix ? DefaultSuffix(this, setting) : given_suffix;
282
283 QString suffix =
284 given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix;
285 335
286 const QString use_format = QStringLiteral("%1").append(suffix); 336 const QString use_format = QStringLiteral("%1").append(suffix);
287 337
288 QObject::connect(slider, &QAbstractSlider::valueChanged, [=](int value) { 338 if (setting.IsIntegral()) {
289 int present = (reversed ? max_val - value : value) * multiplier + 0.5f; 339 CreateIntSlider(setting, reversed, multiplier, feedback, use_format, slider, serializer,
290 feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>())); 340 restore_func);
291 }); 341 } else {
292 342 CreateFloatSlider(setting, reversed, multiplier, feedback, use_format, slider, serializer,
293 slider->setMinimum(std::stoi(setting.MinVal())); 343 restore_func);
294 slider->setMaximum(max_val); 344 }
295 slider->setValue(std::stoi(setting.ToString()));
296 345
297 slider->setInvertedAppearance(reversed); 346 slider->setInvertedAppearance(reversed);
298 slider->setInvertedControls(reversed);
299
300 serializer = [this]() { return std::to_string(slider->value()); };
301 restore_func = [this]() { slider->setValue(std::stoi(RelevantDefault(setting))); };
302 347
303 if (!Settings::IsConfiguringGlobal()) { 348 if (!Settings::IsConfiguringGlobal()) {
304 QObject::connect(slider, &QAbstractSlider::actionTriggered, [touch]() { touch(); }); 349 QObject::connect(slider, &QAbstractSlider::actionTriggered, [touch]() { touch(); });
@@ -311,14 +356,11 @@ QWidget* Widget::CreateSpinBox(const QString& given_suffix,
311 std::function<std::string()>& serializer, 356 std::function<std::string()>& serializer,
312 std::function<void()>& restore_func, 357 std::function<void()>& restore_func,
313 const std::function<void()>& touch) { 358 const std::function<void()>& touch) {
314 const int min_val = 359 const auto min_val = std::strtol(setting.MinVal().c_str(), nullptr, 0);
315 setting.Ranged() ? std::stoi(setting.MinVal()) : std::numeric_limits<int>::min(); 360 const auto max_val = std::strtol(setting.MaxVal().c_str(), nullptr, 0);
316 const int max_val = 361 const auto default_val = std::strtol(setting.ToString().c_str(), nullptr, 0);
317 setting.Ranged() ? std::stoi(setting.MaxVal()) : std::numeric_limits<int>::max();
318 const int default_val = std::stoi(setting.ToString());
319 362
320 QString suffix = 363 QString suffix = given_suffix == default_suffix ? DefaultSuffix(this, setting) : given_suffix;
321 given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix;
322 364
323 spinbox = new QSpinBox(this); 365 spinbox = new QSpinBox(this);
324 spinbox->setRange(min_val, max_val); 366 spinbox->setRange(min_val, max_val);
@@ -329,13 +371,13 @@ QWidget* Widget::CreateSpinBox(const QString& given_suffix,
329 serializer = [this]() { return std::to_string(spinbox->value()); }; 371 serializer = [this]() { return std::to_string(spinbox->value()); };
330 372
331 restore_func = [this]() { 373 restore_func = [this]() {
332 auto value{std::stol(RelevantDefault(setting))}; 374 auto value{std::strtol(RelevantDefault(setting).c_str(), nullptr, 0)};
333 spinbox->setValue(value); 375 spinbox->setValue(value);
334 }; 376 };
335 377
336 if (!Settings::IsConfiguringGlobal()) { 378 if (!Settings::IsConfiguringGlobal()) {
337 QObject::connect(spinbox, QOverload<int>::of(&QSpinBox::valueChanged), [this, touch]() { 379 QObject::connect(spinbox, QOverload<int>::of(&QSpinBox::valueChanged), [this, touch]() {
338 if (spinbox->value() != std::stoi(setting.ToStringGlobal())) { 380 if (spinbox->value() != std::strtol(setting.ToStringGlobal().c_str(), nullptr, 0)) {
339 touch(); 381 touch();
340 } 382 }
341 }); 383 });
@@ -344,6 +386,42 @@ QWidget* Widget::CreateSpinBox(const QString& given_suffix,
344 return spinbox; 386 return spinbox;
345} 387}
346 388
389QWidget* Widget::CreateDoubleSpinBox(const QString& given_suffix,
390 std::function<std::string()>& serializer,
391 std::function<void()>& restore_func,
392 const std::function<void()>& touch) {
393 const auto min_val = std::strtod(setting.MinVal().c_str(), nullptr);
394 const auto max_val = std::strtod(setting.MaxVal().c_str(), nullptr);
395 const auto default_val = std::strtod(setting.ToString().c_str(), nullptr);
396
397 QString suffix = given_suffix == default_suffix ? DefaultSuffix(this, setting) : given_suffix;
398
399 double_spinbox = new QDoubleSpinBox(this);
400 double_spinbox->setRange(min_val, max_val);
401 double_spinbox->setValue(default_val);
402 double_spinbox->setSuffix(suffix);
403 double_spinbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
404
405 serializer = [this]() { return fmt::format("{:f}", double_spinbox->value()); };
406
407 restore_func = [this]() {
408 auto value{std::strtod(RelevantDefault(setting).c_str(), nullptr)};
409 double_spinbox->setValue(value);
410 };
411
412 if (!Settings::IsConfiguringGlobal()) {
413 QObject::connect(double_spinbox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
414 [this, touch]() {
415 if (double_spinbox->value() !=
416 std::strtod(setting.ToStringGlobal().c_str(), nullptr)) {
417 touch();
418 }
419 });
420 }
421
422 return double_spinbox;
423}
424
347QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer, 425QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer,
348 std::function<void()>& restore_func, 426 std::function<void()>& restore_func,
349 const std::function<void()>& touch) { 427 const std::function<void()>& touch) {
@@ -353,7 +431,8 @@ QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer,
353 } 431 }
354 432
355 auto to_hex = [=](const std::string& input) { 433 auto to_hex = [=](const std::string& input) {
356 return QString::fromStdString(fmt::format("{:08x}", std::stoul(input))); 434 return QString::fromStdString(
435 fmt::format("{:08x}", std::strtoul(input.c_str(), nullptr, 0)));
357 }; 436 };
358 437
359 QRegularExpressionValidator* regex = new QRegularExpressionValidator( 438 QRegularExpressionValidator* regex = new QRegularExpressionValidator(
@@ -366,7 +445,7 @@ QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer,
366 line_edit->setValidator(regex); 445 line_edit->setValidator(regex);
367 446
368 auto hex_to_dec = [this]() -> std::string { 447 auto hex_to_dec = [this]() -> std::string {
369 return std::to_string(std::stoul(line_edit->text().toStdString(), nullptr, 16)); 448 return std::to_string(std::strtoul(line_edit->text().toStdString().c_str(), nullptr, 16));
370 }; 449 };
371 450
372 serializer = [hex_to_dec]() { return hex_to_dec(); }; 451 serializer = [hex_to_dec]() { return hex_to_dec(); };
@@ -386,7 +465,8 @@ QWidget* Widget::CreateDateTimeEdit(bool disabled, bool restrict,
386 std::function<void()>& restore_func, 465 std::function<void()>& restore_func,
387 const std::function<void()>& touch) { 466 const std::function<void()>& touch) {
388 const long long current_time = QDateTime::currentSecsSinceEpoch(); 467 const long long current_time = QDateTime::currentSecsSinceEpoch();
389 const s64 the_time = disabled ? current_time : std::stoll(setting.ToString()); 468 const s64 the_time =
469 disabled ? current_time : std::strtoll(setting.ToString().c_str(), nullptr, 0);
390 const auto default_val = QDateTime::fromSecsSinceEpoch(the_time); 470 const auto default_val = QDateTime::fromSecsSinceEpoch(the_time);
391 471
392 date_time_edit = new QDateTimeEdit(this); 472 date_time_edit = new QDateTimeEdit(this);
@@ -399,7 +479,7 @@ QWidget* Widget::CreateDateTimeEdit(bool disabled, bool restrict,
399 auto get_clear_val = [this, restrict, current_time]() { 479 auto get_clear_val = [this, restrict, current_time]() {
400 return QDateTime::fromSecsSinceEpoch([this, restrict, current_time]() { 480 return QDateTime::fromSecsSinceEpoch([this, restrict, current_time]() {
401 if (restrict && checkbox->checkState() == Qt::Checked) { 481 if (restrict && checkbox->checkState() == Qt::Checked) {
402 return std::stoll(RelevantDefault(setting)); 482 return std::strtoll(RelevantDefault(setting).c_str(), nullptr, 0);
403 } 483 }
404 return current_time; 484 return current_time;
405 }()); 485 }());
@@ -506,8 +586,7 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
506 } else { 586 } else {
507 data_component = CreateCombobox(serializer, restore_func, touch); 587 data_component = CreateCombobox(serializer, restore_func, touch);
508 } 588 }
509 } else if (type == typeid(u32) || type == typeid(int) || type == typeid(u16) || 589 } else if (setting.IsIntegral()) {
510 type == typeid(s64) || type == typeid(u8)) {
511 switch (request) { 590 switch (request) {
512 case RequestType::Slider: 591 case RequestType::Slider:
513 case RequestType::ReverseSlider: 592 case RequestType::ReverseSlider:
@@ -534,6 +613,20 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
534 default: 613 default:
535 UNIMPLEMENTED(); 614 UNIMPLEMENTED();
536 } 615 }
616 } else if (setting.IsFloatingPoint()) {
617 switch (request) {
618 case RequestType::Default:
619 case RequestType::SpinBox:
620 data_component = CreateDoubleSpinBox(suffix, serializer, restore_func, touch);
621 break;
622 case RequestType::Slider:
623 case RequestType::ReverseSlider:
624 data_component = CreateSlider(request == RequestType::ReverseSlider, multiplier, suffix,
625 serializer, restore_func, touch);
626 break;
627 default:
628 UNIMPLEMENTED();
629 }
537 } else if (type == typeid(std::string)) { 630 } else if (type == typeid(std::string)) {
538 switch (request) { 631 switch (request) {
539 case RequestType::Default: 632 case RequestType::Default:
@@ -638,10 +731,10 @@ Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translati
638 return std::pair{translations.at(id).first, translations.at(id).second}; 731 return std::pair{translations.at(id).first, translations.at(id).second};
639 } 732 }
640 LOG_WARNING(Frontend, "Translation table lacks entry for \"{}\"", setting_label); 733 LOG_WARNING(Frontend, "Translation table lacks entry for \"{}\"", setting_label);
641 return std::pair{QString::fromStdString(setting_label), QStringLiteral("")}; 734 return std::pair{QString::fromStdString(setting_label), QStringLiteral()};
642 }(); 735 }();
643 736
644 if (label == QStringLiteral("")) { 737 if (label == QStringLiteral()) {
645 LOG_DEBUG(Frontend, "Translation table has empty entry for \"{}\", skipping...", 738 LOG_DEBUG(Frontend, "Translation table has empty entry for \"{}\", skipping...",
646 setting.GetLabel()); 739 setting.GetLabel());
647 return; 740 return;
diff --git a/src/yuzu/configuration/shared_widget.h b/src/yuzu/configuration/shared_widget.h
index 5303dd898..226284cf3 100644
--- a/src/yuzu/configuration/shared_widget.h
+++ b/src/yuzu/configuration/shared_widget.h
@@ -22,6 +22,7 @@ class QObject;
22class QPushButton; 22class QPushButton;
23class QSlider; 23class QSlider;
24class QSpinBox; 24class QSpinBox;
25class QDoubleSpinBox;
25class QRadioButton; 26class QRadioButton;
26 27
27namespace Settings { 28namespace Settings {
@@ -43,6 +44,10 @@ enum class RequestType {
43 MaxEnum, 44 MaxEnum,
44}; 45};
45 46
47constexpr float default_multiplier{1.f};
48constexpr float default_float_multiplier{100.f};
49static const QString default_suffix = QStringLiteral();
50
46class Widget : public QWidget { 51class Widget : public QWidget {
47 Q_OBJECT 52 Q_OBJECT
48 53
@@ -66,8 +71,9 @@ public:
66 const ComboboxTranslationMap& combobox_translations, QWidget* parent, 71 const ComboboxTranslationMap& combobox_translations, QWidget* parent,
67 bool runtime_lock, std::vector<std::function<void(bool)>>& apply_funcs_, 72 bool runtime_lock, std::vector<std::function<void(bool)>>& apply_funcs_,
68 RequestType request = RequestType::Default, bool managed = true, 73 RequestType request = RequestType::Default, bool managed = true,
69 float multiplier = 1.0f, Settings::BasicSetting* other_setting = nullptr, 74 float multiplier = default_multiplier,
70 const QString& suffix = QStringLiteral("")); 75 Settings::BasicSetting* other_setting = nullptr,
76 const QString& suffix = default_suffix);
71 virtual ~Widget(); 77 virtual ~Widget();
72 78
73 /** 79 /**
@@ -89,6 +95,7 @@ public:
89 QPushButton* restore_button{}; ///< Restore button for custom configurations 95 QPushButton* restore_button{}; ///< Restore button for custom configurations
90 QLineEdit* line_edit{}; ///< QLineEdit, used for LineEdit and HexEdit 96 QLineEdit* line_edit{}; ///< QLineEdit, used for LineEdit and HexEdit
91 QSpinBox* spinbox{}; 97 QSpinBox* spinbox{};
98 QDoubleSpinBox* double_spinbox{};
92 QCheckBox* checkbox{}; 99 QCheckBox* checkbox{};
93 QSlider* slider{}; 100 QSlider* slider{};
94 QComboBox* combobox{}; 101 QComboBox* combobox{};
@@ -126,6 +133,9 @@ private:
126 const std::function<void()>& touch); 133 const std::function<void()>& touch);
127 QWidget* CreateSpinBox(const QString& suffix, std::function<std::string()>& serializer, 134 QWidget* CreateSpinBox(const QString& suffix, std::function<std::string()>& serializer,
128 std::function<void()>& restore_func, const std::function<void()>& touch); 135 std::function<void()>& restore_func, const std::function<void()>& touch);
136 QWidget* CreateDoubleSpinBox(const QString& suffix, std::function<std::string()>& serializer,
137 std::function<void()>& restore_func,
138 const std::function<void()>& touch);
129 139
130 QWidget* parent; 140 QWidget* parent;
131 const TranslationMap& translations; 141 const TranslationMap& translations;
@@ -145,14 +155,15 @@ public:
145 Widget* BuildWidget(Settings::BasicSetting* setting, 155 Widget* BuildWidget(Settings::BasicSetting* setting,
146 std::vector<std::function<void(bool)>>& apply_funcs, 156 std::vector<std::function<void(bool)>>& apply_funcs,
147 RequestType request = RequestType::Default, bool managed = true, 157 RequestType request = RequestType::Default, bool managed = true,
148 float multiplier = 1.0f, Settings::BasicSetting* other_setting = nullptr, 158 float multiplier = default_multiplier,
149 const QString& suffix = QStringLiteral("")) const; 159 Settings::BasicSetting* other_setting = nullptr,
160 const QString& suffix = default_suffix) const;
150 161
151 Widget* BuildWidget(Settings::BasicSetting* setting, 162 Widget* BuildWidget(Settings::BasicSetting* setting,
152 std::vector<std::function<void(bool)>>& apply_funcs, 163 std::vector<std::function<void(bool)>>& apply_funcs,
153 Settings::BasicSetting* other_setting, 164 Settings::BasicSetting* other_setting,
154 RequestType request = RequestType::Default, 165 RequestType request = RequestType::Default,
155 const QString& suffix = QStringLiteral("")) const; 166 const QString& suffix = default_suffix) const;
156 167
157 const ComboboxTranslationMap& ComboboxTranslations() const; 168 const ComboboxTranslationMap& ComboboxTranslations() const;
158 169
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index c42d98709..0d25ff400 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -259,7 +259,7 @@ void Config::ReadValues() {
259 std::stringstream ss(title_list); 259 std::stringstream ss(title_list);
260 std::string line; 260 std::string line;
261 while (std::getline(ss, line, '|')) { 261 while (std::getline(ss, line, '|')) {
262 const auto title_id = std::stoul(line, nullptr, 16); 262 const auto title_id = std::strtoul(line.c_str(), nullptr, 16);
263 const auto disabled_list = sdl2_config->Get("AddOns", "disabled_" + line, ""); 263 const auto disabled_list = sdl2_config->Get("AddOns", "disabled_" + line, "");
264 264
265 std::stringstream inner_ss(disabled_list); 265 std::stringstream inner_ss(disabled_list);
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 55d0938f7..087cfaa26 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -264,8 +264,9 @@ int main(int argc, char** argv) {
264 nickname = match[1]; 264 nickname = match[1];
265 password = match[2]; 265 password = match[2];
266 address = match[3]; 266 address = match[3];
267 if (!match[4].str().empty()) 267 if (!match[4].str().empty()) {
268 port = static_cast<u16>(std::stoi(match[4])); 268 port = static_cast<u16>(std::strtoul(match[4].str().c_str(), nullptr, 0));
269 }
269 std::regex nickname_re("^[a-zA-Z0-9._\\- ]+$"); 270 std::regex nickname_re("^[a-zA-Z0-9._\\- ]+$");
270 if (!std::regex_match(nickname, nickname_re)) { 271 if (!std::regex_match(nickname, nickname_re)) {
271 std::cout 272 std::cout