diff --git a/docs/User.md b/docs/User.md index 7928a90615..bf41415911 100644 --- a/docs/User.md +++ b/docs/User.md @@ -10,3 +10,4 @@ This handbook is primarily aimed at the end-user - baking useful knowledge for e - **[Platforms and Architectures](user/Architectures.md)** - **[Testing](user/Testing.md)** - **[Data, savefiles and storage](user/Storage.md)** +- **[Native Application Development](user/Development.md)** diff --git a/docs/user/Development.md b/docs/user/Development.md new file mode 100644 index 0000000000..ec1cd02253 --- /dev/null +++ b/docs/user/Development.md @@ -0,0 +1,12 @@ +# User Handbook - Native Application Development + +Debugging on physical hardware can get tedious and time consuming. Users are empowered with the debugging capabilities of the emulator to ensure their applications run as-is on the system. To the greatest extent possible atleast. + +## Debugging + +**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. diff --git a/src/common/settings.h b/src/common/settings.h index 1dc3bdca20..969108d05c 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -735,10 +735,11 @@ struct Values { Setting disable_web_applet{linkage, true, "disable_web_applet", Category::Debugging}; // Miscellaneous + Setting serial_battery{linkage, std::string(), "serial_battery", Category::Miscellaneous}; + Setting serial_unit{linkage, std::string(), "serial_unit", Category::Miscellaneous}; Setting log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; Setting log_flush_line{linkage, false, "flush_line", Category::Miscellaneous, Specialization::Default, true, true}; Setting censor_username{linkage, true, "censor_username", Category::Miscellaneous}; - Setting use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous}; Setting first_launch{linkage, true, "first_launch", Category::Miscellaneous}; // Network diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 50945eee91..353274d77b 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -640,32 +640,20 @@ KeyManager::KeyManager() { void KeyManager::ReloadKeys() { // Initialize keys - const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir); - - if (!Common::FS::CreateDir(yuzu_keys_dir)) { + const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir); + if (!Common::FS::CreateDir(keys_dir)) LOG_ERROR(Core, "Failed to create the keys directory."); - } - - if (Settings::values.use_dev_keys) { - dev_mode = true; - LoadFromFile(yuzu_keys_dir / "dev.keys_autogenerated", false); - LoadFromFile(yuzu_keys_dir / "dev.keys", false); - } else { - dev_mode = false; - LoadFromFile(yuzu_keys_dir / "prod.keys_autogenerated", false); - LoadFromFile(yuzu_keys_dir / "prod.keys", false); - } - - LoadFromFile(yuzu_keys_dir / "title.keys_autogenerated", true); - LoadFromFile(yuzu_keys_dir / "title.keys", true); - LoadFromFile(yuzu_keys_dir / "console.keys_autogenerated", false); - LoadFromFile(yuzu_keys_dir / "console.keys", false); + LoadFromFile(keys_dir / "prod.keys_autogenerated", false); + LoadFromFile(keys_dir / "prod.keys", false); + LoadFromFile(keys_dir / "title.keys_autogenerated", true); + LoadFromFile(keys_dir / "title.keys", true); + LoadFromFile(keys_dir / "console.keys_autogenerated", false); + LoadFromFile(keys_dir / "console.keys", false); } static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { - if (base.size() < begin + length) { + if (base.size() < begin + length) return false; - } return std::all_of(base.begin() + begin, base.begin() + begin + length, [](u8 c) { return std::isxdigit(c); }); } @@ -850,9 +838,8 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname, const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir); std::string filename = "title.keys_autogenerated"; - if (category == KeyCategory::Standard) { - filename = dev_mode ? "dev.keys_autogenerated" : "prod.keys_autogenerated"; + filename = "prod.keys_autogenerated"; } else if (category == KeyCategory::Console) { filename = "console.keys_autogenerated"; } @@ -947,17 +934,10 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) { } bool KeyManager::KeyFileExists(bool title) { - const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir); - - if (title) { - return Common::FS::Exists(yuzu_keys_dir / "title.keys"); - } - - if (Settings::values.use_dev_keys) { - return Common::FS::Exists(yuzu_keys_dir / "dev.keys"); - } - - return Common::FS::Exists(yuzu_keys_dir / "prod.keys"); + const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir); + if (title) + return Common::FS::Exists(keys_dir / "title.keys"); + return Common::FS::Exists(keys_dir / "prod.keys"); } void KeyManager::DeriveSDSeedLazy() { diff --git a/src/core/crypto/key_manager.h b/src/core/crypto/key_manager.h index 7de21f8a45..a3d64f099c 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -311,7 +311,6 @@ private: std::array eticket_extended_kek{}; RSAKeyPair<2048> eticket_rsa_keypair{}; - bool dev_mode; void LoadFromFile(const std::filesystem::path& file_path, bool is_title_keys); template diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index 22e12b1b9c..009aebea96 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -948,15 +948,23 @@ Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary 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(), s.end(), out_battery_lot->lot_number.begin()); + } R_SUCCEED(); } Result ISystemSettingsServer::GetSerialNumber(Out out_console_serial) { LOG_INFO(Service_SET, "called"); - *out_console_serial = {"YUZ10000000001"}; + if (auto const s = ::Settings::values.serial_unit.GetValue(); !s.empty()) { + auto const max_size = out_console_serial->serial_number.size(); + auto const end = s.size() > max_size ? s.begin() + max_size : s.end(); + std::copy(s.begin(), s.end(), out_console_serial->serial_number.begin()); + } R_SUCCEED(); } @@ -1058,10 +1066,9 @@ Result ISystemSettingsServer::SetDeviceNickName( } Result ISystemSettingsServer::GetProductModel(Out out_product_model) { - const u32 product_model = 1; - + // Most certainly should be 1 -- definitely should not be 2, but it's worth tinkering with anyways + u32 const product_model = 1; LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model); - *out_product_model = product_model; R_SUCCEED(); } @@ -1324,52 +1331,44 @@ Result ISystemSettingsServer::SetPanelCrcMode(s32 panel_crc_mode) { } void ISystemSettingsServer::SetupSettings() { - auto system_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000050"; + auto system_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000050"; if (!LoadSettingsFile(system_dir, []() { return DefaultSystemSettings(); })) { ASSERT(false); } - auto private_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000052"; + auto private_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000052"; if (!LoadSettingsFile(private_dir, []() { return DefaultPrivateSettings(); })) { ASSERT(false); } - auto device_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000053"; + auto device_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000053"; if (!LoadSettingsFile(device_dir, []() { return DefaultDeviceSettings(); })) { ASSERT(false); } - auto appln_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000054"; + auto appln_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000054"; if (!LoadSettingsFile(appln_dir, []() { return DefaultApplnSettings(); })) { ASSERT(false); } } void ISystemSettingsServer::StoreSettings() { - auto system_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000050"; + auto system_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000050"; if (!StoreSettingsFile(system_dir, m_system_settings)) { LOG_ERROR(Service_SET, "Failed to store System settings"); } - auto private_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000052"; + auto private_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000052"; if (!StoreSettingsFile(private_dir, m_private_settings)) { LOG_ERROR(Service_SET, "Failed to store Private settings"); } - auto device_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000053"; + auto device_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000053"; if (!StoreSettingsFile(device_dir, m_device_settings)) { LOG_ERROR(Service_SET, "Failed to store Device settings"); } - auto appln_dir = - Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000054"; + auto appln_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "system/save/8000000000000054"; if (!StoreSettingsFile(appln_dir, m_appln_settings)) { LOG_ERROR(Service_SET, "Failed to store ApplLn settings"); } @@ -1380,9 +1379,8 @@ void ISystemSettingsServer::StoreSettingsThreadFunc(std::stop_token stop_token) while (Common::StoppableTimedWait(stop_token, std::chrono::minutes(1))) { std::scoped_lock l{m_save_needed_mutex}; - if (!std::exchange(m_save_needed, false)) { + if (!std::exchange(m_save_needed, false)) continue; - } StoreSettings(); } } diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 70fd90734f..a308a7e692 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -39,20 +39,30 @@ void ConfigureDebug::SetConfiguration() { ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue()); ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue()); ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue()); - ui->toggle_console->setEnabled(runtime_lock); - ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); ui->flush_line->setChecked(Settings::values.log_flush_line.GetValue()); ui->censor_username->setChecked(Settings::values.censor_username.GetValue()); - ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args.GetValue())); - ui->fs_access_log->setEnabled(runtime_lock); - ui->fs_access_log->setChecked(Settings::values.enable_fs_access_log.GetValue()); ui->reporting_services->setChecked(Settings::values.reporting_services.GetValue()); ui->dump_audio_commands->setChecked(Settings::values.dump_audio_commands.GetValue()); ui->quest_flag->setChecked(Settings::values.quest_flag.GetValue()); ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue()); ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue()); ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue()); + ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); + ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue()); + ui->disable_web_applet->setChecked(Settings::values.disable_web_applet.GetValue()); + + // 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->setText(QString::fromStdString(Settings::values.program_args.GetValue())); + ui->toggle_console->setEnabled(runtime_lock); + ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); + ui->fs_access_log->setEnabled(runtime_lock); + ui->fs_access_log->setChecked(Settings::values.enable_fs_access_log.GetValue()); ui->enable_renderdoc_hotkey->setEnabled(runtime_lock); ui->enable_renderdoc_hotkey->setChecked(Settings::values.enable_renderdoc_hotkey.GetValue()); ui->disable_buffer_reorder->setEnabled(runtime_lock); @@ -73,9 +83,6 @@ void ConfigureDebug::SetConfiguration() { ui->disable_macro_hle->setChecked(Settings::values.disable_macro_hle.GetValue()); ui->disable_loop_safety_checks->setEnabled(runtime_lock); ui->disable_loop_safety_checks->setChecked(Settings::values.disable_shader_loop_safety_checks.GetValue()); - ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); - ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue()); - ui->disable_web_applet->setChecked(Settings::values.disable_web_applet.GetValue()); #ifndef YUZU_USE_QT_WEB_ENGINE ui->disable_web_applet->setVisible(false); diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 1f302bf118..005bbc014d 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -467,7 +467,87 @@ Debugging + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Battery Serial: + + + + + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Unit Serial: + + + + + + + + + + Qt::Orientation::Vertical @@ -483,7 +563,7 @@ - + Enable this to output the latest generated audio command list to the console. Only affects games using the audio renderer. @@ -493,14 +573,14 @@ - + Flush log output on each line - + Enable FS Access Log @@ -514,7 +594,7 @@ - + Censor username in logs