Browse Source

[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 <crueter@eden-emu.dev>
pull/2884/head
crueter 3 months ago
parent
commit
5ef71661ff
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 183
      src/qt_common/qt_common.cpp
  2. 1
      src/qt_common/qt_common.h
  3. 4
      src/yuzu/game_list.cpp
  4. 2
      src/yuzu/game_list.h
  5. 5
      src/yuzu/game_list_worker.cpp
  6. 143
      src/yuzu/main.cpp

183
src/qt_common/qt_common.cpp

@ -1,22 +1,37 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // 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 "qt_common.h"
#include "common/fs/fs.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 <QGuiApplication> #include <QGuiApplication>
#include <QStringLiteral> #include <QStringLiteral>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/frontend/emu_window.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 <QFile> #include <QFile>
#include <QMessageBox> #include <QMessageBox>
#include <JlCompress.h> #include <JlCompress.h>
#include <thread>
#if !defined(WIN32) && !defined(__APPLE__) #if !defined(WIN32) && !defined(__APPLE__)
#include <qpa/qplatformnativeinterface.h> #include <qpa/qplatformnativeinterface.h>
@ -24,6 +39,8 @@
#include <objc/message.h> #include <objc/message.h>
#endif #endif
using namespace Common::Literals;
namespace QtCommon { namespace QtCommon {
#ifdef YUZU_QT_WIDGETS #ifdef YUZU_QT_WIDGETS
@ -36,8 +53,14 @@ std::unique_ptr<Core::System> system = nullptr;
std::shared_ptr<FileSys::RealVfsFilesystem> vfs = nullptr; std::shared_ptr<FileSys::RealVfsFilesystem> vfs = nullptr;
std::unique_ptr<FileSys::ManualContentProvider> provider = nullptr; std::unique_ptr<FileSys::ManualContentProvider> 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. // Determine WSI type based on Qt platform.
QString platform_name = QGuiApplication::platformName(); QString platform_name = QGuiApplication::platformName();
if (platform_name == QStringLiteral("windows")) if (platform_name == QStringLiteral("windows"))
@ -93,8 +116,88 @@ const QString tr(const std::string& str)
return QGuiApplication::tr(str.c_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<u8> buf(sz);
if (GetFileVersionInfoA(runtime_dll_name, 0, sz, buf.data())) {
VS_FIXEDFILEINFO* pvi;
sz = sizeof(VS_FIXEDFILEINFO);
if (VerQueryValueA(buf.data(), "\\", reinterpret_cast<LPVOID*>(&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 #ifdef YUZU_QT_WIDGETS
void Init(QWidget* root)
void Init(QWidget * root)
#else #else
void Init(QObject* root) void Init(QObject* root)
#endif #endif
@ -103,6 +206,74 @@ void Init(QObject* root)
rootObject = root; rootObject = root;
vfs = std::make_unique<FileSys::RealVfsFilesystem>(); vfs = std::make_unique<FileSys::RealVfsFilesystem>();
provider = std::make_unique<FileSys::ManualContentProvider>(); provider = std::make_unique<FileSys::ManualContentProvider>();
// 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<int> 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<std::chrono::duration<f64, std::milli>>(
Common::Windows::SetCurrentTimerResolutionToMaximum())
.count());
QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
#endif
// content providers
system->SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
system->RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual,
provider.get());
system->GetFileSystemController().CreateFactories(*vfs);
// Remove cached contents generated during the previous session
RemoveCachedContents();
} }
std::filesystem::path GetEdenCommand() std::filesystem::path GetEdenCommand()

1
src/qt_common/qt_common.h

@ -23,6 +23,7 @@ extern QObject *rootObject;
extern std::unique_ptr<Core::System> system; extern std::unique_ptr<Core::System> system;
extern std::shared_ptr<FileSys::RealVfsFilesystem> vfs; extern std::shared_ptr<FileSys::RealVfsFilesystem> vfs;
extern std::unique_ptr<FileSys::ManualContentProvider> provider; extern std::unique_ptr<FileSys::ManualContentProvider> provider;
extern const QStringList supported_file_extensions;
typedef std::function<bool(std::size_t, std::size_t)> QtProgressCallback; typedef std::function<bool(std::size_t, std::size_t)> QtProgressCallback;

4
src/yuzu/game_list.cpp

@ -878,10 +878,6 @@ void GameList::LoadInterfaceLayout() {
header->resizeSection(COLUMN_NAME, header->width()); 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() void GameList::RefreshGameDirectory()
{ {
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) { if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {

2
src/yuzu/game_list.h

@ -89,8 +89,6 @@ public:
/// Disables events from the emulated controller /// Disables events from the emulated controller
void UnloadController(); void UnloadController();
static const QStringList supported_file_extensions;
public slots: public slots:
void RefreshGameDirectory(); void RefreshGameDirectory();

5
src/yuzu/game_list_worker.cpp

@ -26,11 +26,12 @@
#include "core/file_sys/registered_cache.h" #include "core/file_sys/registered_cache.h"
#include "core/file_sys/submission_package.h" #include "core/file_sys/submission_package.h"
#include "core/loader/loader.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/compatibility_list.h"
#include "yuzu/game_list.h" #include "yuzu/game_list.h"
#include "yuzu/game_list_p.h" #include "yuzu/game_list_p.h"
#include "yuzu/game_list_worker.h" #include "yuzu/game_list_worker.h"
#include "qt_common/config/uisettings.h"
namespace { namespace {
@ -144,7 +145,7 @@ void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const
bool HasSupportedFileExtension(const std::string& file_name) { bool HasSupportedFileExtension(const std::string& file_name) {
const QFileInfo file = QFileInfo(QString::fromStdString(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) { bool IsExtractedNCAMain(const std::string& file_name) {

143
src/yuzu/main.cpp

@ -303,85 +303,6 @@ enum class CalloutFlag : uint32_t {
const int GMainWindow::max_recent_files_item; 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<u8> buf(sz);
if (GetFileVersionInfoA(runtime_dll_name, 0, sz, buf.data())) {
VS_FIXEDFILEINFO* pvi;
sz = sizeof(VS_FIXEDFILEINFO);
if (VerQueryValueA(buf.data(), "\\", reinterpret_cast<LPVOID*>(&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 #ifndef _WIN32
// TODO(crueter): carboxyl does this, is it needed in qml? // TODO(crueter): carboxyl does this, is it needed in qml?
inline static bool isDarkMode() { inline static bool isDarkMode() {
@ -402,7 +323,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, user_data_migrator{this} { input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, user_data_migrator{this} {
QtCommon::Init(this); QtCommon::Init(this);
Common::FS::CreateEdenPaths();
this->config = std::make_unique<QtConfig>(); this->config = std::make_unique<QtConfig>();
if (user_data_migrator.migrated) { if (user_data_migrator.migrated) {
@ -432,11 +352,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
UISettings::RestoreWindowState(config); UISettings::RestoreWindowState(config);
QtCommon::system->Initialize();
Common::Log::Initialize();
Common::Log::Start();
LoadTranslation(); LoadTranslation();
setAcceptDrops(true); setAcceptDrops(true);
@ -456,10 +371,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
play_time_manager = std::make_unique<PlayTime::PlayTimeManager>(); play_time_manager = std::make_unique<PlayTime::PlayTimeManager>();
Network::Init();
QtCommon::Meta::RegisterMetaTypes();
InitializeWidgets(); InitializeWidgets();
InitializeDebugWidgets(); InitializeDebugWidgets();
InitializeRecentFileMenuActions(); InitializeRecentFileMenuActions();
@ -471,52 +382,8 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
ConnectMenuEvents(); ConnectMenuEvents();
ConnectWidgetEvents(); ConnectWidgetEvents();
QtCommon::system->HIDCore().ReloadInputDevices();
controller_dialog->refreshConfiguration(); 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<int> 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<std::chrono::duration<f64, std::milli>>(
Common::Windows::SetCurrentTimerResolutionToMaximum())
.count());
QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
#endif
UpdateWindowTitle(); UpdateWindowTitle();
show(); show();
@ -541,14 +408,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
} }
#endif #endif
QtCommon::system->SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
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 // Gen keys if necessary
OnCheckFirmwareDecryption(); OnCheckFirmwareDecryption();
@ -2944,7 +2803,7 @@ void GMainWindow::OnMenuLoadFile() {
is_load_file_select_active = true; is_load_file_select_active = true;
const QString extensions = const QString extensions =
QStringLiteral("*.") QStringLiteral("*.")
.append(GameList::supported_file_extensions.join(QStringLiteral(" *.")))
.append(QtCommon::supported_file_extensions.join(QStringLiteral(" *.")))
.append(QStringLiteral(" main")); .append(QStringLiteral(" main"));
const QString file_filter = tr("Switch Executable (%1);;All Files (*.*)", const QString file_filter = tr("Switch Executable (%1);;All Files (*.*)",
"%1 is an identifier for the Switch executable file extensions.") "%1 is an identifier for the Switch executable file extensions.")

Loading…
Cancel
Save