From 438c848a255c77df234e60697162aa263d974207 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 14 Feb 2026 20:12:49 +0000 Subject: [PATCH] [common] autogenerate unique console serial for every install Signed-off-by: lizzie --- src/common/settings.h | 10 ++- .../service/set/system_settings_server.cpp | 65 +++++++++++++++---- src/frontend_common/settings_generator.cpp | 15 +++-- src/yuzu/configuration/configure_debug.cpp | 4 -- 4 files changed, 69 insertions(+), 25 deletions(-) diff --git a/src/common/settings.h b/src/common/settings.h index 9a7d3a30d3..a7cf800142 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -620,11 +620,11 @@ struct Values { "language_index", Category::System}; SwitchableSetting region_index{linkage, Region::Usa, "region_index", Category::System}; - SwitchableSetting time_zone_index{linkage, TimeZone::Auto, - "time_zone_index", Category::System}; + SwitchableSetting time_zone_index{linkage, TimeZone::Auto, "time_zone_index", Category::System}; + Setting serial_battery{linkage, 0, "serial_battery", Category::System}; + Setting serial_unit{linkage, 0, "serial_unit", Category::System}; // Measured in seconds since epoch - SwitchableSetting custom_rtc_enabled{ - linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true}; + SwitchableSetting custom_rtc_enabled{linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true}; SwitchableSetting custom_rtc{ linkage, 0, "custom_rtc", Category::System, Specialization::Time, false, true, &custom_rtc_enabled}; @@ -794,8 +794,6 @@ struct Values { true}; // Miscellaneous - Setting serial_battery{linkage, std::string(), "serial_battery", Category::Miscellaneous}; - Setting serial_unit{linkage, std::string(), "serial_unit", Category::Miscellaneous}; Setting log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; Setting log_flush_line{linkage, false, "flush_line", Category::Miscellaneous, Specialization::Default, true, true}; Setting censor_username{linkage, true, "censor_username", Category::Miscellaneous}; diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index f87dd847ba..1cf44868b9 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -983,22 +983,65 @@ Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary Result ISystemSettingsServer::GetBatteryLot(Out out_battery_lot) { LOG_INFO(Service_SET, "called"); *out_battery_lot = {"YUZU0EMULATOR14022024"}; - if (auto const s = ::Settings::values.serial_battery.GetValue(); !s.empty()) { - auto const max_size = out_battery_lot->lot_number.size(); - auto const end = s.size() > max_size ? s.begin() + max_size : s.end(); - std::copy(s.begin(), end, out_battery_lot->lot_number.begin()); - } + // if (auto const s = ::Settings::values.serial_battery.GetValue(); !s.empty()) { + // auto const max_size = out_battery_lot->lot_number.size(); + // auto const end = s.size() > max_size ? s.begin() + max_size : s.end(); + // std::copy(s.begin(), end, out_battery_lot->lot_number.begin()); + // } R_SUCCEED(); } +static SerialNumber GenerateSerialNumber(u32 d) { + SerialNumber c{}; + std::array digits = { + u8((d / 1000000000) % 100), + u8((d / 100000000) % 10), + u8((d / 10000000) % 10), + u8((d / 1000000) % 10), + u8((d / 100000) % 10), + u8((d / 10000) % 10), + u8((d / 1000) % 10), + u8((d / 100) % 10), + u8((d / 10) % 10), + u8(d % 10), + }; + // Normalize to retail values + std::array retail_digits = { 1, 4, 5, 7 }; + digits[0] = retail_digits[(d % 10) % 4]; + digits[1] = 0; + + c.serial_number[0] = 'X'; + c.serial_number[1] = 'A'; + c.serial_number[2] = [] { + // Adding another setting would be tedious so... let's just reuse region_index :) + switch (::Settings::values.region_index.GetValue()) { + case ::Settings::Region::Japan: return 'J'; + case ::Settings::Region::Usa: return 'W'; + case ::Settings::Region::Europe: return 'E'; + case ::Settings::Region::Australia: return 'M'; //pretend its Malaysia + case ::Settings::Region::China: + case ::Settings::Region::Taiwan: return 'C'; + case ::Settings::Region::Korea: return 'K'; + default: return 'W'; + } + }(); + for (size_t i = 0; i < sizeof(digits); ++i) + c.serial_number[3 + i] = digits[i] + '0'; + u8 sum_odd = 0, sum_even = 0; + for (size_t i = 0; i < sizeof(digits); i += 2) { + sum_odd += digits[i + 0]; + sum_even += digits[i + 1]; + } + u8 sum_digit = ((sum_even * 3) + sum_odd) % 10; + if (sum_digit != 0) + sum_digit = 10 - sum_digit; + c.serial_number[3 + sizeof(digits)] = sum_digit + '0'; + return c; +} + Result ISystemSettingsServer::GetSerialNumber(Out out_console_serial) { LOG_INFO(Service_SET, "called"); - *out_console_serial = {"YUZ10000000001"}; - if (auto const s = ::Settings::values.serial_unit.GetValue(); !s.empty()) { - auto const max_size = out_console_serial->serial_number.size(); - auto const end = s.size() > max_size ? s.begin() + max_size : s.end(); - std::copy(s.begin(), end, out_console_serial->serial_number.begin()); - } + *out_console_serial = GenerateSerialNumber(::Settings::values.serial_unit.GetValue()); R_SUCCEED(); } diff --git a/src/frontend_common/settings_generator.cpp b/src/frontend_common/settings_generator.cpp index 0f09878b30..c3d4750649 100644 --- a/src/frontend_common/settings_generator.cpp +++ b/src/frontend_common/settings_generator.cpp @@ -11,9 +11,8 @@ namespace FrontendCommon { void GenerateSettings() { static std::random_device rd; - // Web Token // - auto &token_setting = Settings::values.eden_token; - if (token_setting.GetValue().empty()) { + // Web Token + if (Settings::values.eden_token.GetValue().empty()) { static constexpr const size_t token_length = 48; static constexpr const frozen::string token_set = "abcdefghijklmnopqrstuvwxyz"; static std::uniform_int_distribution token_dist(0, token_set.size() - 1); @@ -23,8 +22,16 @@ void GenerateSettings() { size_t idx = token_dist(rd); result += token_set[idx]; } + Settings::values.eden_token.SetValue(result); + } - token_setting.SetValue(result); + // Randomly generated number because, well, we fill the rest automagically ;) + // Other serial parts are filled by Region_Index + if (Settings::values.serial_unit.GetValue() == 0) { + std::random_device device; + std::mt19937 gen(device()); + std::uniform_int_distribution distribution(1, (std::numeric_limits::max)()); + Settings::values.serial_unit.SetValue(distribution(gen)); } } diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 0de5f46dcc..bbabee3be3 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -57,10 +57,6 @@ void ConfigureDebug::SetConfiguration() { #endif // Immutable after starting - ui->serial_battery_edit->setEnabled(runtime_lock); - ui->serial_battery_edit->setText(QString::fromStdString(Settings::values.serial_battery.GetValue())); - ui->serial_board_edit->setEnabled(runtime_lock); - ui->serial_board_edit->setText(QString::fromStdString(Settings::values.serial_unit.GetValue())); ui->homebrew_args_edit->setEnabled(runtime_lock); ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args.GetValue())); ui->toggle_console->setEnabled(runtime_lock);