diff --git a/src/citra_qt/configuration/configure_system.cpp b/src/citra_qt/configuration/configure_system.cpp index a3a9015a40..9b1e6711d5 100644 --- a/src/citra_qt/configuration/configure_system.cpp +++ b/src/citra_qt/configuration/configure_system.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "citra_qt/configuration/configure_system.h" #include "citra_qt/ui_settings.h" #include "core/core.h" @@ -15,8 +16,11 @@ static const std::array days_in_month = {{ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) { ui->setupUi(this); - connect(ui->combo_birthmonth, SIGNAL(currentIndexChanged(int)), - SLOT(updateBirthdayComboBox(int))); + connect(ui->combo_birthmonth, + static_cast(&QComboBox::currentIndexChanged), this, + &ConfigureSystem::updateBirthdayComboBox); + connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, + &ConfigureSystem::refreshConsoleID); this->setConfiguration(); } @@ -71,6 +75,10 @@ void ConfigureSystem::ReadSystemSettings() { // set sound output mode sound_index = Service::CFG::GetSoundOutputMode(); ui->combo_sound->setCurrentIndex(sound_index); + + // set the console id + u64 console_id = Service::CFG::GetConsoleUniqueId(); + ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper()); } void ConfigureSystem::applyConfiguration() { @@ -140,3 +148,21 @@ void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) { // restore the day selection ui->combo_birthday->setCurrentIndex(birthday_index); } + +void ConfigureSystem::refreshConsoleID() { + QMessageBox::StandardButton reply; + QString warning_text = tr("This will replace your current virtual 3DS with a new one. " + "Your current virtual 3DS will not be recoverable. " + "This might have unexpected effects in games. This might fail, " + "if you use an outdated config savegame. Continue?"); + reply = QMessageBox::critical(this, tr("Warning"), warning_text, + QMessageBox::No | QMessageBox::Yes); + if (reply == QMessageBox::No) + return; + u32 random_number; + u64 console_id; + Service::CFG::GenerateConsoleUniqueId(random_number, console_id); + Service::CFG::SetConsoleUniqueId(random_number, console_id); + Service::CFG::UpdateConfigNANDSavegame(); + ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper()); +} diff --git a/src/citra_qt/configuration/configure_system.h b/src/citra_qt/configuration/configure_system.h index db0ead13c7..f13de17d44 100644 --- a/src/citra_qt/configuration/configure_system.h +++ b/src/citra_qt/configuration/configure_system.h @@ -23,6 +23,7 @@ public: public slots: void updateBirthdayComboBox(int birthmonth_index); + void refreshConsoleID(); private: void ReadSystemSettings(); diff --git a/src/citra_qt/configuration/configure_system.ui b/src/citra_qt/configuration/configure_system.ui index cc54fa37f1..8caf496239 100644 --- a/src/citra_qt/configuration/configure_system.ui +++ b/src/citra_qt/configuration/configure_system.ui @@ -220,6 +220,29 @@ + + + + Console ID: + + + + + + + + 0 + 0 + + + + Qt::RightToLeft + + + Regenerate + + + diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 4ddb1bc900..8c8c1ec77e 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include "common/file_util.h" #include "common/logging/log.h" @@ -50,6 +51,7 @@ enum ConfigBlockID { SoundOutputModeBlockID = 0x00070001, ConsoleUniqueID1BlockID = 0x00090000, ConsoleUniqueID2BlockID = 0x00090001, + ConsoleUniqueID3BlockID = 0x00090002, UsernameBlockID = 0x000A0000, BirthdayBlockID = 0x000A0001, LanguageBlockID = 0x000A0002, @@ -86,7 +88,6 @@ struct ConsoleCountryInfo { static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); } -static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; static const ConsoleModelInfo CONSOLE_MODEL = {NINTENDO_3DS_XL, {0, 0, 0}}; static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; static const UsernameBlock CONSOLE_USERNAME_BLOCK = {u"CITRA", 0, 0}; @@ -438,13 +439,22 @@ ResultCode FormatConfig() { if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(ConsoleUniqueID1BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, - &CONSOLE_UNIQUE_ID); + u32 random_number; + u64 console_id; + GenerateConsoleUniqueId(random_number, console_id); + + u64_le console_id_le = console_id; + res = CreateConfigInfoBlk(ConsoleUniqueID1BlockID, sizeof(console_id_le), 0xE, &console_id_le); if (!res.IsSuccess()) return res; - res = CreateConfigInfoBlk(ConsoleUniqueID2BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, - &CONSOLE_UNIQUE_ID); + res = CreateConfigInfoBlk(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le); + if (!res.IsSuccess()) + return res; + + u32_le random_number_le = random_number; + res = CreateConfigInfoBlk(ConsoleUniqueID3BlockID, sizeof(random_number_le), 0xE, + &random_number_le); if (!res.IsSuccess()) return res; @@ -663,5 +673,40 @@ SoundOutputMode GetSoundOutputMode() { return static_cast(block); } +void GenerateConsoleUniqueId(u32& random_number, u64& console_id) { + CryptoPP::AutoSeededRandomPool rng; + random_number = rng.GenerateWord32(0, 0xFFFF); + u64_le local_friend_code_seed; + rng.GenerateBlock(reinterpret_cast(&local_friend_code_seed), + sizeof(local_friend_code_seed)); + console_id = (local_friend_code_seed & 0x3FFFFFFFF) | (static_cast(random_number) << 48); +} + +ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id) { + u64_le console_id_le = console_id; + ResultCode res = + SetConfigInfoBlock(ConsoleUniqueID1BlockID, sizeof(console_id_le), 0xE, &console_id_le); + if (!res.IsSuccess()) + return res; + + res = SetConfigInfoBlock(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le); + if (!res.IsSuccess()) + return res; + + u32_le random_number_le = random_number; + res = SetConfigInfoBlock(ConsoleUniqueID3BlockID, sizeof(random_number_le), 0xE, + &random_number_le); + if (!res.IsSuccess()) + return res; + + return RESULT_SUCCESS; +} + +u64 GetConsoleUniqueId() { + u64_le console_id_le; + GetConfigInfoBlock(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le); + return console_id_le; +} + } // namespace CFG } // namespace Service diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index 618c9647e6..1659ebf32d 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -342,5 +342,26 @@ void SetSoundOutputMode(SoundOutputMode mode); */ SoundOutputMode GetSoundOutputMode(); +/** + * Generates a new random console unique id. + * @param random_number a random generated 16bit number stored at 0x90002, used for generating the + * console_id + * @param console_id the randomly created console id + */ +void GenerateConsoleUniqueId(u32& random_number, u64& console_id); + +/** + * Sets the random_number and the console unique id in the config savegame. + * @param random_number the random_number to set + * @param console_id the console id to set + */ +ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id); + +/** + * Gets the console unique id from config savegame. + * @returns the console unique id + */ +u64 GetConsoleUniqueId(); + } // namespace CFG } // namespace Service