diff --git a/docs/user/Native.md b/docs/user/Native.md index ec1cd02253..0d8ee81a7a 100644 --- a/docs/user/Native.md +++ b/docs/user/Native.md @@ -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`. -**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). -- 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. +**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. diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index 31bca55d5b..e0dbe7f3a5 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -980,19 +980,7 @@ Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary R_SUCCEED(); } -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()); - // } - R_SUCCEED(); -} - -static SerialNumber GenerateSerialNumber(u32 d) { - SerialNumber c{}; +void Fill3DS_CRC(u32 d, char* data) { std::array digits = { u8((d / 1000000000) % 100), u8((d / 100000000) % 10), @@ -1009,24 +997,9 @@ static SerialNumber GenerateSerialNumber(u32 d) { 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'; + data[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]; @@ -1035,13 +1008,54 @@ static SerialNumber GenerateSerialNumber(u32 d) { 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; + data[sizeof(digits)] = sum_digit + '0'; +} + +Result ISystemSettingsServer::GetBatteryLot(Out out_battery_lot) { + LOG_INFO(Service_SET, "called"); + *out_battery_lot = []{ + u32 d = ::Settings::values.serial_battery.GetValue(); + BatteryLot c{}; + c.lot_number[0] = 'B'; + 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] = u8((d / 100000) % 26) + 'A'; + Fill3DS_CRC(d, c.lot_number.data() + 10); + return c; + }(); + R_SUCCEED(); } Result ISystemSettingsServer::GetSerialNumber(Out out_console_serial) { LOG_INFO(Service_SET, "called"); - *out_console_serial = GenerateSerialNumber(::Settings::values.serial_unit.GetValue()); + *out_console_serial = []{ + u32 d = ::Settings::values.serial_unit.GetValue(); + SerialNumber c{}; + 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'; + } + }(); + Fill3DS_CRC(d, c.serial_number.data() + 3); + return c; + }(); R_SUCCEED(); } diff --git a/src/frontend_common/settings_generator.cpp b/src/frontend_common/settings_generator.cpp index c3d4750649..46625656b1 100644 --- a/src/frontend_common/settings_generator.cpp +++ b/src/frontend_common/settings_generator.cpp @@ -27,12 +27,13 @@ void GenerateSettings() { // 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)()); + std::random_device device; + std::mt19937 gen(device()); + std::uniform_int_distribution distribution(1, (std::numeric_limits::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)); } }