From 5ef71661ffd8bbea7b67ededfb883c237c828110 Mon Sep 17 00:00:00 2001 From: crueter Date: Tue, 28 Oct 2025 17:05:50 -0400 Subject: [PATCH] [qt] port QtCommon stuff from qml Ports some of the initialization stuff from QML branch, please test: - initialization - decryption - new user setup - input Signed-off-by: crueter --- src/qt_common/qt_common.cpp | 183 ++++++++++++++++++++++++++++++++-- src/qt_common/qt_common.h | 1 + src/yuzu/game_list.cpp | 4 - src/yuzu/game_list.h | 2 - src/yuzu/game_list_worker.cpp | 5 +- src/yuzu/main.cpp | 143 +------------------------- 6 files changed, 182 insertions(+), 156 deletions(-) diff --git a/src/qt_common/qt_common.cpp b/src/qt_common/qt_common.cpp index f2091df866..4a05ecc937 100644 --- a/src/qt_common/qt_common.cpp +++ b/src/qt_common/qt_common.cpp @@ -1,22 +1,37 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "common/literals.h" + +#include "common/memory_detect.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "hid_core/hid_core.h" +#include "network/network.h" #include "qt_common.h" + #include "common/fs/fs.h" -#include "common/fs/ryujinx_compat.h" +#include "common/fs/path_util.h" +#include "common/logging/backend.h" +#include "common/logging/log.h" +#include "common/scm_rev.h" +#include "core/memory.h" + +#ifdef ARCHITECTURE_x86_64 +#include "common/x64/cpu_detect.h" +#endif #include #include #include "common/logging/log.h" #include "core/frontend/emu_window.h" -#include "qt_common/abstract/frontend.h" -#include "qt_common/qt_string_lookup.h" +#include "qt_common/util/meta.h" #include #include #include +#include #if !defined(WIN32) && !defined(__APPLE__) #include @@ -24,6 +39,8 @@ #include #endif +using namespace Common::Literals; + namespace QtCommon { #ifdef YUZU_QT_WIDGETS @@ -36,8 +53,14 @@ std::unique_ptr system = nullptr; std::shared_ptr vfs = nullptr; std::unique_ptr provider = nullptr; -Core::Frontend::WindowSystemType GetWindowSystemType() -{ +const QStringList supported_file_extensions = {QStringLiteral("nro"), + QStringLiteral("nso"), + QStringLiteral("nca"), + QStringLiteral("xci"), + QStringLiteral("nsp"), + QStringLiteral("kip")}; + +Core::Frontend::WindowSystemType GetWindowSystemType() { // Determine WSI type based on Qt platform. QString platform_name = QGuiApplication::platformName(); if (platform_name == QStringLiteral("windows")) @@ -93,8 +116,88 @@ const QString tr(const std::string& str) return QGuiApplication::tr(str.c_str()); } +static void LogRuntimes() { +#ifdef _MSC_VER + // It is possible that the name of the dll will change. + // vcruntime140.dll is for 2015 and onwards + static constexpr char runtime_dll_name[] = "vcruntime140.dll"; + UINT sz = GetFileVersionInfoSizeA(runtime_dll_name, nullptr); + bool runtime_version_inspection_worked = false; + if (sz > 0) { + std::vector buf(sz); + if (GetFileVersionInfoA(runtime_dll_name, 0, sz, buf.data())) { + VS_FIXEDFILEINFO* pvi; + sz = sizeof(VS_FIXEDFILEINFO); + if (VerQueryValueA(buf.data(), "\\", reinterpret_cast(&pvi), &sz)) { + if (pvi->dwSignature == VS_FFI_SIGNATURE) { + runtime_version_inspection_worked = true; + LOG_INFO(Frontend, "MSVC Compiler: {} Runtime: {}.{}.{}.{}", _MSC_VER, + pvi->dwProductVersionMS >> 16, pvi->dwProductVersionMS & 0xFFFF, + pvi->dwProductVersionLS >> 16, pvi->dwProductVersionLS & 0xFFFF); + } + } + } + } + if (!runtime_version_inspection_worked) { + LOG_INFO(Frontend, "Unable to inspect {}", runtime_dll_name); + } +#endif + LOG_INFO(Frontend, "Qt Compile: {} Runtime: {}", QT_VERSION_STR, qVersion()); +} + +static QString PrettyProductName() { +#ifdef _WIN32 + // After Windows 10 Version 2004, Microsoft decided to switch to a different notation: 20H2 + // With that notation change they changed the registry key used to denote the current version + QSettings windows_registry( + QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), + QSettings::NativeFormat); + const QString release_id = windows_registry.value(QStringLiteral("ReleaseId")).toString(); + if (release_id == QStringLiteral("2009")) { + const u32 current_build = windows_registry.value(QStringLiteral("CurrentBuild")).toUInt(); + const QString display_version = + windows_registry.value(QStringLiteral("DisplayVersion")).toString(); + const u32 ubr = windows_registry.value(QStringLiteral("UBR")).toUInt(); + u32 version = 10; + if (current_build >= 22000) { + version = 11; + } + return QStringLiteral("Windows %1 Version %2 (Build %3.%4)") + .arg(QString::number(version), display_version, QString::number(current_build), + QString::number(ubr)); + } +#endif + return QSysInfo::prettyProductName(); +} + +#ifdef _WIN32 +static void OverrideWindowsFont() { + // Qt5 chooses these fonts on Windows and they have fairly ugly alphanumeric/cyrillic characters + // Asking to use "MS Shell Dlg 2" gives better other chars while leaving the Chinese Characters. + const QString startup_font = QApplication::font().family(); + const QStringList ugly_fonts = {QStringLiteral("SimSun"), QStringLiteral("PMingLiU")}; + if (ugly_fonts.contains(startup_font)) { + QApplication::setFont(QFont(QStringLiteral("MS Shell Dlg 2"), 9, QFont::Normal)); + } +} +#endif + +static void RemoveCachedContents() { + const auto cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir); + const auto offline_fonts = cache_dir / "fonts"; + const auto offline_manual = cache_dir / "offline_web_applet_manual"; + const auto offline_legal_information = cache_dir / "offline_web_applet_legal_information"; + const auto offline_system_data = cache_dir / "offline_web_applet_system_data"; + + Common::FS::RemoveDirRecursively(offline_fonts); + Common::FS::RemoveDirRecursively(offline_manual); + Common::FS::RemoveDirRecursively(offline_legal_information); + Common::FS::RemoveDirRecursively(offline_system_data); +} + + #ifdef YUZU_QT_WIDGETS -void Init(QWidget* root) +void Init(QWidget * root) #else void Init(QObject* root) #endif @@ -103,6 +206,74 @@ void Init(QObject* root) rootObject = root; vfs = std::make_unique(); provider = std::make_unique(); + + // initialization stuff + Common::FS::CreateEdenPaths(); + + system->Initialize(); + + Common::Log::Initialize(); + Common::Log::Start(); + + Network::Init(); + + QtCommon::Meta::RegisterMetaTypes(); + system->HIDCore().ReloadInputDevices(); + + // build version + const auto branch_name = std::string(Common::g_scm_branch); + const auto description = std::string(Common::g_scm_desc); + const auto build_id = std::string(Common::g_build_id); + + const auto yuzu_build = fmt::format("Eden Development Build | {}-{}", branch_name, description); + const auto override_build = + fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id); + const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; + const auto processor_count = std::thread::hardware_concurrency(); + + // info logging + LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version); + LogRuntimes(); +#ifdef ARCHITECTURE_x86_64 + const auto& caps = Common::GetCPUCaps(); + std::string cpu_string = caps.cpu_string; + if (caps.avx || caps.avx2 || caps.avx512f) { + cpu_string += " | AVX"; + if (caps.avx512f) { + cpu_string += "512"; + } else if (caps.avx2) { + cpu_string += '2'; + } + if (caps.fma || caps.fma4) { + cpu_string += " | FMA"; + } + } + LOG_INFO(Frontend, "Host CPU: {}", cpu_string); + if (std::optional processor_core = Common::GetProcessorCount()) { + LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core); + } +#endif + LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count); + LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString()); + LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", + Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); + LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB}); +#ifdef _WIN32 + LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", + std::chrono::duration_cast>( + Common::Windows::SetCurrentTimerResolutionToMaximum()) + .count()); + QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution()); +#endif + + // content providers + system->SetContentProvider(std::make_unique()); + system->RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual, + provider.get()); + system->GetFileSystemController().CreateFactories(*vfs); + + // Remove cached contents generated during the previous session + RemoveCachedContents(); } std::filesystem::path GetEdenCommand() diff --git a/src/qt_common/qt_common.h b/src/qt_common/qt_common.h index a2700427ab..df5ae465d9 100644 --- a/src/qt_common/qt_common.h +++ b/src/qt_common/qt_common.h @@ -23,6 +23,7 @@ extern QObject *rootObject; extern std::unique_ptr system; extern std::shared_ptr vfs; extern std::unique_ptr provider; +extern const QStringList supported_file_extensions; typedef std::function QtProgressCallback; diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 89bbb6078f..b462229625 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -878,10 +878,6 @@ void GameList::LoadInterfaceLayout() { header->resizeSection(COLUMN_NAME, header->width()); } -const QStringList GameList::supported_file_extensions = { - QStringLiteral("nso"), QStringLiteral("nro"), QStringLiteral("nca"), - QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")}; - void GameList::RefreshGameDirectory() { if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) { diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index 0b3ac7fcde..f5ebab1f0c 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -89,8 +89,6 @@ public: /// Disables events from the emulated controller void UnloadController(); - static const QStringList supported_file_extensions; - public slots: void RefreshGameDirectory(); diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 4542b63100..ecf8cf62a6 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -26,11 +26,12 @@ #include "core/file_sys/registered_cache.h" #include "core/file_sys/submission_package.h" #include "core/loader/loader.h" +#include "qt_common/config/uisettings.h" +#include "qt_common/qt_common.h" #include "yuzu/compatibility_list.h" #include "yuzu/game_list.h" #include "yuzu/game_list_p.h" #include "yuzu/game_list_worker.h" -#include "qt_common/config/uisettings.h" namespace { @@ -144,7 +145,7 @@ void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const bool HasSupportedFileExtension(const std::string& file_name) { const QFileInfo file = QFileInfo(QString::fromStdString(file_name)); - return GameList::supported_file_extensions.contains(file.suffix(), Qt::CaseInsensitive); + return QtCommon::supported_file_extensions.contains(file.suffix(), Qt::CaseInsensitive); } bool IsExtractedNCAMain(const std::string& file_name) { diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 849ffa84de..d1a65091c9 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -303,85 +303,6 @@ enum class CalloutFlag : uint32_t { const int GMainWindow::max_recent_files_item; -static void RemoveCachedContents() { - const auto cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir); - const auto offline_fonts = cache_dir / "fonts"; - const auto offline_manual = cache_dir / "offline_web_applet_manual"; - const auto offline_legal_information = cache_dir / "offline_web_applet_legal_information"; - const auto offline_system_data = cache_dir / "offline_web_applet_system_data"; - - Common::FS::RemoveDirRecursively(offline_fonts); - Common::FS::RemoveDirRecursively(offline_manual); - Common::FS::RemoveDirRecursively(offline_legal_information); - Common::FS::RemoveDirRecursively(offline_system_data); -} - -static void LogRuntimes() { -#ifdef _MSC_VER - // It is possible that the name of the dll will change. - // vcruntime140.dll is for 2015 and onwards - static constexpr char runtime_dll_name[] = "vcruntime140.dll"; - UINT sz = GetFileVersionInfoSizeA(runtime_dll_name, nullptr); - bool runtime_version_inspection_worked = false; - if (sz > 0) { - std::vector buf(sz); - if (GetFileVersionInfoA(runtime_dll_name, 0, sz, buf.data())) { - VS_FIXEDFILEINFO* pvi; - sz = sizeof(VS_FIXEDFILEINFO); - if (VerQueryValueA(buf.data(), "\\", reinterpret_cast(&pvi), &sz)) { - if (pvi->dwSignature == VS_FFI_SIGNATURE) { - runtime_version_inspection_worked = true; - LOG_INFO(Frontend, "MSVC Compiler: {} Runtime: {}.{}.{}.{}", _MSC_VER, - pvi->dwProductVersionMS >> 16, pvi->dwProductVersionMS & 0xFFFF, - pvi->dwProductVersionLS >> 16, pvi->dwProductVersionLS & 0xFFFF); - } - } - } - } - if (!runtime_version_inspection_worked) { - LOG_INFO(Frontend, "Unable to inspect {}", runtime_dll_name); - } -#endif - LOG_INFO(Frontend, "Qt Compile: {} Runtime: {}", QT_VERSION_STR, qVersion()); -} - -static QString PrettyProductName() { -#ifdef _WIN32 - // After Windows 10 Version 2004, Microsoft decided to switch to a different notation: 20H2 - // With that notation change they changed the registry key used to denote the current version - QSettings windows_registry( - QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), - QSettings::NativeFormat); - const QString release_id = windows_registry.value(QStringLiteral("ReleaseId")).toString(); - if (release_id == QStringLiteral("2009")) { - const u32 current_build = windows_registry.value(QStringLiteral("CurrentBuild")).toUInt(); - const QString display_version = - windows_registry.value(QStringLiteral("DisplayVersion")).toString(); - const u32 ubr = windows_registry.value(QStringLiteral("UBR")).toUInt(); - u32 version = 10; - if (current_build >= 22000) { - version = 11; - } - return QStringLiteral("Windows %1 Version %2 (Build %3.%4)") - .arg(QString::number(version), display_version, QString::number(current_build), - QString::number(ubr)); - } -#endif - return QSysInfo::prettyProductName(); -} - -#ifdef _WIN32 -static void OverrideWindowsFont() { - // Qt5 chooses these fonts on Windows and they have fairly ugly alphanumeric/cyrillic characters - // Asking to use "MS Shell Dlg 2" gives better other chars while leaving the Chinese Characters. - const QString startup_font = QApplication::font().family(); - const QStringList ugly_fonts = {QStringLiteral("SimSun"), QStringLiteral("PMingLiU")}; - if (ugly_fonts.contains(startup_font)) { - QApplication::setFont(QFont(QStringLiteral("MS Shell Dlg 2"), 9, QFont::Normal)); - } -} -#endif - #ifndef _WIN32 // TODO(crueter): carboxyl does this, is it needed in qml? inline static bool isDarkMode() { @@ -402,7 +323,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) input_subsystem{std::make_shared()}, user_data_migrator{this} { QtCommon::Init(this); - Common::FS::CreateEdenPaths(); this->config = std::make_unique(); if (user_data_migrator.migrated) { @@ -432,11 +352,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) UISettings::RestoreWindowState(config); - QtCommon::system->Initialize(); - - Common::Log::Initialize(); - Common::Log::Start(); - LoadTranslation(); setAcceptDrops(true); @@ -456,10 +371,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) play_time_manager = std::make_unique(); - Network::Init(); - - QtCommon::Meta::RegisterMetaTypes(); - InitializeWidgets(); InitializeDebugWidgets(); InitializeRecentFileMenuActions(); @@ -471,52 +382,8 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) ConnectMenuEvents(); ConnectWidgetEvents(); - QtCommon::system->HIDCore().ReloadInputDevices(); controller_dialog->refreshConfiguration(); - const auto branch_name = std::string(Common::g_scm_branch); - const auto description = std::string(Common::g_scm_desc); - const auto build_id = std::string(Common::g_build_id); - - const auto yuzu_build = fmt::format("Eden Development Build | {}-{}", branch_name, description); - const auto override_build = - fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id); - const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; - const auto processor_count = std::thread::hardware_concurrency(); - - LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version); - LogRuntimes(); -#ifdef ARCHITECTURE_x86_64 - const auto& caps = Common::GetCPUCaps(); - std::string cpu_string = caps.cpu_string; - if (caps.avx || caps.avx2 || caps.avx512f) { - cpu_string += " | AVX"; - if (caps.avx512f) { - cpu_string += "512"; - } else if (caps.avx2) { - cpu_string += '2'; - } - if (caps.fma || caps.fma4) { - cpu_string += " | FMA"; - } - } - LOG_INFO(Frontend, "Host CPU: {}", cpu_string); - if (std::optional processor_core = Common::GetProcessorCount()) { - LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core); - } -#endif - LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count); - LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString()); - LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", - Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); - LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB}); -#ifdef _WIN32 - LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", - std::chrono::duration_cast>( - Common::Windows::SetCurrentTimerResolutionToMaximum()) - .count()); - QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution()); -#endif UpdateWindowTitle(); show(); @@ -541,14 +408,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) } #endif - QtCommon::system->SetContentProvider(std::make_unique()); - QtCommon::system->RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual, - QtCommon::provider.get()); - QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs); - - // Remove cached contents generated during the previous session - RemoveCachedContents(); - // Gen keys if necessary OnCheckFirmwareDecryption(); @@ -2944,7 +2803,7 @@ void GMainWindow::OnMenuLoadFile() { is_load_file_select_active = true; const QString extensions = QStringLiteral("*.") - .append(GameList::supported_file_extensions.join(QStringLiteral(" *."))) + .append(QtCommon::supported_file_extensions.join(QStringLiteral(" *."))) .append(QStringLiteral(" main")); const QString file_filter = tr("Switch Executable (%1);;All Files (*.*)", "%1 is an identifier for the Switch executable file extensions.")