generate battery serial as well

This commit is contained in:
lizzie 2026-02-14 21:49:30 +00:00
parent 1f3003490c
commit 953dda9cc1
3 changed files with 54 additions and 42 deletions

View File

@ -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.

View File

@ -980,19 +980,7 @@ Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary
R_SUCCEED();
}
Result ISystemSettingsServer::GetBatteryLot(Out<BatteryLot> 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<u8, 10> digits = {
u8((d / 1000000000) % 100),
u8((d / 100000000) % 10),
@ -1009,24 +997,9 @@ static SerialNumber GenerateSerialNumber(u32 d) {
std::array<u8, 4> 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<BatteryLot> 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<SerialNumber> 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();
}

View File

@ -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<u32> distribution(1, (std::numeric_limits<u32>::max)());
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));
}
}