[common] autogenerate unique console serial for every install (#3550)
Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3550 Reviewed-by: Maufeat <sahyno1996@gmail.com> Reviewed-by: DraVee <dravee@eden-emu.dev> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
e3035ae8f2
commit
75ebfaa090
|
|
@ -6,7 +6,4 @@ Debugging on physical hardware can get tedious and time consuming. Users are emp
|
||||||
|
|
||||||
**Standard key prefix**: Allows to redirect the key manager to a file other than `prod.keys` (for example `other` would redirect to `other.keys`). This is useful for testing multiple keysets. Default is `prod`.
|
**Standard key prefix**: Allows to redirect the key manager to a file other than `prod.keys` (for example `other` would redirect to `other.keys`). This is useful for testing multiple keysets. Default is `prod`.
|
||||||
|
|
||||||
**Changing serial**: Very basic way to set debug values for the serial (and battery number). Developers do not need to write the full serial as it will be writen in-place (that is, it will be filled with the default serial and then overwrite the serial from the beginning).
|
**Changing serial**: Very basic way to set debug values for the serial (and battery number). Developers do not need to write the full serial as only the first digits (excluding the last) will be accoutned for. Region settings will affect the generated serial. The serial corresponds to a non-OLED/Lite console.
|
||||||
- Battery serial: `YUZU0EMULATOR14022024`
|
|
||||||
- Board serial: `YUZ10000000001`
|
|
||||||
If the user were to set their board serial as `ABC`, then it will be written in-place and the resulting serial would be `ABC10000000001`. There are no underlying checks to ensure correctness of serials other than a hard limit of 16-characters for both.
|
|
||||||
|
|
|
||||||
|
|
@ -620,11 +620,11 @@ struct Values {
|
||||||
"language_index",
|
"language_index",
|
||||||
Category::System};
|
Category::System};
|
||||||
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, "region_index", Category::System};
|
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, "region_index", Category::System};
|
||||||
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
|
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto, "time_zone_index", Category::System};
|
||||||
"time_zone_index", Category::System};
|
Setting<u32> serial_battery{linkage, 0, "serial_battery", Category::System};
|
||||||
|
Setting<u32> serial_unit{linkage, 0, "serial_unit", Category::System};
|
||||||
// Measured in seconds since epoch
|
// Measured in seconds since epoch
|
||||||
SwitchableSetting<bool> custom_rtc_enabled{
|
SwitchableSetting<bool> custom_rtc_enabled{linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
|
||||||
linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
|
|
||||||
SwitchableSetting<s64> custom_rtc{
|
SwitchableSetting<s64> custom_rtc{
|
||||||
linkage, 0, "custom_rtc", Category::System, Specialization::Time,
|
linkage, 0, "custom_rtc", Category::System, Specialization::Time,
|
||||||
false, true, &custom_rtc_enabled};
|
false, true, &custom_rtc_enabled};
|
||||||
|
|
@ -794,8 +794,6 @@ struct Values {
|
||||||
true};
|
true};
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
Setting<std::string> serial_battery{linkage, std::string(), "serial_battery", Category::Miscellaneous};
|
|
||||||
Setting<std::string> serial_unit{linkage, std::string(), "serial_unit", Category::Miscellaneous};
|
|
||||||
Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
|
Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
|
||||||
Setting<bool> log_flush_line{linkage, false, "flush_line", Category::Miscellaneous, Specialization::Default, true, true};
|
Setting<bool> log_flush_line{linkage, false, "flush_line", Category::Miscellaneous, Specialization::Default, true, true};
|
||||||
Setting<bool> censor_username{linkage, true, "censor_username", Category::Miscellaneous};
|
Setting<bool> censor_username{linkage, true, "censor_username", Category::Miscellaneous};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
|
@ -980,25 +980,82 @@ Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Fill3DS_CRC(u32 d, char* data) {
|
||||||
|
std::array<u8, 10> 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<u8, 4> retail_digits = { 1, 4, 5, 7 };
|
||||||
|
digits[0] = retail_digits[(d % 10) % 4];
|
||||||
|
digits[1] = 0;
|
||||||
|
//
|
||||||
|
for (size_t i = 0; i < sizeof(digits); ++i)
|
||||||
|
data[i] = char(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 = u8(((sum_even * 3) + sum_odd) % 10);
|
||||||
|
if (sum_digit != 0)
|
||||||
|
sum_digit = 10 - sum_digit;
|
||||||
|
data[sizeof(digits)] = char(sum_digit + '0');
|
||||||
|
}
|
||||||
|
|
||||||
Result ISystemSettingsServer::GetBatteryLot(Out<BatteryLot> out_battery_lot) {
|
Result ISystemSettingsServer::GetBatteryLot(Out<BatteryLot> out_battery_lot) {
|
||||||
LOG_INFO(Service_SET, "called");
|
LOG_INFO(Service_SET, "called");
|
||||||
*out_battery_lot = {"YUZU0EMULATOR14022024"};
|
*out_battery_lot = []{
|
||||||
if (auto const s = ::Settings::values.serial_battery.GetValue(); !s.empty()) {
|
u32 d = ::Settings::values.serial_battery.GetValue();
|
||||||
auto const max_size = out_battery_lot->lot_number.size();
|
BatteryLot c{};
|
||||||
auto const end = s.size() > max_size ? s.begin() + max_size : s.end();
|
c.lot_number[0] = 'B';
|
||||||
std::copy(s.begin(), end, out_battery_lot->lot_number.begin());
|
c.lot_number[1] = 'H';
|
||||||
}
|
c.lot_number[2] = 'A';
|
||||||
|
c.lot_number[3] = 'C';
|
||||||
|
// TODO: I have no fucking idea what the letters mean
|
||||||
|
c.lot_number[4] = 'H';
|
||||||
|
c.lot_number[5] = 'Z';
|
||||||
|
c.lot_number[6] = 'Z';
|
||||||
|
c.lot_number[7] = 'A';
|
||||||
|
c.lot_number[8] = 'D';
|
||||||
|
c.lot_number[9] = char(((d / 100000) % 26) + 'A');
|
||||||
|
Fill3DS_CRC(d, c.lot_number.data() + 10);
|
||||||
|
return c;
|
||||||
|
}();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ISystemSettingsServer::GetSerialNumber(Out<SerialNumber> out_console_serial) {
|
Result ISystemSettingsServer::GetSerialNumber(Out<SerialNumber> out_console_serial) {
|
||||||
LOG_INFO(Service_SET, "called");
|
LOG_INFO(Service_SET, "called");
|
||||||
*out_console_serial = {"YUZ10000000001"};
|
*out_console_serial = []{
|
||||||
if (auto const s = ::Settings::values.serial_unit.GetValue(); !s.empty()) {
|
u32 d = ::Settings::values.serial_unit.GetValue();
|
||||||
auto const max_size = out_console_serial->serial_number.size();
|
SerialNumber c{};
|
||||||
auto const end = s.size() > max_size ? s.begin() + max_size : s.end();
|
c.serial_number[0] = 'X';
|
||||||
std::copy(s.begin(), end, out_console_serial->serial_number.begin());
|
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';
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
Fill3DS_CRC(d, c.serial_number.data() + 3);
|
||||||
|
return c;
|
||||||
|
}();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,8 @@ namespace FrontendCommon {
|
||||||
void GenerateSettings() {
|
void GenerateSettings() {
|
||||||
static std::random_device rd;
|
static std::random_device rd;
|
||||||
|
|
||||||
// Web Token //
|
// Web Token
|
||||||
auto &token_setting = Settings::values.eden_token;
|
if (Settings::values.eden_token.GetValue().empty()) {
|
||||||
if (token_setting.GetValue().empty()) {
|
|
||||||
static constexpr const size_t token_length = 48;
|
static constexpr const size_t token_length = 48;
|
||||||
static constexpr const frozen::string token_set = "abcdefghijklmnopqrstuvwxyz";
|
static constexpr const frozen::string token_set = "abcdefghijklmnopqrstuvwxyz";
|
||||||
static std::uniform_int_distribution<int> token_dist(0, token_set.size() - 1);
|
static std::uniform_int_distribution<int> token_dist(0, token_set.size() - 1);
|
||||||
|
|
@ -23,9 +22,18 @@ void GenerateSettings() {
|
||||||
size_t idx = token_dist(rd);
|
size_t idx = token_dist(rd);
|
||||||
result += token_set[idx];
|
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
|
||||||
|
std::random_device device;
|
||||||
|
std::mt19937 gen(device());
|
||||||
|
std::uniform_int_distribution<u32> distribution(1, (std::numeric_limits<u32>::max)());
|
||||||
|
if (Settings::values.serial_unit.GetValue() == 0)
|
||||||
|
Settings::values.serial_unit.SetValue(distribution(gen));
|
||||||
|
if (Settings::values.serial_battery.GetValue() == 0)
|
||||||
|
Settings::values.serial_battery.SetValue(distribution(gen));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||||
|
|
@ -57,10 +57,6 @@ void ConfigureDebug::SetConfiguration() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Immutable after starting
|
// 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->setEnabled(runtime_lock);
|
||||||
ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args.GetValue()));
|
ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args.GetValue()));
|
||||||
ui->toggle_console->setEnabled(runtime_lock);
|
ui->toggle_console->setEnabled(runtime_lock);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue