|
|
@ -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
|
|
|
@ -99,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
|
|
|
@ -109,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() |
|
|
|