diff --git a/src/core/core.cpp b/src/core/core.cpp index 3c57a62ec9..5205890b45 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -175,6 +175,8 @@ struct System::Impl { GetAndResetPerfStats(); perf_stats.BeginSystemFrame(); + nfc_activate = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "Nfc:ActivateTag"); + return ResultStatus::Success; } @@ -289,6 +291,10 @@ struct System::Impl { std::array, NUM_CPU_CORES - 1> cpu_core_threads; std::size_t active_core{}; ///< Active core, only used in single thread mode + /// NFC Loading + Kernel::SharedPtr nfc_activate; + std::string nfc_filename; + /// Service manager std::shared_ptr service_manager; @@ -465,6 +471,19 @@ std::shared_ptr System::GetFilesystem() const { return impl->virtual_filesystem; } +void System::LoadAmiibo(const std::string& filename) { + impl->nfc_filename = filename; + impl->nfc_activate->Signal(); +} + +Kernel::SharedPtr& System::GetNFCEvent() const { + return impl->nfc_activate; +} + +std::string& System::GetNFCFilename() const { + return impl->nfc_filename; +} + System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { return impl->Init(emu_window); } diff --git a/src/core/core.h b/src/core/core.h index 173be45f87..40f6b6e85a 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -23,6 +23,7 @@ namespace Kernel { class KernelCore; class Process; class Scheduler; +class Event; } // namespace Kernel namespace Loader { @@ -224,6 +225,12 @@ public: std::shared_ptr GetFilesystem() const; + std::string& GetNFCFilename() const; + + void LoadAmiibo(const std::string& path); + + Kernel::SharedPtr& GetNFCEvent() const; + private: System(); diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 8fec97db83..e9ce19ce8f 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp @@ -10,12 +10,13 @@ #include "core/hle/service/nfc/nfc.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" +#include "core/settings.h" namespace Service::NFC { class IAm final : public ServiceFramework { public: - explicit IAm() : ServiceFramework{"IAm"} { + explicit IAm() : ServiceFramework{"NFC::IAm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -52,7 +53,7 @@ private: class MFIUser final : public ServiceFramework { public: - explicit MFIUser() : ServiceFramework{"IUser"} { + explicit MFIUser() : ServiceFramework{"NFC::MFIUser"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -100,13 +101,13 @@ private: class IUser final : public ServiceFramework { public: - explicit IUser() : ServiceFramework{"IUser"} { + explicit IUser() : ServiceFramework{"NFC::IUser"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "Initialize"}, - {1, nullptr, "Finalize"}, - {2, nullptr, "GetState"}, - {3, nullptr, "IsNfcEnabled"}, + {0, &IUser::InitializeOld, "InitializeOld"}, + {1, &IUser::FinalizeOld, "FinalizeOld"}, + {2, &IUser::GetStateOld, "GetStateOld"}, + {3, &IUser::IsNfcEnabledOld, "IsNfcEnabledOld"}, {400, nullptr, "Initialize"}, {401, nullptr, "Finalize"}, {402, nullptr, "GetState"}, @@ -130,11 +131,43 @@ public: RegisterHandlers(functions); } + +private: + void InitializeOld(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0}; + rb.Push(RESULT_SUCCESS); + + // We don't deal with hardware initialization so we can just stub this. + LOG_DEBUG(Service_NFC, "called"); + } + + void IsNfcEnabledOld(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(Settings::values.enable_nfc); + + LOG_DEBUG(Service_NFC, "IsNfcEnabledOld"); + } + + void GetStateOld(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NFC, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(6); // TODO(ogniK): Figure out if this matches nfp + } + + void FinalizeOld(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NFC, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } }; class NFC_U final : public ServiceFramework { public: - explicit NFC_U() : ServiceFramework{"nfc:u"} { + explicit NFC_U() : ServiceFramework{"nfc:user"} { // clang-format off static const FunctionInfo functions[] = { {0, &NFC_U::CreateUserInterface, "CreateUserInterface"}, diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 39c0c1e63f..1bc4de3f2f 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/file_util.h" #include "common/logging/log.h" #include "core/core.h" #include "core/hle/ipc_helpers.h" @@ -19,25 +20,25 @@ Module::Interface::~Interface() = default; class IUser final : public ServiceFramework { public: - IUser() : ServiceFramework("IUser") { + IUser() : ServiceFramework("NFP::IUser") { static const FunctionInfo functions[] = { {0, &IUser::Initialize, "Initialize"}, - {1, nullptr, "Finalize"}, + {1, &IUser::Finalize, "Finalize"}, {2, &IUser::ListDevices, "ListDevices"}, - {3, nullptr, "StartDetection"}, - {4, nullptr, "StopDetection"}, - {5, nullptr, "Mount"}, - {6, nullptr, "Unmount"}, + {3, &IUser::StartDetection, "StartDetection"}, + {4, &IUser::StopDetection, "StopDetection"}, + {5, &IUser::Mount, "Mount"}, + {6, &IUser::Unmount, "Unmount"}, {7, nullptr, "OpenApplicationArea"}, {8, nullptr, "GetApplicationArea"}, {9, nullptr, "SetApplicationArea"}, {10, nullptr, "Flush"}, {11, nullptr, "Restore"}, {12, nullptr, "CreateApplicationArea"}, - {13, nullptr, "GetTagInfo"}, + {13, &IUser::GetTagInfo, "GetTagInfo"}, {14, nullptr, "GetRegisterInfo"}, {15, nullptr, "GetCommonInfo"}, - {16, nullptr, "GetModelInfo"}, + {16, &IUser::GetModelInfo, "GetModelInfo"}, {17, &IUser::AttachActivateEvent, "AttachActivateEvent"}, {18, &IUser::AttachDeactivateEvent, "AttachDeactivateEvent"}, {19, &IUser::GetState, "GetState"}, @@ -50,8 +51,6 @@ public: RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - activate_event = - Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:ActivateEvent"); deactivate_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); availability_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, @@ -66,15 +65,46 @@ private: enum class DeviceState : u32 { Initialized = 0, + SearchingForTag = 1, + TagFound = 2, + TagRemoved = 3, + TagNearby = 4, + Unknown5 = 5, + Finalized = 6 }; + struct TagInfo { + std::array uuid; + u8 uuid_length; // TODO(ogniK): Figure out if this is actual the uuid length or does it mean + // something else + INSERT_PADDING_BYTES(0x15); + u32_le protocol; + u32_le tag_type; + INSERT_PADDING_BYTES(0x30); + }; + static_assert(sizeof(TagInfo) == 0x58, "TagInfo is an invalid size"); + + struct ModelInfo { + std::array amiibo_identification_block; + INSERT_PADDING_BYTES(0x38); + }; + static_assert(sizeof(ModelInfo) == 0x40, "ModelInfo is an invalid size"); + void Initialize(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NFP, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2, 0}; + rb.Push(RESULT_SUCCESS); state = State::Initialized; - IPC::ResponseBuilder rb{ctx, 2}; + LOG_DEBUG(Service_NFC, "called"); + } + + void GetState(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3, 0}; rb.Push(RESULT_SUCCESS); + rb.PushRaw(static_cast(state)); + + LOG_DEBUG(Service_NFC, "called"); } void ListDevices(Kernel::HLERequestContext& ctx) { @@ -83,71 +113,144 @@ private: ctx.WriteBuffer(&device_handle, sizeof(device_handle)); - LOG_WARNING(Service_NFP, "(STUBBED) called, array_size={}", array_size); + LOG_DEBUG(Service_NFP, "called, array_size={}", array_size); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(0); + rb.Push(1); + } + + void GetNpadId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const u64 dev_handle = rp.Pop(); + LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(npad_id); } void AttachActivateEvent(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 dev_handle = rp.Pop(); - LOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); + LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(activate_event); + + Core::System& system{Core::System::GetInstance()}; + rb.PushCopyObjects(system.GetNFCEvent()); } void AttachDeactivateEvent(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 dev_handle = rp.Pop(); - LOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); + LOG_DEBUG(Service_NFP, "called, dev_handle=0x{:X}", dev_handle); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(deactivate_event); } - void GetState(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NFP, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 3}; + void StopDetection(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + switch (device_state) { + case DeviceState::TagFound: + case DeviceState::TagNearby: + deactivate_event->Signal(); + [[fallthrough]]; + case DeviceState::SearchingForTag: + case DeviceState::TagRemoved: + device_state = DeviceState::Initialized; + break; + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - rb.Push(static_cast(state)); } void GetDeviceState(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_NFP, "(STUBBED) called"); + LOG_DEBUG(Service_NFP, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); rb.Push(static_cast(device_state)); } - void GetNpadId(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 dev_handle = rp.Pop(); - LOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); - IPC::ResponseBuilder rb{ctx, 3}; + void StartDetection(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + + if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) { + device_state = DeviceState::SearchingForTag; + } + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void GetTagInfo(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + TagInfo tag_info{}; + Core::System& system{Core::System::GetInstance()}; + auto nfc_file = FileUtil::IOFile(system.GetNFCFilename(), "rb"); + size_t read_length = nfc_file.ReadBytes(tag_info.uuid.data(), sizeof(tag_info.uuid.size())); + tag_info.uuid_length = static_cast(read_length); + tag_info.protocol = 1; // TODO(ogniK): Figure out actual values + tag_info.tag_type = 2; + ctx.WriteBuffer(&tag_info, sizeof(TagInfo)); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void Mount(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + + device_state = DeviceState::TagNearby; + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void GetModelInfo(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + + Core::System& system{Core::System::GetInstance()}; + auto nfc_file = FileUtil::IOFile(system.GetNFCFilename(), "rb"); + nfc_file.Seek(0x54, SEEK_SET); + ModelInfo model_info{}; + nfc_file.ReadBytes(model_info.amiibo_identification_block.data(), + model_info.amiibo_identification_block.size()); + ctx.WriteBuffer(&model_info, sizeof(ModelInfo)); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void Unmount(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + + device_state = DeviceState::TagFound; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void Finalize(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NFP, "called"); + + device_state = DeviceState::Finalized; + + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - rb.Push(npad_id); } void AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const u64 dev_handle = rp.Pop(); - LOG_WARNING(Service_NFP, "(STUBBED) called, dev_handle=0x{:X}", dev_handle); + LOG_WARNING(Service_NFP, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2, 1}; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(availability_change_event); } - const u64 device_handle{0xDEAD}; - const u32 npad_id{0}; // This is the first player controller id + const u64 device_handle{Common::MakeMagic('Y', 'U', 'Z', 'U')}; + const u32 npad_id{0}; // Player 1 State state{State::NonInitialized}; DeviceState device_state{DeviceState::Initialized}; - Kernel::SharedPtr activate_event; Kernel::SharedPtr deactivate_event; Kernel::SharedPtr availability_change_event; }; diff --git a/src/core/settings.h b/src/core/settings.h index 8f2da01c85..ca80718e27 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -113,6 +113,7 @@ static const std::array mapping = {{ struct Values { // System bool use_docked_mode; + bool enable_nfc; std::string username; int language_index; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 71c6ebb414..d029590ff3 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -122,6 +122,7 @@ void Config::ReadValues() { qt_config->beginGroup("System"); Settings::values.use_docked_mode = qt_config->value("use_docked_mode", false).toBool(); + Settings::values.enable_nfc = qt_config->value("enable_nfc", true).toBool(); Settings::values.username = qt_config->value("username", "yuzu").toString().toStdString(); Settings::values.language_index = qt_config->value("language_index", 1).toInt(); qt_config->endGroup(); @@ -258,6 +259,7 @@ void Config::SaveValues() { qt_config->beginGroup("System"); qt_config->setValue("use_docked_mode", Settings::values.use_docked_mode); + qt_config->setValue("enable_nfc", Settings::values.enable_nfc); qt_config->setValue("username", QString::fromStdString(Settings::values.username)); qt_config->setValue("language_index", Settings::values.language_index); qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index f5db9e55bd..537d6e576e 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -31,6 +31,7 @@ void ConfigureGeneral::setConfiguration() { ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit); ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); + ui->enable_nfc->setChecked(Settings::values.enable_nfc); } void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) { @@ -45,4 +46,5 @@ void ConfigureGeneral::applyConfiguration() { Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); + Settings::values.enable_nfc = ui->enable_nfc->isChecked(); } diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index 1775c4d40c..b82fffde82 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -68,19 +68,26 @@ Emulation - + + + - - - - - Enable docked mode - - - - + + + Enable docked mode + + - + + + + Enable NFC + + + + + + diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index bef9df00da..fb840a5fbe 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -422,6 +422,7 @@ void GMainWindow::ConnectMenuEvents() { connect(ui.action_Select_SDMC_Directory, &QAction::triggered, this, [this] { OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget::SDMC); }); connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close); + connect(ui.action_Load_Amiibo, &QAction::triggered, this, &GMainWindow::OnLoadAmiibo); // Emulation connect(ui.action_Start, &QAction::triggered, this, &GMainWindow::OnStartGame); @@ -690,6 +691,7 @@ void GMainWindow::ShutdownGame() { ui.action_Stop->setEnabled(false); ui.action_Restart->setEnabled(false); ui.action_Report_Compatibility->setEnabled(false); + ui.action_Load_Amiibo->setEnabled(false); render_window->hide(); game_list->show(); game_list->setFilterFocus(); @@ -1174,6 +1176,7 @@ void GMainWindow::OnStartGame() { ui.action_Report_Compatibility->setEnabled(true); discord_rpc->Update(); + ui.action_Load_Amiibo->setEnabled(true); } void GMainWindow::OnPauseGame() { @@ -1278,6 +1281,18 @@ void GMainWindow::OnConfigure() { } } +void GMainWindow::OnLoadAmiibo() { + const QString extensions{"*.bin"}; + const QString file_filter = + tr("Amiibo File") + " (" + extensions + ");;" + tr("All Files (*.*)"); + const QString filename = QFileDialog::getOpenFileName( + this, tr("Load Amiibo"), UISettings::values.amiibo_path, file_filter); + if (!filename.isEmpty()) { + Core::System& system{Core::System::GetInstance()}; + system.LoadAmiibo(filename.toStdString()); + } +} + void GMainWindow::OnAbout() { AboutDialog aboutDialog(this); aboutDialog.exec(); @@ -1318,15 +1333,17 @@ void GMainWindow::UpdateStatusBar() { void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) { QMessageBox::StandardButton answer; QString status_message; - const QString common_message = tr( - "The game you are trying to load requires additional files from your Switch to be dumped " - "before playing.

For more information on dumping these files, please see the " - "following wiki page: Dumping System " - "Archives and the Shared Fonts from a Switch Console.

Would you like to quit " - "back to the game list? Continuing emulation may result in crashes, corrupted save " - "data, or other bugs."); + const QString common_message = + tr("The game you are trying to load requires additional files from your Switch to be " + "dumped " + "before playing.

For more information on dumping these files, please see the " + "following wiki page: Dumping System " + "Archives and the Shared Fonts from a Switch Console.

Would you like to " + "quit " + "back to the game list? Continuing emulation may result in crashes, corrupted save " + "data, or other bugs."); switch (result) { case Core::System::ResultStatus::ErrorSystemFiles: { QString message = "yuzu was unable to locate a Switch system archive"; @@ -1357,9 +1374,12 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det this, tr("Fatal Error"), tr("yuzu has encountered a fatal error, please see the log for more details. " "For more information on accessing the log, please see the following page: " - "How to " - "Upload the Log File.

Would you like to quit back to the game list? " - "Continuing emulation may result in crashes, corrupted save data, or other bugs."), + "How " + "to " + "Upload the Log File.

Would you like to quit back to the game " + "list? " + "Continuing emulation may result in crashes, corrupted save data, or other " + "bugs."), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); status_message = "Fatal Error encountered"; break; diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 3663d6aeda..212a5a88a0 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -164,6 +164,7 @@ private slots: void OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target); void OnMenuRecentFile(); void OnConfigure(); + void OnLoadAmiibo(); void OnAbout(); void OnToggleFilterBar(); void OnDisplayTitleBars(bool); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 9851f507d4..87456d68e1 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -57,8 +57,8 @@ Recent Files - - + + @@ -68,6 +68,8 @@ + + @@ -111,11 +113,14 @@ - - - Install File to NAND... - - + + + true + + + Install File to NAND... + + Load File... @@ -247,6 +252,14 @@ Restart + + + false + + + Load Amiibo... + + false diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h index 2e617d52ad..9a3ec5aa7a 100644 --- a/src/yuzu/ui_settings.h +++ b/src/yuzu/ui_settings.h @@ -44,6 +44,7 @@ struct Values { QString roms_path; QString symbols_path; QString gamedir; + QString amiibo_path; bool gamedir_deepscan; QStringList recent_files; diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 5e42e48b20..654a15a5cf 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -125,6 +125,7 @@ void Config::ReadValues() { // System Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); + Settings::values.enable_nfc = sdl2_config->GetBoolean("System", "enable_nfc", true); Settings::values.username = sdl2_config->Get("System", "username", "yuzu"); if (Settings::values.username.empty()) { Settings::values.username = "yuzu"; diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index a97b75f7b7..e0b223cd64 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -174,6 +174,10 @@ use_virtual_sd = # 1: Yes, 0 (default): No use_docked_mode = +# Allow the use of NFC in games +# 1 (default): Yes, 0 : No +enable_nfc = + # Sets the account username, max length is 32 characters # yuzu (default) username = yuzu