diff --git a/docs/user/Native.md b/docs/user/Native.md new file mode 100644 index 0000000000..ec1cd02253 --- /dev/null +++ b/docs/user/Native.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/docs/user/README.md b/docs/user/README.md index 64895f4aa8..5b93cee4d6 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -11,3 +11,4 @@ This handbook is primarily aimed at the end-user - baking useful knowledge for e - **[Testing](Testing.md)** - **[Data, savefiles and storage](Storage.md)** - **[Orphaned Profiles](Orphaned.md)** +- **[Native Application Development](Native.md)** diff --git a/src/common/settings.h b/src/common/settings.h index b424a83985..4114a21680 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -740,10 +740,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..4d51b42677 100644 --- a/src/core/crypto/key_manager.h +++ b/src/core/crypto/key_manager.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -311,7 +314,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 c9a2a1f497..d69d2252f5 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -961,15 +961,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(), 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(), end, out_console_serial->serial_number.begin()); + } R_SUCCEED(); } @@ -1071,10 +1079,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(); } @@ -1343,52 +1350,44 @@ Result ISystemSettingsServer::GetHttpAuthConfigs(Out out_count, OutBuffertoggle_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()); +#ifdef YUZU_USE_QT_WEB_ENGINE + ui->disable_web_applet->setChecked(Settings::values.disable_web_applet.GetValue()); +#else + ui->disable_web_applet->setChecked(true); +#endif + + // 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,14 +87,7 @@ 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()); -#ifdef YUZU_USE_QT_WEB_ENGINE - ui->disable_web_applet->setChecked(Settings::values.disable_web_applet.GetValue()); -#else - ui->disable_web_applet->setChecked(true); - ui->disable_web_applet->setVisible(false); -#endif } void ConfigureDebug::ApplyConfiguration() { 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