From c6300dfc9b8f80880ea07a9726fc3ab512169a10 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Wed, 20 Dec 2023 20:19:48 -0500 Subject: [PATCH] Download and install DXVK --- launcher/include/assetupdater.h | 5 +++ launcher/src/assetupdater.cpp | 75 ++++++++++++++++++++++++++++++++- launcher/src/gamerunner.cpp | 19 +++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) diff --git a/launcher/include/assetupdater.h b/launcher/include/assetupdater.h index 3c77a9f..cb67377 100644 --- a/launcher/include/assetupdater.h +++ b/launcher/include/assetupdater.h @@ -26,11 +26,13 @@ public: private: QCoro::Task checkRemoteCompatibilityToolVersion(); + QCoro::Task checkRemoteDxvkVersion(); QCoro::Task checkRemoteDalamudAssetVersion(); QCoro::Task checkRemoteDalamudVersion(); QCoro::Task installCompatibilityTool(); + QCoro::Task installDxvkTool(); QCoro::Task installDalamudAssets(); QCoro::Task installDalamud(); QCoro::Task installRuntime(); @@ -49,6 +51,7 @@ private: QTemporaryDir m_tempDir; QDir m_wineDir; + QDir m_dxvkDir; QDir m_dataDir; QDir m_appDataDir; QDir m_dalamudDir; @@ -59,9 +62,11 @@ private: QJsonArray m_remoteDalamudAssetArray; QString m_remoteDalamudDownloadUrl; QString m_remoteCompatibilityToolVersion; + QString m_remoteDxvkToolVersion; // TODO: hardcoded QString m_remoteCompatibilityToolUrl = QStringLiteral("https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-ubuntu-8.5.r4.g4211bac7.tar.xz"); + QString m_remoteDxvkToolUrl = QStringLiteral("https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz"); Profile &m_profile; }; diff --git a/launcher/src/assetupdater.cpp b/launcher/src/assetupdater.cpp index 8ebffcc..2572a49 100644 --- a/launcher/src/assetupdater.cpp +++ b/launcher/src/assetupdater.cpp @@ -33,13 +33,19 @@ QCoro::Task AssetUpdater::update() m_dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); const QDir compatibilityToolDir = m_dataDir.absoluteFilePath(QStringLiteral("tools")); m_wineDir = compatibilityToolDir.absoluteFilePath(QStringLiteral("wine")); + m_dxvkDir = compatibilityToolDir.absoluteFilePath(QStringLiteral("dxvk")); Utility::createPathIfNeeded(m_wineDir); + Utility::createPathIfNeeded(m_dxvkDir); if (!co_await checkRemoteCompatibilityToolVersion()) { co_return false; } + if (!co_await checkRemoteDxvkVersion()) { + co_return false; + } + if (!m_profile.dalamudEnabled()) { co_return true; } @@ -83,6 +89,33 @@ QCoro::Task AssetUpdater::checkRemoteCompatibilityToolVersion() co_return true; } +QCoro::Task AssetUpdater::checkRemoteDxvkVersion() +{ + // TODO: hardcoded for now + m_remoteDxvkToolVersion = QStringLiteral("dxvk-2.3"); + + qInfo(ASTRA_LOG) << "DXVK remote version" << m_remoteDxvkToolVersion; + + QString localDxvkVersion; + const QString dxvkVer = m_dxvkDir.absoluteFilePath(QStringLiteral("dxvk.ver")); + if (QFile::exists(dxvkVer)) { + QFile wineJson(dxvkVer); + wineJson.open(QFile::ReadOnly | QFile::Text); + + localDxvkVersion = QString::fromUtf8(wineJson.readAll()); + qInfo(ASTRA_LOG) << "Local DXVK version:" << localDxvkVersion; + } + + // TODO: this version should not be profile specific + if (m_remoteDxvkToolVersion != localDxvkVersion) { + qInfo(ASTRA_LOG) << "DXVK tool out of date"; + + co_return co_await installDxvkTool(); + } + + co_return true; +} + QCoro::Task AssetUpdater::checkRemoteDalamudAssetVersion() { // first we want to fetch the list of assets required @@ -171,12 +204,12 @@ QCoro::Task AssetUpdater::installCompatibilityTool() qInfo(ASTRA_LOG) << "Finished downloading compatibility tool"; - QFile file(m_tempDir.filePath(QStringLiteral("latest.tar.xz"))); + QFile file(m_tempDir.filePath(QStringLiteral("wine.tar.xz"))); file.open(QIODevice::WriteOnly); file.write(reply->readAll()); file.close(); - KTar archive(m_tempDir.filePath(QStringLiteral("latest.tar.xz"))); + KTar archive(m_tempDir.filePath(QStringLiteral("wine.tar.xz"))); if (!archive.open(QIODevice::ReadOnly)) { qCritical(ASTRA_LOG) << "Failed to install compatibility tool"; Q_EMIT launcher.dalamudError(i18n("Failed to install compatibility tool.")); @@ -199,6 +232,44 @@ QCoro::Task AssetUpdater::installCompatibilityTool() co_return true; } +QCoro::Task AssetUpdater::installDxvkTool() +{ + Q_EMIT launcher.stageChanged(i18n("Updating DXVK...")); + + const QNetworkRequest request = QNetworkRequest(QUrl(m_remoteDxvkToolUrl)); + Utility::printRequest(QStringLiteral("GET"), request); + + const auto reply = launcher.mgr()->get(request); + co_await reply; + + qInfo(ASTRA_LOG) << "Finished downloading DXVK"; + + QFile file(m_tempDir.filePath(QStringLiteral("dxvk.tar.xz"))); + file.open(QIODevice::WriteOnly); + file.write(reply->readAll()); + file.close(); + + KTar archive(m_tempDir.filePath(QStringLiteral("dxvk.tar.xz"))); + if (!archive.open(QIODevice::ReadOnly)) { + qCritical(ASTRA_LOG) << "Failed to install DXVK"; + Q_EMIT launcher.dalamudError(i18n("Failed to install DXVK.")); + co_return false; + } + + // the first directory is the same as the version we download + const KArchiveDirectory *root = dynamic_cast(archive.directory()->entry(m_remoteDxvkToolVersion)); + root->copyTo(m_dxvkDir.absolutePath(), true); + + archive.close(); + + QFile verFile(m_dxvkDir.absoluteFilePath(QStringLiteral("dxvk.ver"))); + verFile.open(QIODevice::WriteOnly | QIODevice::Text); + verFile.write(m_remoteDxvkToolVersion.toUtf8()); + verFile.close(); + + co_return true; +} + QCoro::Task AssetUpdater::installDalamudAssets() { Q_EMIT launcher.stageChanged(i18n("Updating Dalamud assets...")); diff --git a/launcher/src/gamerunner.cpp b/launcher/src/gamerunner.cpp index 35d0051..927a0a8 100644 --- a/launcher/src/gamerunner.cpp +++ b/launcher/src/gamerunner.cpp @@ -173,6 +173,21 @@ void GameRunner::launchExecutable(const Profile &profile, QProcess *process, con // FFXIV detects this as a "macOS" build by checking if Wine shows up const int value = profile.account()->license() == Account::GameLicense::macOS ? 0 : 1; addRegistryKey(profile, QStringLiteral("HKEY_CURRENT_USER\\Software\\Wine"), QStringLiteral("HideWineExports"), QString::number(value)); + + // copy DXVK + const QDir dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + const QDir compatibilityToolDir = dataDir.absoluteFilePath(QStringLiteral("tools")); + const QDir dxvkDir = compatibilityToolDir.absoluteFilePath(QStringLiteral("dxvk")); + const QDir dxvk64Dir = dxvkDir.absoluteFilePath(QStringLiteral("x64")); + + const QDir winePrefix = profile.winePrefixPath(); + const QDir driveC = winePrefix.absoluteFilePath(QStringLiteral("drive_c")); + const QDir windows = driveC.absoluteFilePath(QStringLiteral("windows")); + const QDir system32 = windows.absoluteFilePath(QStringLiteral("system32")); + + for (const auto &entry : dxvk64Dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { + QFile::copy(entry.absoluteFilePath(), system32.absoluteFilePath(entry.fileName())); + } #endif } @@ -217,6 +232,10 @@ void GameRunner::launchExecutable(const Profile &profile, QProcess *process, con #if defined(Q_OS_MAC) || defined(Q_OS_LINUX) env.insert(QStringLiteral("WINEPREFIX"), profile.winePrefixPath()); + if (profile.wineType() == Profile::WineType::BuiltIn) { + env.insert(QStringLiteral("WINEDLLOVERRIDES"), QStringLiteral("d3d9,d3d11,d3d10core,dxgi=n")); + } + arguments.push_back(profile.winePath()); #endif