// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include #include #include #include #include #include #include "citra_qt/configuration/configuration_shared.h" #include "citra_qt/configuration/configure_system.h" #include "common/file_util.h" #include "common/settings.h" #include "core/core.h" #include "core/hle/service/am/am.h" #include "core/hle/service/cfg/cfg.h" #include "core/hle/service/ptm/ptm.h" #include "core/hw/aes/key.h" #include "core/hw/unique_data.h" #include "core/system_titles.h" #include "ui_configure_system.h" static const std::array days_in_month = {{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }}; static const std::array country_names = { "", QT_TRANSLATE_NOOP("ConfigureSystem", "Japan"), "", "", "", "", "", "", QT_TRANSLATE_NOOP("ConfigureSystem", "Anguilla"), QT_TRANSLATE_NOOP("ConfigureSystem", "Antigua and Barbuda"), // 0-9 QT_TRANSLATE_NOOP("ConfigureSystem", "Argentina"), QT_TRANSLATE_NOOP("ConfigureSystem", "Aruba"), QT_TRANSLATE_NOOP("ConfigureSystem", "Bahamas"), QT_TRANSLATE_NOOP("ConfigureSystem", "Barbados"), QT_TRANSLATE_NOOP("ConfigureSystem", "Belize"), QT_TRANSLATE_NOOP("ConfigureSystem", "Bolivia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Brazil"), QT_TRANSLATE_NOOP("ConfigureSystem", "British Virgin Islands"), QT_TRANSLATE_NOOP("ConfigureSystem", "Canada"), QT_TRANSLATE_NOOP("ConfigureSystem", "Cayman Islands"), // 10-19 QT_TRANSLATE_NOOP("ConfigureSystem", "Chile"), QT_TRANSLATE_NOOP("ConfigureSystem", "Colombia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Costa Rica"), QT_TRANSLATE_NOOP("ConfigureSystem", "Dominica"), QT_TRANSLATE_NOOP("ConfigureSystem", "Dominican Republic"), QT_TRANSLATE_NOOP("ConfigureSystem", "Ecuador"), QT_TRANSLATE_NOOP("ConfigureSystem", "El Salvador"), QT_TRANSLATE_NOOP("ConfigureSystem", "French Guiana"), QT_TRANSLATE_NOOP("ConfigureSystem", "Grenada"), QT_TRANSLATE_NOOP("ConfigureSystem", "Guadeloupe"), // 20-29 QT_TRANSLATE_NOOP("ConfigureSystem", "Guatemala"), QT_TRANSLATE_NOOP("ConfigureSystem", "Guyana"), QT_TRANSLATE_NOOP("ConfigureSystem", "Haiti"), QT_TRANSLATE_NOOP("ConfigureSystem", "Honduras"), QT_TRANSLATE_NOOP("ConfigureSystem", "Jamaica"), QT_TRANSLATE_NOOP("ConfigureSystem", "Martinique"), QT_TRANSLATE_NOOP("ConfigureSystem", "Mexico"), QT_TRANSLATE_NOOP("ConfigureSystem", "Montserrat"), QT_TRANSLATE_NOOP("ConfigureSystem", "Netherlands Antilles"), QT_TRANSLATE_NOOP("ConfigureSystem", "Nicaragua"), // 30-39 QT_TRANSLATE_NOOP("ConfigureSystem", "Panama"), QT_TRANSLATE_NOOP("ConfigureSystem", "Paraguay"), QT_TRANSLATE_NOOP("ConfigureSystem", "Peru"), QT_TRANSLATE_NOOP("ConfigureSystem", "Saint Kitts and Nevis"), QT_TRANSLATE_NOOP("ConfigureSystem", "Saint Lucia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Saint Vincent and the Grenadines"), QT_TRANSLATE_NOOP("ConfigureSystem", "Suriname"), QT_TRANSLATE_NOOP("ConfigureSystem", "Trinidad and Tobago"), QT_TRANSLATE_NOOP("ConfigureSystem", "Turks and Caicos Islands"), QT_TRANSLATE_NOOP("ConfigureSystem", "United States"), // 40-49 QT_TRANSLATE_NOOP("ConfigureSystem", "Uruguay"), QT_TRANSLATE_NOOP("ConfigureSystem", "US Virgin Islands"), QT_TRANSLATE_NOOP("ConfigureSystem", "Venezuela"), "", "", "", "", "", "", "", // 50-59 "", "", "", "", QT_TRANSLATE_NOOP("ConfigureSystem", "Albania"), QT_TRANSLATE_NOOP("ConfigureSystem", "Australia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Austria"), QT_TRANSLATE_NOOP("ConfigureSystem", "Belgium"), QT_TRANSLATE_NOOP("ConfigureSystem", "Bosnia and Herzegovina"), QT_TRANSLATE_NOOP("ConfigureSystem", "Botswana"), // 60-69 QT_TRANSLATE_NOOP("ConfigureSystem", "Bulgaria"), QT_TRANSLATE_NOOP("ConfigureSystem", "Croatia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Cyprus"), QT_TRANSLATE_NOOP("ConfigureSystem", "Czech Republic"), QT_TRANSLATE_NOOP("ConfigureSystem", "Denmark"), QT_TRANSLATE_NOOP("ConfigureSystem", "Estonia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Finland"), QT_TRANSLATE_NOOP("ConfigureSystem", "France"), QT_TRANSLATE_NOOP("ConfigureSystem", "Germany"), QT_TRANSLATE_NOOP("ConfigureSystem", "Greece"), // 70-79 QT_TRANSLATE_NOOP("ConfigureSystem", "Hungary"), QT_TRANSLATE_NOOP("ConfigureSystem", "Iceland"), QT_TRANSLATE_NOOP("ConfigureSystem", "Ireland"), QT_TRANSLATE_NOOP("ConfigureSystem", "Italy"), QT_TRANSLATE_NOOP("ConfigureSystem", "Latvia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Lesotho"), QT_TRANSLATE_NOOP("ConfigureSystem", "Liechtenstein"), QT_TRANSLATE_NOOP("ConfigureSystem", "Lithuania"), QT_TRANSLATE_NOOP("ConfigureSystem", "Luxembourg"), QT_TRANSLATE_NOOP("ConfigureSystem", "Macedonia"), // 80-89 QT_TRANSLATE_NOOP("ConfigureSystem", "Malta"), QT_TRANSLATE_NOOP("ConfigureSystem", "Montenegro"), QT_TRANSLATE_NOOP("ConfigureSystem", "Mozambique"), QT_TRANSLATE_NOOP("ConfigureSystem", "Namibia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Netherlands"), QT_TRANSLATE_NOOP("ConfigureSystem", "New Zealand"), QT_TRANSLATE_NOOP("ConfigureSystem", "Norway"), QT_TRANSLATE_NOOP("ConfigureSystem", "Poland"), QT_TRANSLATE_NOOP("ConfigureSystem", "Portugal"), QT_TRANSLATE_NOOP("ConfigureSystem", "Romania"), // 90-99 QT_TRANSLATE_NOOP("ConfigureSystem", "Russia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Serbia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Slovakia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Slovenia"), QT_TRANSLATE_NOOP("ConfigureSystem", "South Africa"), QT_TRANSLATE_NOOP("ConfigureSystem", "Spain"), QT_TRANSLATE_NOOP("ConfigureSystem", "Swaziland"), QT_TRANSLATE_NOOP("ConfigureSystem", "Sweden"), QT_TRANSLATE_NOOP("ConfigureSystem", "Switzerland"), QT_TRANSLATE_NOOP("ConfigureSystem", "Turkey"), // 100-109 QT_TRANSLATE_NOOP("ConfigureSystem", "United Kingdom"), QT_TRANSLATE_NOOP("ConfigureSystem", "Zambia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Zimbabwe"), QT_TRANSLATE_NOOP("ConfigureSystem", "Azerbaijan"), QT_TRANSLATE_NOOP("ConfigureSystem", "Mauritania"), QT_TRANSLATE_NOOP("ConfigureSystem", "Mali"), QT_TRANSLATE_NOOP("ConfigureSystem", "Niger"), QT_TRANSLATE_NOOP("ConfigureSystem", "Chad"), QT_TRANSLATE_NOOP("ConfigureSystem", "Sudan"), QT_TRANSLATE_NOOP("ConfigureSystem", "Eritrea"), // 110-119 QT_TRANSLATE_NOOP("ConfigureSystem", "Djibouti"), QT_TRANSLATE_NOOP("ConfigureSystem", "Somalia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Andorra"), QT_TRANSLATE_NOOP("ConfigureSystem", "Gibraltar"), QT_TRANSLATE_NOOP("ConfigureSystem", "Guernsey"), QT_TRANSLATE_NOOP("ConfigureSystem", "Isle of Man"), QT_TRANSLATE_NOOP("ConfigureSystem", "Jersey"), QT_TRANSLATE_NOOP("ConfigureSystem", "Monaco"), QT_TRANSLATE_NOOP("ConfigureSystem", "Taiwan"), "", // 120-129 "", "", "", "", "", "", QT_TRANSLATE_NOOP("ConfigureSystem", "South Korea"), "", "", "", // 130-139 "", "", "", "", QT_TRANSLATE_NOOP("ConfigureSystem", "Hong Kong"), QT_TRANSLATE_NOOP("ConfigureSystem", "Macau"), "", "", "", "", // 140-149 "", "", QT_TRANSLATE_NOOP("ConfigureSystem", "Indonesia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Singapore"), QT_TRANSLATE_NOOP("ConfigureSystem", "Thailand"), QT_TRANSLATE_NOOP("ConfigureSystem", "Philippines"), QT_TRANSLATE_NOOP("ConfigureSystem", "Malaysia"), "", "", "", // 150-159 QT_TRANSLATE_NOOP("ConfigureSystem", "China"), "", "", "", "", "", "", "", QT_TRANSLATE_NOOP("ConfigureSystem", "United Arab Emirates"), QT_TRANSLATE_NOOP("ConfigureSystem", "India"), // 160-169 QT_TRANSLATE_NOOP("ConfigureSystem", "Egypt"), QT_TRANSLATE_NOOP("ConfigureSystem", "Oman"), QT_TRANSLATE_NOOP("ConfigureSystem", "Qatar"), QT_TRANSLATE_NOOP("ConfigureSystem", "Kuwait"), QT_TRANSLATE_NOOP("ConfigureSystem", "Saudi Arabia"), QT_TRANSLATE_NOOP("ConfigureSystem", "Syria"), QT_TRANSLATE_NOOP("ConfigureSystem", "Bahrain"), QT_TRANSLATE_NOOP("ConfigureSystem", "Jordan"), "", "", // 170-179 "", "", "", "", QT_TRANSLATE_NOOP("ConfigureSystem", "San Marino"), QT_TRANSLATE_NOOP("ConfigureSystem", "Vatican City"), QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186 }; ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent) : QWidget(parent), ui(std::make_unique()), system{system_} { ui->setupUi(this); connect(ui->combo_birthmonth, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureSystem::UpdateBirthdayComboBox); connect(ui->combo_init_clock, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureSystem::UpdateInitTime); connect(ui->combo_init_ticks_type, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureSystem::UpdateInitTicks); connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, &ConfigureSystem::RefreshConsoleID); connect(ui->button_regenerate_mac, &QPushButton::clicked, this, &ConfigureSystem::RefreshMAC); connect(ui->button_linked_console, &QPushButton::clicked, this, &ConfigureSystem::UnlinkConsole); connect(ui->button_secure_info, &QPushButton::clicked, this, [this] { ui->button_secure_info->setEnabled(false); const QString file_path_qtstr = QFileDialog::getOpenFileName( this, tr("Select SecureInfo_A/B"), QString(), tr("SecureInfo_A/B (SecureInfo_A SecureInfo_B);;All Files (*.*)")); ui->button_secure_info->setEnabled(true); InstallSecureData(file_path_qtstr.toStdString(), HW::UniqueData::GetSecureInfoAPath()); }); connect(ui->button_friend_code_seed, &QPushButton::clicked, this, [this] { ui->button_friend_code_seed->setEnabled(false); const QString file_path_qtstr = QFileDialog::getOpenFileName(this, tr("Select LocalFriendCodeSeed_A/B"), QString(), tr("LocalFriendCodeSeed_A/B (LocalFriendCodeSeed_A " "LocalFriendCodeSeed_B);;All Files (*.*)")); ui->button_friend_code_seed->setEnabled(true); InstallSecureData(file_path_qtstr.toStdString(), HW::UniqueData::GetLocalFriendCodeSeedBPath()); }); connect(ui->button_otp, &QPushButton::clicked, this, [this] { ui->button_otp->setEnabled(false); const QString file_path_qtstr = QFileDialog::getOpenFileName(this, tr("Select encrypted OTP file"), QString(), tr("Binary file (*.bin);;All Files (*.*)")); ui->button_otp->setEnabled(true); InstallSecureData(file_path_qtstr.toStdString(), HW::UniqueData::GetOTPPath()); }); connect(ui->button_movable, &QPushButton::clicked, this, [this] { ui->button_movable->setEnabled(false); const QString file_path_qtstr = QFileDialog::getOpenFileName( this, tr("Select movable.sed"), QString(), tr("Sed file (*.sed);;All Files (*.*)")); ui->button_movable->setEnabled(true); InstallSecureData(file_path_qtstr.toStdString(), HW::UniqueData::GetMovablePath()); }); for (u8 i = 0; i < country_names.size(); i++) { if (std::strcmp(country_names.at(i), "") != 0) { ui->combo_country->addItem(tr(country_names.at(i)), i); } } SetupPerGameUI(); ConfigureTime(); } ConfigureSystem::~ConfigureSystem() = default; void ConfigureSystem::SetConfiguration() { enabled = !system.IsPoweredOn(); ui->combo_init_clock->setCurrentIndex(static_cast(Settings::values.init_clock.GetValue())); QDateTime date_time; date_time.setSecsSinceEpoch(Settings::values.init_time.GetValue()); ui->edit_init_time->setDateTime(date_time); s64 init_time_offset = Settings::values.init_time_offset.GetValue(); int days_offset = static_cast(init_time_offset / 86400); ui->edit_init_time_offset_days->setValue(days_offset); u64 time_offset = std::abs(init_time_offset) - std::abs(days_offset * 86400); QTime time = QTime::fromMSecsSinceStartOfDay(static_cast(time_offset * 1000)); ui->edit_init_time_offset_time->setTime(time); ui->combo_init_ticks_type->setCurrentIndex( static_cast(Settings::values.init_ticks_type.GetValue())); ui->edit_init_ticks_value->setText( QString::number(Settings::values.init_ticks_override.GetValue())); ui->spinBox_steps_per_hour->setValue(Settings::values.steps_per_hour.GetValue()); cfg = Service::CFG::GetModule(system); ReadSystemSettings(); ui->group_system_settings->setEnabled(enabled); ui->group_real_console_unique_data->setEnabled(enabled); if (enabled) { ui->label_disable_info->hide(); } ui->toggle_new_3ds->setChecked(Settings::values.is_new_3ds.GetValue()); ui->toggle_lle_applets->setChecked(Settings::values.lle_applets.GetValue()); ui->enable_required_online_lle_modules->setChecked( Settings::values.enable_required_online_lle_modules.GetValue()); ui->plugin_loader->setChecked(Settings::values.plugin_loader_enabled.GetValue()); ui->allow_plugin_loader->setChecked(Settings::values.allow_plugin_loader.GetValue()); } void ConfigureSystem::ReadSystemSettings() { // set username username = cfg->GetUsername(); ui->edit_username->setText(QString::fromStdU16String(username)); // set birthday std::tie(birthmonth, birthday) = cfg->GetBirthday(); ui->combo_birthmonth->setCurrentIndex(birthmonth - 1); UpdateBirthdayComboBox( birthmonth - 1); // explicitly update it because the signal from setCurrentIndex is not reliable ui->combo_birthday->setCurrentIndex(birthday - 1); // set system language language_index = cfg->GetSystemLanguage(); ui->combo_language->setCurrentIndex(language_index); // set sound output mode sound_index = cfg->GetSoundOutputMode(); ui->combo_sound->setCurrentIndex(sound_index); // set the country code country_code = cfg->GetCountryCode(); ui->combo_country->setCurrentIndex(ui->combo_country->findData(country_code)); // set whether system setup is needed system_setup = cfg->IsSystemSetupNeeded(); ui->toggle_system_setup->setChecked(system_setup); // set the console id u64 console_id = cfg->GetConsoleUniqueId(); ui->label_console_id->setText( tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); mac_address = cfg->GetMacAddress(); ui->label_mac->setText(tr("MAC: %1").arg(QString::fromStdString(mac_address))); // set play coin play_coin = Service::PTM::Module::GetPlayCoins(); ui->spinBox_play_coins->setValue(play_coin); // Refresh secure data status RefreshSecureDataStatus(); } void ConfigureSystem::ApplyConfiguration() { if (enabled) { bool modified = false; // apply username std::u16string new_username = ui->edit_username->text().toStdU16String(); if (new_username != username) { cfg->SetUsername(new_username); modified = true; } // apply birthday s32 new_birthmonth = ui->combo_birthmonth->currentIndex() + 1; s32 new_birthday = ui->combo_birthday->currentIndex() + 1; if (birthmonth != new_birthmonth || birthday != new_birthday) { cfg->SetBirthday(static_cast(new_birthmonth), static_cast(new_birthday)); modified = true; } // apply language s32 new_language = ui->combo_language->currentIndex(); if (language_index != new_language) { cfg->SetSystemLanguage(static_cast(new_language)); modified = true; } // apply sound s32 new_sound = ui->combo_sound->currentIndex(); if (sound_index != new_sound) { cfg->SetSoundOutputMode(static_cast(new_sound)); modified = true; } // apply country u8 new_country = static_cast(ui->combo_country->currentData().toInt()); if (country_code != new_country) { cfg->SetCountryCode(new_country); modified = true; } // apply whether system setup is needed bool new_system_setup = static_cast(ui->toggle_system_setup->isChecked()); if (system_setup != new_system_setup) { cfg->SetSystemSetupNeeded(new_system_setup); modified = true; } // apply play coin u16 new_play_coin = static_cast(ui->spinBox_play_coins->value()); if (play_coin != new_play_coin) { Service::PTM::Module::SetPlayCoins(new_play_coin); } // update the config savegame if any item is modified. if (modified) { cfg->UpdateConfigNANDSavegame(); } ConfigurationShared::ApplyPerGameSetting(&Settings::values.is_new_3ds, ui->toggle_new_3ds, is_new_3ds); ConfigurationShared::ApplyPerGameSetting(&Settings::values.lle_applets, ui->toggle_lle_applets, lle_applets); ConfigurationShared::ApplyPerGameSetting( &Settings::values.enable_required_online_lle_modules, ui->enable_required_online_lle_modules, required_online_lle_modules); Settings::values.init_clock = static_cast(ui->combo_init_clock->currentIndex()); Settings::values.init_time = ui->edit_init_time->dateTime().toSecsSinceEpoch(); Settings::values.init_ticks_type = static_cast(ui->combo_init_ticks_type->currentIndex()); Settings::values.init_ticks_override = static_cast(ui->edit_init_ticks_value->text().toLongLong()); Settings::values.steps_per_hour = static_cast(ui->spinBox_steps_per_hour->value()); s64 time_offset_time = ui->edit_init_time_offset_time->time().msecsSinceStartOfDay() / 1000; s64 time_offset_days = ui->edit_init_time_offset_days->value() * 86400; if (time_offset_days < 0) { time_offset_time = -time_offset_time; } Settings::values.init_time_offset = time_offset_days + time_offset_time; Settings::values.is_new_3ds = ui->toggle_new_3ds->isChecked(); Settings::values.lle_applets = ui->toggle_lle_applets->isChecked(); Settings::values.enable_required_online_lle_modules = ui->enable_required_online_lle_modules->isChecked(); Settings::values.plugin_loader_enabled.SetValue(ui->plugin_loader->isChecked()); Settings::values.allow_plugin_loader.SetValue(ui->allow_plugin_loader->isChecked()); cfg->GetMacAddress() = mac_address; cfg->SaveMacAddress(); } } void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { if (birthmonth_index < 0 || birthmonth_index >= 12) return; // store current day selection s32 birthday_index = ui->combo_birthday->currentIndex(); // get number of days in the new selected month s32 days = days_in_month[birthmonth_index]; // if the selected day is out of range, // reset it to 1st if (birthday_index < 0 || birthday_index >= days) birthday_index = 0; // update the day combo box ui->combo_birthday->clear(); for (s32 i = 1; i <= days; ++i) { ui->combo_birthday->addItem(QString::number(i)); } // restore the day selection ui->combo_birthday->setCurrentIndex(birthday_index); } void ConfigureSystem::ConfigureTime() { QDateTime dt; dt.fromString(QStringLiteral("2000-01-01 00:00:01"), QStringLiteral("yyyy-MM-dd hh:mm:ss")); ui->edit_init_time->setMinimumDateTime(dt); ui->edit_init_time->setCalendarPopup(true); SetConfiguration(); UpdateInitTime(ui->combo_init_clock->currentIndex()); UpdateInitTicks(ui->combo_init_ticks_type->currentIndex()); } void ConfigureSystem::UpdateInitTime(int init_clock) { const bool is_global = Settings::IsConfiguringGlobal(); const bool is_fixed_time = static_cast(init_clock) == Settings::InitClock::FixedTime; ui->label_init_time->setVisible(is_fixed_time && is_global); ui->edit_init_time->setVisible(is_fixed_time && is_global); ui->label_init_time_offset->setVisible(!is_fixed_time && is_global); ui->edit_init_time_offset_days->setVisible(!is_fixed_time && is_global); ui->edit_init_time_offset_time->setVisible(!is_fixed_time && is_global); } void ConfigureSystem::UpdateInitTicks(int init_ticks_type) { const bool is_global = Settings::IsConfiguringGlobal(); const bool is_fixed = static_cast(init_ticks_type) == Settings::InitTicks::Fixed; ui->label_init_ticks_value->setVisible(is_fixed && is_global); ui->edit_init_ticks_value->setVisible(is_fixed && is_global); } void ConfigureSystem::RefreshConsoleID() { QMessageBox::StandardButton reply; QString warning_text = tr("This will replace your current virtual 3DS console ID with a new one. " "Your current virtual 3DS console ID will not be recoverable. " "This might have unexpected effects in applications. This might fail " "if you use an outdated config save. Continue?"); reply = QMessageBox::critical(this, tr("Warning"), warning_text, QMessageBox::No | QMessageBox::Yes); if (reply == QMessageBox::No) { return; } const auto [random_number, console_id] = cfg->GenerateConsoleUniqueId(); cfg->SetConsoleUniqueId(random_number, console_id); cfg->UpdateConfigNANDSavegame(); ui->label_console_id->setText( tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); } void ConfigureSystem::RefreshMAC() { QMessageBox::StandardButton reply; QString warning_text = tr("This will replace your current MAC address with a new one. " "It is not recommended to do this if you got the MAC address from " "your real console using the setup tool. Continue?"); reply = QMessageBox::warning(this, tr("Warning"), warning_text, QMessageBox::No | QMessageBox::Yes); if (reply == QMessageBox::No) { return; } mac_address = Service::CFG::GenerateRandomMAC(); ui->label_mac->setText(tr("MAC: %1").arg(QString::fromStdString(mac_address))); } void ConfigureSystem::UnlinkConsole() { QMessageBox::StandardButton reply; QString warning_text = tr("This action will unlink your real console from Azahar, with the following " "consequences:
  • Your OTP, SecureInfo and LocalFriendCodeSeed will be removed " "from Azahar.
  • Your friend list will reset and you will be logged out of your " "NNID/PNID account.
  • System files and eshop titles obtained through Azahar will " "become inaccessible until the same console is linked again (save data will not be " "lost).

Continue?"); reply = QMessageBox::warning(this, tr("Warning"), warning_text, QMessageBox::No | QMessageBox::Yes); if (reply == QMessageBox::No) { return; } HW::UniqueData::UnlinkConsole(); RefreshSecureDataStatus(); } void ConfigureSystem::InstallSecureData(const std::string& from_path, const std::string& to_path) { std::string from = FileUtil::SanitizePath(from_path, FileUtil::DirectorySeparator::PlatformDefault); std::string to = FileUtil::SanitizePath(to_path, FileUtil::DirectorySeparator::PlatformDefault); if (from.empty() || from == to) { return; } FileUtil::CreateFullPath(to); FileUtil::Copy(from, to); HW::UniqueData::InvalidateSecureData(); RefreshSecureDataStatus(); } void ConfigureSystem::RefreshSecureDataStatus() { auto status_to_str = [](HW::UniqueData::SecureDataLoadStatus status) { switch (status) { case HW::UniqueData::SecureDataLoadStatus::Loaded: return "Loaded"; case HW::UniqueData::SecureDataLoadStatus::InvalidSignature: return "Loaded (Invalid Signature)"; case HW::UniqueData::SecureDataLoadStatus::NotFound: return "Not Found"; case HW::UniqueData::SecureDataLoadStatus::Invalid: return "Invalid"; case HW::UniqueData::SecureDataLoadStatus::IOError: return "IO Error"; default: return ""; } }; ui->label_secure_info_status->setText( tr((std::string("Status: ") + status_to_str(HW::UniqueData::LoadSecureInfoA())).c_str())); ui->label_friend_code_seed_status->setText( tr((std::string("Status: ") + status_to_str(HW::UniqueData::LoadLocalFriendCodeSeedB())) .c_str())); ui->label_otp_status->setText( tr((std::string("Status: ") + status_to_str(HW::UniqueData::LoadOTP())).c_str())); ui->label_movable_status->setText( tr((std::string("Status: ") + status_to_str(HW::UniqueData::LoadMovable())).c_str())); if (HW::UniqueData::IsFullConsoleLinked()) { ui->linked_console->setVisible(true); ui->button_otp->setEnabled(false); ui->button_secure_info->setEnabled(false); ui->button_friend_code_seed->setEnabled(false); } else { ui->linked_console->setVisible(false); } } void ConfigureSystem::RetranslateUI() { ui->retranslateUi(this); } void ConfigureSystem::SetupPerGameUI() { // Block the global settings if a game is currently running that overrides them if (Settings::IsConfiguringGlobal()) { ui->toggle_new_3ds->setEnabled(Settings::values.is_new_3ds.UsingGlobal()); ui->toggle_lle_applets->setEnabled(Settings::values.lle_applets.UsingGlobal()); ui->enable_required_online_lle_modules->setEnabled( Settings::values.enable_required_online_lle_modules.UsingGlobal()); return; } // Hide most settings for now, we can implement them later ui->label_username->setVisible(false); ui->label_birthday->setVisible(false); ui->label_init_clock->setVisible(false); ui->label_init_time->setVisible(false); ui->label_init_ticks_type->setVisible(false); ui->label_init_ticks_value->setVisible(false); ui->label_console_id->setVisible(false); ui->label_mac->setVisible(false); ui->label_sound->setVisible(false); ui->label_language->setVisible(false); ui->label_country->setVisible(false); ui->label_play_coins->setVisible(false); ui->label_steps_per_hour->setVisible(false); ui->edit_username->setVisible(false); ui->spinBox_play_coins->setVisible(false); ui->spinBox_steps_per_hour->setVisible(false); ui->combo_birthday->setVisible(false); ui->combo_birthmonth->setVisible(false); ui->combo_init_clock->setVisible(false); ui->combo_init_ticks_type->setVisible(false); ui->combo_sound->setVisible(false); ui->combo_language->setVisible(false); ui->combo_country->setVisible(false); ui->label_init_time_offset->setVisible(false); ui->edit_init_time_offset_days->setVisible(false); ui->edit_init_time_offset_time->setVisible(false); ui->edit_init_ticks_value->setVisible(false); ui->toggle_system_setup->setVisible(false); ui->button_regenerate_console_id->setVisible(false); ui->button_regenerate_mac->setVisible(false); // Apps can change the state of the plugin loader, so plugins load // to a chainloaded app with specific parameters. Don't allow // the plugin loader state to be configured per-game as it may // mess things up. ui->label_plugin_loader->setVisible(false); ui->plugin_loader->setVisible(false); ui->allow_plugin_loader->setVisible(false); ui->group_real_console_unique_data->setVisible(false); ConfigurationShared::SetColoredTristate(ui->toggle_new_3ds, Settings::values.is_new_3ds, is_new_3ds); ConfigurationShared::SetColoredTristate(ui->toggle_lle_applets, Settings::values.lle_applets, lle_applets); ConfigurationShared::SetColoredTristate(ui->enable_required_online_lle_modules, Settings::values.enable_required_online_lle_modules, required_online_lle_modules); }