From 1bae49d60932590dbc129a037eebe59580be9542 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Mon, 27 Nov 2023 17:27:32 -0500 Subject: [PATCH 01/37] Properly handle title disam. diag cancellation --- app/src/command/c-play.cpp | 3 +++ app/src/kernel/driver.cpp | 2 ++ app/src/kernel/driver.h | 1 + 3 files changed, 6 insertions(+) diff --git a/app/src/command/c-play.cpp b/app/src/command/c-play.cpp index 5331cc2..96c1ecc 100644 --- a/app/src/command/c-play.cpp +++ b/app/src/command/c-play.cpp @@ -314,6 +314,9 @@ Qx::Error CPlay::perform() else if(Qx::Error ide = getTitleId(titleId); ide.isValid()) return ide; + // Bail if ID is missing (user cancel) + if(titleId.isNull()) + return CPlayError(); logEvent(LOG_EVENT_HANDLING_AUTO); diff --git a/app/src/kernel/driver.cpp b/app/src/kernel/driver.cpp index cc7fb75..b2e2832 100644 --- a/app/src/kernel/driver.cpp +++ b/app/src/kernel/driver.cpp @@ -163,6 +163,8 @@ void Driver::cleanup() void Driver::finish() { + logEvent(LOG_EVENT_FINISH); + // Clear update cache if(CUpdate::isUpdateCacheClearable()) { diff --git a/app/src/kernel/driver.h b/app/src/kernel/driver.h index 1451ed7..50a795d 100644 --- a/app/src/kernel/driver.h +++ b/app/src/kernel/driver.h @@ -82,6 +82,7 @@ class Driver : public QObject static inline const QString LOG_EVENT_QUIT_REQUEST_REDUNDANT = u"Received redundant quit request"_s; static inline const QString LOG_EVENT_CLEARED_UPDATE_CACHE = u"Cleared stale update cache."_s; static inline const QString LOG_EVENT_CORE_ABORT = u"Core abort signaled, quitting now."_s; + static inline const QString LOG_EVENT_FINISH = u"Finishing run..."_s; // Meta static inline const QString NAME = u"driver"_s; From 84717627016aa0956a2f147499308937b781e112 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 28 Jun 2024 03:08:14 -0400 Subject: [PATCH 02/37] Fix datapack download --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 070179c..578d2f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ ob_fetch_qx( # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("v0.5.2") +ob_fetch_libfp("7224fd564e1ce4871da3d9299bc2ebf53b961ef8") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP) From 73f743a3e12b03caef9cb2409996375b05996cfb Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 28 Jun 2024 03:12:05 -0400 Subject: [PATCH 03/37] Actions: Remove gcc 13 workaround; fixed by GitHub --- .github/workflows/build-clifp-linux.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index a111b8d..e1fe072 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -68,13 +68,6 @@ jobs: credentials: ${{ secrets.qt_ffynnon_cred }} - name: Update package index run: sudo apt-get update - - name: WORKAROUND FOR https://github.com/actions/runner-images/issues/8659 - if: matrix.os == 'ubuntu-22.04' - run: | - echo "TEMPORARY WORKAROUND FOR GITHUB RUNNER BUG #8659\n\nRemoving GCC 13 as it breaks Clang14" - sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list - sudo apt-get update - sudo apt-get install -y --allow-downgrades libc6=2.35-0ubuntu3.4 libc6-dev=2.35-0ubuntu3.4 libstdc++6=12.3.0-1ubuntu1~22.04 libgcc-s1=12.3.0-1ubuntu1~22.04 - name: Install OpenGL lib run: sudo apt-get install libglu1-mesa-dev - name: Install XCB Related libs From 45f21455dae2797f60add7f2151349c6c584391d Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 29 Jun 2024 21:45:38 -0400 Subject: [PATCH 04/37] Account for datapack downloads being unavailable on Ultimate --- CMakeLists.txt | 2 +- app/src/command/c-download.cpp | 9 +++++++-- app/src/kernel/core.cpp | 11 +++++++---- app/src/kernel/core.h | 2 +- app/src/task/t-download.cpp | 17 +++++++++++++++++ app/src/task/t-download.h | 16 +++++++++++++--- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 578d2f8..c2c9dce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ ob_fetch_qx( # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("7224fd564e1ce4871da3d9299bc2ebf53b961ef8") +ob_fetch_libfp("7fb8242593457033ca25008ec5d79d3f5a4ca0b7") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP) diff --git a/app/src/command/c-download.cpp b/app/src/command/c-download.cpp index fb8ad67..472ada8 100644 --- a/app/src/command/c-download.cpp +++ b/app/src/command/c-download.cpp @@ -92,8 +92,13 @@ Qx::Error CDownload::perform() if(tk->datapackIsPresent(gameData)) continue; - // Queue download - downloadTask->addFile({.target = tk->datapackUrl(gameData), .dest = tk->datapackPath(gameData), .checksum = gameData.sha256()}); + // Queue download, if possible + TDownloadError packError = downloadTask->addDatapack(tk, &gameData); + if(packError.isValid()) + { + postError(packError); + return packError; + } // Note data id dataIds.append(gameData.id()); diff --git a/app/src/kernel/core.cpp b/app/src/kernel/core.cpp index bf0b114..fb1b032 100644 --- a/app/src/kernel/core.cpp +++ b/app/src/kernel/core.cpp @@ -733,20 +733,23 @@ Qx::Error Core::enqueueDataPackTasks(const Fp::GameData& gameData) const Fp::Toolkit* tk = mFlashpointInstall->toolkit(); - QString packFilename = gameData.path(); QString packPath = tk->datapackPath(gameData); + QString packFilename = tk->datapackFilename(gameData); // Enqueue pack download if it's not available if(!tk->datapackIsPresent(gameData)) { logEvent(LOG_EVENT_DATA_PACK_MISS); - QUrl packUrl = tk->datapackUrl(gameData); - TDownload* downloadTask = new TDownload(this); downloadTask->setStage(Task::Stage::Auxiliary); downloadTask->setDescription(u"data pack "_s + packFilename); - downloadTask->addFile({.target = packUrl, .dest = packPath, .checksum = gameData.sha256()}); + TDownloadError packError = downloadTask->addDatapack(tk, &gameData); + if(packError.isValid()) + { + postError(packError); + return packError; + } mTaskQueue.push(downloadTask); logTask(downloadTask); diff --git a/app/src/kernel/core.h b/app/src/kernel/core.h index 8c1a6cd..2676c8c 100644 --- a/app/src/kernel/core.h +++ b/app/src/kernel/core.h @@ -58,7 +58,7 @@ class QX_ERROR_TYPE(CoreError, "CoreError", 1200) {TitleNotFound, u"Could not find the title in the Flashpoint database."_s}, {TooManyResults, u"More results than can be presented were returned in a search."_s}, {ConfiguredServerMissing, u"The configured server was not found within the Flashpoint services store."_s}, - {UnknownDatapackParam, u"Unrecognized datapack parameters were present. The game likely won't work correctly."_s}, + {UnknownDatapackParam, u"Unrecognized datapack parameters were present. The game likely won't work correctly."_s} }; //-Instance Variables------------------------------------------------------------- diff --git a/app/src/task/t-download.cpp b/app/src/task/t-download.cpp index 439fd09..ee3c598 100644 --- a/app/src/task/t-download.cpp +++ b/app/src/task/t-download.cpp @@ -1,6 +1,9 @@ // Unit Include #include "t-download.h" +// Flashpoint Includes +#include + //=============================================================================================================== // TDownloadError //=============================================================================================================== @@ -90,6 +93,20 @@ QList TDownload::files() const { return mFiles; } QString TDownload::description() const { return mDescription; } void TDownload::addFile(const Qx::DownloadTask file) { mFiles.append(file); } + +TDownloadError TDownload::addDatapack(const Fp::Toolkit* tk, const Fp::GameData* gameData) +{ + // TODO: CDownload runs this in a loop, which is why Q_UNLIKELY is used, but in the long run a different approach in which download + // ability is checked for once ahead of time is probably best + if(Q_UNLIKELY(!tk->canDownloadDatapacks())) + return TDownloadError(TDownloadError::OfflineEdition, tk->datapackFilename(*gameData)); + + // TODO: This makes it apparent that a class like "CompleteGameData" might be warranted, with a constructor that takes GameData and + // Toolkit and then produces a representation of the GameData with a complete path/url, though the URL would be null for Ultimate + addFile({.target = tk->datapackUrl(*gameData), .dest = tk->datapackPath(*gameData), .checksum = gameData->sha256()}); + return TDownloadError(); +} + void TDownload::setDescription(const QString& desc) { mDescription = desc; } void TDownload::perform() diff --git a/app/src/task/t-download.h b/app/src/task/t-download.h index 11e8055..d5cff61 100644 --- a/app/src/task/t-download.h +++ b/app/src/task/t-download.h @@ -8,6 +8,13 @@ // Project Includes #include "task/task.h" +// FP Forward Declarations +namespace Fp +{ + class Toolkit; + class GameData; +} + class QX_ERROR_TYPE(TDownloadError, "TDownloadError", 1252) { friend class TDownload; @@ -15,15 +22,17 @@ class QX_ERROR_TYPE(TDownloadError, "TDownloadError", 1252) public: enum Type { - NoError = 0, - Incomeplete = 2 + NoError, + Incomeplete, + OfflineEdition }; //-Class Variables------------------------------------------------------------- private: static inline const QHash ERR_STRINGS{ {NoError, u""_s}, - {Incomeplete, u"The download(s) could not be completed."_s} + {Incomeplete, u"The download(s) could not be completed."_s}, + {OfflineEdition, u"A datapack download was prompted in an offline edition of Flashpoint."_s} }; //-Instance Variables------------------------------------------------------------- @@ -91,6 +100,7 @@ class TDownload : public Task QString description() const; void addFile(const Qx::DownloadTask file); + TDownloadError addDatapack(const Fp::Toolkit* tk, const Fp::GameData* gameData); void setDescription(const QString& desc); void perform() override; From bfe43c4bac930e2bc2eb74e581deb06cd81c5f0c Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 30 Jun 2024 00:41:48 -0400 Subject: [PATCH 05/37] Fix parsing of Ultimate version.txt The bloody format of version.txt never stays the same, hopefully the current regex works for future updates as well. --- CMakeLists.txt | 2 +- app/src/kernel/core.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c2c9dce..1bdef49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ ob_fetch_qx( # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("7fb8242593457033ca25008ec5d79d3f5a4ca0b7") +ob_fetch_libfp("5ff81d39c13e40f7fbfe01e44dc2170648d35dc8") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP) diff --git a/app/src/kernel/core.cpp b/app/src/kernel/core.cpp index fb1b032..41ee595 100644 --- a/app/src/kernel/core.cpp +++ b/app/src/kernel/core.cpp @@ -436,9 +436,10 @@ void Core::attachFlashpoint(std::unique_ptr flashpointInstall) mFlashpointInstall = std::move(flashpointInstall); // Note install details - logEvent(LOG_EVENT_FLASHPOINT_VERSION_TXT.arg(mFlashpointInstall->nameVersionString())); - logEvent(LOG_EVENT_FLASHPOINT_VERSION.arg(mFlashpointInstall->version().toString())); - logEvent(LOG_EVENT_FLASHPOINT_EDITION.arg(ENUM_NAME(mFlashpointInstall->edition()))); + auto info = mFlashpointInstall->versionInfo(); + logEvent(LOG_EVENT_FLASHPOINT_VERSION_TXT.arg(info->fullString())); + logEvent(LOG_EVENT_FLASHPOINT_VERSION.arg(info->version().toString())); + logEvent(LOG_EVENT_FLASHPOINT_EDITION.arg(ENUM_NAME(info->edition()))); logEvent(LOG_EVENT_OUTFITTED_DAEMON.arg(ENUM_NAME(mFlashpointInstall->outfittedDaemon()))); // Initialize child process env vars From f060eacf159bdabac97a4b9bb63f572c7b0a966c Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 30 Jun 2024 01:58:03 -0400 Subject: [PATCH 06/37] (Mostly) implement Game Redirects Taking a shortcut here, see libfp commit for details. --- CMakeLists.txt | 2 +- app/src/command/c-download.cpp | 4 ++++ app/src/command/title-command.cpp | 4 ++++ app/src/command/title-command.h | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bdef49..2876aad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ ob_fetch_qx( # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("5ff81d39c13e40f7fbfe01e44dc2170648d35dc8") +ob_fetch_libfp("e65151253813b8da7d7f9b8849810f58dd5e9a50") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP) diff --git a/app/src/command/c-download.cpp b/app/src/command/c-download.cpp index 472ada8..d921e68 100644 --- a/app/src/command/c-download.cpp +++ b/app/src/command/c-download.cpp @@ -75,6 +75,10 @@ Qx::Error CDownload::perform() const Fp::Toolkit* tk = mCore.fpInstall().toolkit(); for(const auto& pg : pItr->playlistGames()) { + /* TODO: This doesn't handle Game Redirects, i.e. if one ID on a playlist becomes a redirect entry in the future. + * Either need to add redirects here, or implement them in the DB module of libfp (full implementation). + */ + // Get data Fp::GameData gameData; if(Fp::DbError gdErr = db->getGameData(gameData, pg.gameId()); gdErr.isValid()) diff --git a/app/src/command/title-command.cpp b/app/src/command/title-command.cpp index c0ba6d2..86c9e0e 100644 --- a/app/src/command/title-command.cpp +++ b/app/src/command/title-command.cpp @@ -210,6 +210,10 @@ Qx::Error TitleCommand::getTitleId(QUuid& id) postError(err); return err; } + QUuid origId = titleId; + titleId = mCore.fpInstall().database()->handleGameRedirects(titleId); // Redirect shortcut + if(titleId != origId) + logEvent(LOG_EVENT_GAME_REDIRECT.arg(origId.toString(QUuid::WithoutBraces), titleId.toString(QUuid::WithoutBraces))); } else if(mParser.isSet(CL_OPTION_TITLE) || mParser.isSet(CL_OPTION_TITLE_STRICT)) { diff --git a/app/src/command/title-command.h b/app/src/command/title-command.h index 9f6cc18..eb0a1f9 100644 --- a/app/src/command/title-command.h +++ b/app/src/command/title-command.h @@ -59,6 +59,7 @@ class TitleCommand : public Command static inline const QString LOG_EVENT_SEL_RAND = u"Selecting a playable title at random..."_s; static inline const QString LOG_EVENT_INIT_RAND_ID = u"Randomly chose primary title is \"%1\""_s; static inline const QString LOG_EVENT_INIT_RAND_PLAY_ADD_COUNT = u"Chosen title has %1 playable additional-apps"_s; + static inline const QString LOG_EVENT_GAME_REDIRECT = u"Game redirected: %1 -> %2"_s; static inline const QString LOG_EVENT_RAND_DET_PRIM = u"Selected primary title"_s; static inline const QString LOG_EVENT_RAND_DET_ADD_APP = u"Selected additional-app \"%1\""_s; static inline const QString LOG_EVENT_RAND_GET_INFO = u"Querying random game info..."_s; From f90ac521f68b6c744396535bffc027dc005b5fc4 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 30 Jun 2024 02:58:32 -0400 Subject: [PATCH 07/37] Update libfp --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2876aad..23cc224 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ ob_fetch_qx( # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("e65151253813b8da7d7f9b8849810f58dd5e9a50") +ob_fetch_libfp("89430b79c7b06f67c1219008a07a1b1daf6d443f") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP) From d2de3db0bccb60f6a80639c34f15158cbd9638da Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 4 Jul 2024 20:33:02 -0400 Subject: [PATCH 08/37] More closely mimick launcher when setting mount request to FPGS Not required, but hopefully more future-proof. --- app/src/tools/mounter_proxy.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/tools/mounter_proxy.cpp b/app/src/tools/mounter_proxy.cpp index 1227acb..9d05480 100644 --- a/app/src/tools/mounter_proxy.cpp +++ b/app/src/tools/mounter_proxy.cpp @@ -144,12 +144,15 @@ void MounterProxy::mount() QNetworkRequest mountReq(mountUrl); // Header - mountReq.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - // These headers are used by the stock launcher, but don't seem to be needed - // - // mountReq.setRawHeader("Connection"_ba, "close"_ba); - // mountReq.setRawHeader("Accept"_ba, "application/json, text/plain, */*"_ba); - // mountReq.setRawHeader("Accept-Encoding"_ba, "gzip, compress, deflate, br"_ba); + mountReq.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"_ba); + /* These following headers are used by the stock launcher, but don't seem to be needed; + * however, we include them anyway out of posterity in hopes of avoiding future issues + * in case FPGS starts caring + */ + mountReq.setHeader(QNetworkRequest::UserAgentHeader, "axios/1.6.8"_ba); + mountReq.setRawHeader("Connection"_ba, "close"_ba); + mountReq.setRawHeader("Accept"_ba, "application/json, text/plain, */*"_ba); + mountReq.setRawHeader("Accept-Encoding"_ba, "gzip, compress, deflate, br"_ba); // Data QJsonDocument jdData(QJsonObject{{u"filePath"_s, mFilePath}}); From 89203863c8f7cb46730102e26a8f1ad2b4e3cac6 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 4 Jul 2024 20:33:39 -0400 Subject: [PATCH 09/37] Remove leftovers from failed downloads --- app/src/task/t-download.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/task/t-download.cpp b/app/src/task/t-download.cpp index ee3c598..8258913 100644 --- a/app/src/task/t-download.cpp +++ b/app/src/task/t-download.cpp @@ -38,6 +38,7 @@ TDownload::TDownload(QObject* parent) : { // Setup download manager mDownloadManager.setOverwrite(true); + mDownloadManager.setDeletePartialDownloads(true); mDownloadManager.setVerificationMethod(QCryptographicHash::Sha256); // Download event handlers From da8bb78151acff3f9d146578cc394456b5814534 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 4 Jul 2024 20:36:43 -0400 Subject: [PATCH 10/37] Update Qx and libfp, fix FPGS parameters - Fixes updated Qx downloader dependency - Fixes pathing oversight with FPGS requring "../" as the value for the macro within it's arguments --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23cc224..069b6d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,14 +72,14 @@ endif() include(OB/FetchQx) ob_fetch_qx( - REF "v0.5.6" + REF "037a16dd85bb4de9419c7f095a520e898ccacebc" COMPONENTS ${CLIFP_QX_COMPONENTS} ) # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("89430b79c7b06f67c1219008a07a1b1daf6d443f") +ob_fetch_libfp("c14360d4306e6f74bce06f98414a3a51f0cf9cd8") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP) From 20f35b12cfd88d586094a1118bcd151bf11b6a80 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 5 Jul 2024 14:56:59 -0400 Subject: [PATCH 11/37] Match new ./start-flashpoint.sh extra steps --- app/src/kernel/core.cpp | 97 ++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/app/src/kernel/core.cpp b/app/src/kernel/core.cpp index 41ee595..b86ce86 100644 --- a/app/src/kernel/core.cpp +++ b/app/src/kernel/core.cpp @@ -444,30 +444,44 @@ void Core::attachFlashpoint(std::unique_ptr flashpointInstall) // Initialize child process env vars QProcessEnvironment de = QProcessEnvironment::systemEnvironment(); - QString fpPath = mFlashpointInstall->dir().absolutePath(); + const QString fpPath = mFlashpointInstall->dir().absolutePath(); #ifdef __linux__ + //-Mimic startup script setup------------------------- + QString winFpPath = u"Z:"_s + QString(fpPath).replace('/', '\\'); + bool immutable = mFlashpointInstall->dir().exists(u"Libraries"_s); // NOTE: This check likely will need to be modified over time + // Add platform support environment variables - if(mFlashpointInstall->outfittedDaemon() == Fp::Daemon::Qemu) // Appimage based build + de.insert(u"DIR"_s, fpPath); + de.insert(u"FP_STARTUP_PATH"_s, winFpPath + u"\\FPSoftware"_s); + de.insert(u"FP_BROWSER_PLUGINS"_s, winFpPath + u"\\FPSoftware\\BrowserPlugins"_s); + de.insert(u"WINEPREFIX"_s, fpPath + u"/FPSoftware/Wine"_s); + + if(immutable) { + de.insert(u"LD_LIBRARY_PATH"_s, fpPath + u"/Libraries/lib"_s); QString pathValue = de.value(u"PATH"_s); - pathValue.prepend(fpPath + u"/FPSoftware/FPWine/bin:"_s + fpPath + u"/FPSoftware/FPQemuPHP:"_s); + pathValue.prepend(fpPath + u"/Libraries/bin:"_s); de.insert(u"PATH"_s, pathValue); qputenv("PATH", pathValue.toLocal8Bit()); // Path needs to be updated for self as well - de.insert(u"GTK_USE_PORTAL"_s, "1"); - de.remove(u"LD_PRELOAD"_s); - } - else // Regular Linux build - { - QString winFpPath = u"Z:"_s + fpPath; - - de.insert(u"DIR"_s, fpPath); - de.insert(u"WINDOWS_DIR"_s, winFpPath); - de.insert(u"FP_STARTUP_PATH"_s, winFpPath + u"\\FPSoftware"_s); - de.insert(u"FP_BROWSER_PLUGINS"_s, winFpPath + u"\\FPSoftware\\BrowserPlugins"_s); - de.insert(u"WINEPREFIX"_s, fpPath + u"/FPSoftware/Wine"_s); + /* This step likely isn't necesary, as it seems to be done only for the launcher, which of course + * we replace (and we use Qt so GTK doesn't really come into play); however, since this variable + * is exported it does affect child processes so we include this anyway just in case. + */ + int gtkRes = QProcess::execute(u"sh"_s, {u"-c"_s, u"ldconfig -p | grep libgtk-3.so >/dev/null 2>&1"_s}); + if(gtkRes != 0) + de.insert(u"GTK_USE_PORTAL"_s, "1"); } + else + de.insert(u"LD_LIBRARY_PATH"_s, fpPath + u"/Legacy"_s); + + /* Ensure ruffle has execute permissions (may not be present). The launcher delays this action until 15 + * seconds after start since it may update Ruffle, but we don't touch it so we don't have to wait + */ + QFile ruffle(fpPath + u"/Data/Ruffle/standalone/latest/ruffle"_s); // TODO: Might want to add this under Fp::Install + if(!ruffle.setPermissions(QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther)) + qWarning("Failed to mark ruffle as executable!"); #endif TExec::setDefaultProcessEnvironment(de); @@ -560,6 +574,43 @@ CoreError Core::enqueueStartupTasks(const QString& serverOverride) mTaskQueue.push(xhostSet); logTask(xhostSet); } + + // Setup WINE prefix if not present + QDir winePrefix(mFlashpointInstall->dir().absolutePath() + u"/FPSoftware/Wine"_s); + if(!winePrefix.exists()) + { + // Copy backup prefix + QDir winePrefixBak(mFlashpointInstall->dir().absolutePath() + u"/FPSoftware/.winebak"_s); + if(Qx::copyDirectory(winePrefixBak, winePrefix, true, false).isFailure()) + qWarning("Failed to restore WINE prefix backup"); + + // Setup WINE registry modification + auto wineEnv = TExec::defaultProcessEnvironment(); + wineEnv.insert(u"WINEDLLOVERRIDES"_s, u"control.exe,explorer.exe,mscoree,plugplay.exe,services.exe,winedevice.exe,winemenubuilder.exe=d"_s); + + TExec* wineReg = new TExec(this); + wineReg->setIdentifier(u"WINE Registry Setup"_s); + wineReg->setStage(Task::Stage::Startup); + wineReg->setExecutable(u"wine"_s); + wineReg->setDirectory(mFlashpointInstall->dir()); + wineReg->setParameters(QStringList{ + u"reg"_s, + u"add"_s, + u"HKLM\\Software\\Wine\\MSHTML\\2.47.4"_s, + u"/v"_s, + u"GeckoPath"_s, + u"/d"_s, + u"C:\\windows\\syswow64\\gecko\\2.47.4\\wine_gecko\\"_s, + u"/reg:32"_s, + u"/f"_s + }); + wineReg->setEnvironment(wineEnv); + wineReg->setProcessType(TExec::ProcessType::Blocking); + + mTaskQueue.push(wineReg); + logTask(wineReg); + } + #endif // Get settings @@ -694,6 +745,22 @@ void Core::enqueueShutdownTasks() mTaskQueue.push(xhostClear); logTask(xhostClear); } + + // Backup WINE flash saves + QString uname = qgetenv("USER"); + QDir saveSrc(mFlashpointInstall->dir().absoluteFilePath(u"FPSoftware/Wine/drive_c/users/"_s + uname + u"/AppData/Roaming/Macromedia/Flash Player/#SharedObjects"_s)); + QDir saveDest(mFlashpointInstall->dir().absoluteFilePath(u"FPSoftware/.winebak/drive_c/users/"_s + uname + u"/AppData/Roaming/Macromedia/Flash Player"_s)); + + TGeneric* wineSaveBackup = new TGeneric(this); + wineSaveBackup->setStage(Task::Stage::Shutdown); + wineSaveBackup->setDescription(u"Backup Flash WINE saves"_s); + wineSaveBackup->setAction([saveSrc, saveDest]{ + saveDest.mkpath(u"."_s); + return Qx::copyDirectory(saveSrc, saveDest, true, false); + }); + + mTaskQueue.push(wineSaveBackup); + logTask(wineSaveBackup); #endif } From 7cbf796ead8df3c5ff84b1a74265c8b615586d7c Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 5 Jul 2024 15:13:26 -0400 Subject: [PATCH 12/37] Supress clang analyzer warning for TExec Was assuming flase in a check where when the memory in question is freed the result will always be true. --- app/src/task/t-exec.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/task/t-exec.cpp b/app/src/task/t-exec.cpp index 8318011..fca12c1 100644 --- a/app/src/task/t-exec.cpp +++ b/app/src/task/t-exec.cpp @@ -260,7 +260,8 @@ void TExec::perform() } if(smDeferredProcessManager) - smDeferredProcessManager->manage(mIdentifier, taskProcess); // Add process to list for deferred termination + smDeferredProcessManager->manage(mIdentifier, taskProcess); // NOLINT(clang-analyzer-cplusplus.NewDelete) Add process to list for deferred termination + else qWarning("Deferred process started without a deferred process manager installed!"); break; From 7c3f5eee9ad37fac2832731a9273f752801e9b1b Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 5 Jul 2024 18:44:02 -0400 Subject: [PATCH 13/37] Rename proxy mounter to game server mounter Matches FPProxy's renaming to FPGameServer. --- app/CMakeLists.txt | 4 +- app/src/task/t-mount.cpp | 4 +- app/src/task/t-mount.h | 6 +- ...nter_proxy.cpp => mounter_game_server.cpp} | 70 +++++++++---------- ...{mounter_proxy.h => mounter_game_server.h} | 40 +++++------ 5 files changed, 62 insertions(+), 62 deletions(-) rename app/src/tools/{mounter_proxy.cpp => mounter_game_server.cpp} (64%) rename app/src/tools/{mounter_proxy.h => mounter_game_server.h} (74%) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 2bd230b..eca7181 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -51,8 +51,8 @@ set(CLIFP_SOURCE tools/blockingprocessmanager.cpp tools/deferredprocessmanager.h tools/deferredprocessmanager.cpp - tools/mounter_proxy.h - tools/mounter_proxy.cpp + tools/mounter_game_server.h + tools/mounter_game_server.cpp tools/mounter_qmp.h tools/mounter_qmp.cpp tools/mounter_router.h diff --git a/app/src/task/t-mount.cpp b/app/src/task/t-mount.cpp index 1be8bf1..6f5ad07 100644 --- a/app/src/task/t-mount.cpp +++ b/app/src/task/t-mount.cpp @@ -29,7 +29,7 @@ TMount::TMount(QObject* parent) : //-Instance Functions------------------------------------------------------------- //Private: template - requires Qx::any_of + requires Qx::any_of void TMount::initMounter(M*& mounter) { mounter = new M(this); @@ -79,7 +79,7 @@ void TMount::perform() { initMounter(mMounterProxy); mMounterProxy->setFilePath(mPath); - mMounterProxy->setProxyServerPort(22501); + mMounterProxy->setGameServerPort(22501); } else { diff --git a/app/src/task/t-mount.h b/app/src/task/t-mount.h index 84dbfb9..84478d6 100644 --- a/app/src/task/t-mount.h +++ b/app/src/task/t-mount.h @@ -12,7 +12,7 @@ // Project Includes #include "task/task.h" -#include "tools/mounter_proxy.h" +#include "tools/mounter_game_server.h" #include "tools/mounter_qmp.h" #include "tools/mounter_router.h" @@ -32,7 +32,7 @@ class TMount : public Task //-Instance Variables------------------------------------------------------------------------------------------------ private: // Mounters - MounterProxy* mMounterProxy; + MounterGameServer* mMounterProxy; MounterQmp* mMounterQmp; MounterRouter* mMounterRouter; @@ -51,7 +51,7 @@ class TMount : public Task //-Instance Functions------------------------------------------------------------------------------------------------------ private: template - requires Qx::any_of + requires Qx::any_of void initMounter(M*& mounter); public: diff --git a/app/src/tools/mounter_proxy.cpp b/app/src/tools/mounter_game_server.cpp similarity index 64% rename from app/src/tools/mounter_proxy.cpp rename to app/src/tools/mounter_game_server.cpp index 9d05480..7aee5b8 100644 --- a/app/src/tools/mounter_proxy.cpp +++ b/app/src/tools/mounter_game_server.cpp @@ -1,5 +1,5 @@ // Unit Includes -#include "mounter_proxy.h" +#include "mounter_game_server.h" // Qt Includes #include @@ -20,22 +20,22 @@ //-Constructor------------------------------------------------------------- //Private: -MounterProxyError::MounterProxyError(Type t, const QString& s) : +MounterGameServerError::MounterGameServerError(Type t, const QString& s) : mType(t), mSpecific(s) {} //-Instance Functions------------------------------------------------------------- //Public: -bool MounterProxyError::isValid() const { return mType != NoError; } -QString MounterProxyError::specific() const { return mSpecific; } -MounterProxyError::Type MounterProxyError::type() const { return mType; } +bool MounterGameServerError::isValid() const { return mType != NoError; } +QString MounterGameServerError::specific() const { return mSpecific; } +MounterGameServerError::Type MounterGameServerError::type() const { return mType; } //Private: -Qx::Severity MounterProxyError::deriveSeverity() const { return Qx::Critical; } -quint32 MounterProxyError::deriveValue() const { return mType; } -QString MounterProxyError::derivePrimary() const { return ERR_STRINGS.value(mType); } -QString MounterProxyError::deriveSecondary() const { return mSpecific; } +Qx::Severity MounterGameServerError::deriveSeverity() const { return Qx::Critical; } +quint32 MounterGameServerError::deriveValue() const { return mType; } +QString MounterGameServerError::derivePrimary() const { return ERR_STRINGS.value(mType); } +QString MounterGameServerError::deriveSecondary() const { return mSpecific; } //=============================================================================================================== // Mounter @@ -43,17 +43,17 @@ QString MounterProxyError::deriveSecondary() const { return mSpecific; } //-Constructor---------------------------------------------------------------------------------------------------------- //Public: -MounterProxy::MounterProxy(QObject* parent) : +MounterGameServer::MounterGameServer(QObject* parent) : QObject(parent), mMounting(false), - mProxyServerPort(0) + mGameServerPort(0) { // Setup Network Access Manager mNam.setAutoDeleteReplies(true); - mNam.setTransferTimeout(PROXY_TRANSFER_TIMEOUT); + mNam.setTransferTimeout(GAME_SERVER_TRANSFER_TIMEOUT); // Connections - Work - connect(&mNam, &QNetworkAccessManager::finished, this, &MounterProxy::proxyMountFinishedHandler); + connect(&mNam, &QNetworkAccessManager::finished, this, &MounterGameServer::gameServerMountFinishedHandler); /* Network check (none of these should be triggered, they are here in case a FP update would required * them to be used as to help make that clear in the logs when the update causes this to stop working). @@ -76,45 +76,45 @@ MounterProxy::MounterProxy(QObject* parent) : //-Instance Functions--------------------------------------------------------------------------------------------------------- //Private: -void MounterProxy::finish(const MounterProxyError& errorState) +void MounterGameServer::finish(const MounterGameServerError& errorState) { mMounting = false; emit mountFinished(errorState); } -void MounterProxy::noteProxyRequest(QNetworkAccessManager::Operation op, const QUrl& url, QByteArrayView data) +void MounterGameServer::noteProxyRequest(QNetworkAccessManager::Operation op, const QUrl& url, QByteArrayView data) { signalEventOccurred(EVENT_REQUEST_SENT.arg(ENUM_NAME(op), url.toString(), QString::fromLatin1(data))); } -void MounterProxy::noteProxyResponse(const QString& response) +void MounterGameServer::noteProxyResponse(const QString& response) { - signalEventOccurred(EVENT_PROXY_RESPONSE.arg(response)); + signalEventOccurred(EVENT_GAMESERVER_RESPONSE.arg(response)); } -void MounterProxy::signalEventOccurred(const QString& event) { emit eventOccurred(NAME, event); } -void MounterProxy::signalErrorOccurred(const MounterProxyError& errorMessage) { emit errorOccurred(NAME, errorMessage); } +void MounterGameServer::signalEventOccurred(const QString& event) { emit eventOccurred(NAME, event); } +void MounterGameServer::signalErrorOccurred(const MounterGameServerError& errorMessage) { emit errorOccurred(NAME, errorMessage); } //Public: -bool MounterProxy::isMounting() { return mMounting; } +bool MounterGameServer::isMounting() { return mMounting; } -quint16 MounterProxy::proxyServerPort() const { return mProxyServerPort; } -QString MounterProxy::filePath() const { return mFilePath; } +quint16 MounterGameServer::gameServerPort() const { return mGameServerPort; } +QString MounterGameServer::filePath() const { return mFilePath; } -void MounterProxy::setProxyServerPort(quint16 port) { mProxyServerPort = port; } -void MounterProxy::setFilePath(const QString& path) { mFilePath = QDir::toNativeSeparators(path); } +void MounterGameServer::setGameServerPort(quint16 port) { mGameServerPort = port; } +void MounterGameServer::setFilePath(const QString& path) { mFilePath = QDir::toNativeSeparators(path); } //-Signals & Slots------------------------------------------------------------------------------------------------------------ //Private Slots: -void MounterProxy::proxyMountFinishedHandler(QNetworkReply* reply) +void MounterGameServer::gameServerMountFinishedHandler(QNetworkReply* reply) { - assert(reply == mProxyMountReply.get()); + assert(reply == mGameServerMountReply.get()); - MounterProxyError err; + MounterGameServerError err; if(reply->error() != QNetworkReply::NoError) { - err = MounterProxyError(MounterProxyError::ProxyMount, reply->errorString()); + err = MounterGameServerError(MounterGameServerError::ProxyMount, reply->errorString()); signalErrorOccurred(err); } else @@ -127,7 +127,7 @@ void MounterProxy::proxyMountFinishedHandler(QNetworkReply* reply) } //Public Slots: -void MounterProxy::mount() +void MounterGameServer::mount() { signalEventOccurred(EVENT_MOUNTING); @@ -137,7 +137,7 @@ void MounterProxy::mount() QUrl mountUrl; mountUrl.setScheme(u"http"_s); mountUrl.setHost(u"localhost"_s); - mountUrl.setPort(mProxyServerPort); + mountUrl.setPort(mGameServerPort); mountUrl.setPath(u"/fpProxy/api/mountzip"_s); // Req @@ -159,16 +159,16 @@ void MounterProxy::mount() QByteArray data = jdData.toJson(QJsonDocument::Compact); //-POST Request--------------------------------- - mProxyMountReply = mNam.post(mountReq, data); + mGameServerMountReply = mNam.post(mountReq, data); // Log request - noteProxyRequest(mProxyMountReply->operation(), mountUrl, data); + noteProxyRequest(mGameServerMountReply->operation(), mountUrl, data); // Await finished() signal... } -void MounterProxy::abort() +void MounterGameServer::abort() { - if(mProxyMountReply && mProxyMountReply->isRunning()) - mProxyMountReply->abort(); + if(mGameServerMountReply && mGameServerMountReply->isRunning()) + mGameServerMountReply->abort(); } diff --git a/app/src/tools/mounter_proxy.h b/app/src/tools/mounter_game_server.h similarity index 74% rename from app/src/tools/mounter_proxy.h rename to app/src/tools/mounter_game_server.h index 864d183..2a1cb74 100644 --- a/app/src/tools/mounter_proxy.h +++ b/app/src/tools/mounter_game_server.h @@ -1,5 +1,5 @@ -#ifndef MOUNTER_PROXY_H -#define MOUNTER_PROXY_H +#ifndef MOUNTER_GAME_SERVER_H +#define MOUNTER_GAME_SERVER_H // Qt Includes #include @@ -11,9 +11,9 @@ #include #include -class QX_ERROR_TYPE(MounterProxyError, "MounterError", 1232) +class QX_ERROR_TYPE(MounterGameServerError, "MounterError", 1232) { - friend class MounterProxy; + friend class MounterGameServer; //-Class Enums------------------------------------------------------------- public: enum Type @@ -36,7 +36,7 @@ class QX_ERROR_TYPE(MounterProxyError, "MounterError", 1232) //-Constructor------------------------------------------------------------- private: - MounterProxyError(Type t = NoError, const QString& s = {}); + MounterGameServerError(Type t = NoError, const QString& s = {}); //-Instance Functions------------------------------------------------------------- public: @@ -51,7 +51,7 @@ class QX_ERROR_TYPE(MounterProxyError, "MounterError", 1232) QString deriveSecondary() const override; }; -class MounterProxy : public QObject +class MounterGameServer : public QObject { Q_OBJECT //-Class Variables------------------------------------------------------------------------------------------------------ @@ -60,52 +60,52 @@ class MounterProxy : public QObject static inline const QString NAME = u"Mounter"_s; // Events - External - static inline const QString EVENT_PROXY_RESPONSE = u"Proxy Response: \"%1\""_s; + static inline const QString EVENT_GAMESERVER_RESPONSE = u"Game Server Response: \"%1\""_s; // Events - Internal - static inline const QString EVENT_MOUNTING = u"Mounting data pack via proxy server..."_s; + static inline const QString EVENT_MOUNTING = u"Mounting data pack via game server..."_s; static inline const QString EVENT_REQUEST_SENT = u"Sent HTTP request\n" "\tOperation: %1\n" "\tURL: %2\n" "\tData: %3"_s; // Connections - static const int PROXY_TRANSFER_TIMEOUT = 30000; // ms + static const int GAME_SERVER_TRANSFER_TIMEOUT = 30000; // ms //-Instance Variables------------------------------------------------------------------------------------------------------------ private: bool mMounting; - int mProxyServerPort; + int mGameServerPort; QString mFilePath; QNetworkAccessManager mNam; - QPointer mProxyMountReply; + QPointer mGameServerMountReply; //-Constructor------------------------------------------------------------------------------------------------- public: - explicit MounterProxy(QObject* parent = nullptr); + explicit MounterGameServer(QObject* parent = nullptr); //-Instance Functions--------------------------------------------------------------------------------------------------------- private: - void finish(const MounterProxyError& errorState); + void finish(const MounterGameServerError& errorState); void noteProxyRequest(QNetworkAccessManager::Operation op, const QUrl& url, QByteArrayView data); void noteProxyResponse(const QString& response); void signalEventOccurred(const QString& event); - void signalErrorOccurred(const MounterProxyError& errorMessage); + void signalErrorOccurred(const MounterGameServerError& errorMessage); public: bool isMounting(); - quint16 proxyServerPort() const; + quint16 gameServerPort() const; QString filePath() const; - void setProxyServerPort(quint16 port); + void setGameServerPort(quint16 port); void setFilePath(const QString& path); //-Signals & Slots------------------------------------------------------------------------------------------------------------ private slots: - void proxyMountFinishedHandler(QNetworkReply* reply); + void gameServerMountFinishedHandler(QNetworkReply* reply); public slots: void mount(); @@ -113,12 +113,12 @@ public slots: signals: void eventOccurred(const QString& name, const QString& event); - void errorOccurred(const QString& name, const MounterProxyError& errorMessage); - void mountFinished(const MounterProxyError& errorState); + void errorOccurred(const QString& name, const MounterGameServerError& errorMessage); + void mountFinished(const MounterGameServerError& errorState); // For now these just cause a busy state void mountProgress(qint64 progress); void mountProgressMaximumChanged(qint64 maximum); }; -#endif // MOUNTER_PROXY_H +#endif // MOUNTER_GAME_SERVER_H From 6def511f5f4acae9f0b4ec691c6814da410e818e Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 5 Jul 2024 19:35:35 -0400 Subject: [PATCH 14/37] Add Linux specific logging --- app/src/kernel/core.cpp | 8 +++++++- app/src/kernel/core.h | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/src/kernel/core.cpp b/app/src/kernel/core.cpp index b86ce86..57204b7 100644 --- a/app/src/kernel/core.cpp +++ b/app/src/kernel/core.cpp @@ -448,8 +448,11 @@ void Core::attachFlashpoint(std::unique_ptr flashpointInstall) #ifdef __linux__ //-Mimic startup script setup------------------------- + logEvent(LOG_EVENT_LINUX_SPECIFIC_STARTUP_STEPS); + QString winFpPath = u"Z:"_s + QString(fpPath).replace('/', '\\'); bool immutable = mFlashpointInstall->dir().exists(u"Libraries"_s); // NOTE: This check likely will need to be modified over time + logEvent(LOG_EVENT_LINUX_BUILD_TYPE.arg(immutable ? u"isn't"_s : u"is"_s)); // Add platform support environment variables de.insert(u"DIR"_s, fpPath); @@ -471,7 +474,10 @@ void Core::attachFlashpoint(std::unique_ptr flashpointInstall) */ int gtkRes = QProcess::execute(u"sh"_s, {u"-c"_s, u"ldconfig -p | grep libgtk-3.so >/dev/null 2>&1"_s}); if(gtkRes != 0) + { + logEvent(LOG_EVENT_LINUX_GTK3_MISSING); de.insert(u"GTK_USE_PORTAL"_s, "1"); + } } else de.insert(u"LD_LIBRARY_PATH"_s, fpPath + u"/Legacy"_s); @@ -481,7 +487,7 @@ void Core::attachFlashpoint(std::unique_ptr flashpointInstall) */ QFile ruffle(fpPath + u"/Data/Ruffle/standalone/latest/ruffle"_s); // TODO: Might want to add this under Fp::Install if(!ruffle.setPermissions(QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther)) - qWarning("Failed to mark ruffle as executable!"); + logEvent(LOG_ERR_FAILED_SETTING_RUFFLE_PERMS); #endif TExec::setDefaultProcessEnvironment(de); diff --git a/app/src/kernel/core.h b/app/src/kernel/core.h index 2676c8c..c31cc64 100644 --- a/app/src/kernel/core.h +++ b/app/src/kernel/core.h @@ -157,6 +157,7 @@ class Core : public QObject // Logging - Errors static inline const QString LOG_ERR_INVALID_PARAM = u"Invalid parameters provided"_s; static inline const QString LOG_ERR_CRITICAL = u"Aborting execution due to previous critical errors"_s; + static inline const QString LOG_ERR_FAILED_SETTING_RUFFLE_PERMS= u"Failed to mark ruffle as executable!"_s; // Logging - Messages static inline const QString LOG_EVENT_INIT = u"Initializing CLIFp..."_s; @@ -187,6 +188,11 @@ class Core : public QObject static inline const QString LOG_EVENT_LAUNCHER_WATCH_HOOKED = u"Launcher hooked for waiting"_s; static inline const QString LOG_EVENT_LAUNCHER_CLOSED_RESULT = u"CLIFp cannot continue running in companion mode without the launcher's services."_s; + // Logging - Linux Specific Startup Steps + static inline const QString LOG_EVENT_LINUX_SPECIFIC_STARTUP_STEPS= u"Handling Linux specific startup steps..."_s; + static inline const QString LOG_EVENT_LINUX_BUILD_TYPE = u"Linux build %1 mutable."_s; + static inline const QString LOG_EVENT_LINUX_GTK3_MISSING = u"GTK3 isn't installed, setting GTK_USE_PORTAL=1"_s; + // Logging - Title Search static inline const QString LOG_EVENT_GAME_SEARCH = u"Searching for game with title '%1'"_s; static inline const QString LOG_EVENT_ADD_APP_SEARCH = u"Searching for additional-app with title '%1' and parent %2"_s; From fb9c9d738f00cdc25e66e38c65dcc60bb0b9f7b7 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 5 Jul 2024 19:37:00 -0400 Subject: [PATCH 15/37] Fix initial executable path determination Was using QFileInfo::canonicalFilePath() et. al. before actual filesystem resolution step, which meant that on Linux when forming a path to something that needs to be swapped from its windows variant (i.e. bat -> sh) a blank string would be created instead of the initial path. Use QDir::cleanPath() along with QFileInfo()::absoluteFilePath() to obtain the same clean string but without the requirement of the path actually existing. --- app/src/command/c-play.cpp | 4 ++-- app/src/command/c-run.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/command/c-play.cpp b/app/src/command/c-play.cpp index 96c1ecc..4de0a1d 100644 --- a/app/src/command/c-play.cpp +++ b/app/src/command/c-play.cpp @@ -244,7 +244,7 @@ Qx::Error CPlay::enqueueAdditionalApp(const Fp::AddApp& addApp, const QString& p TExec* addAppTask = new TExec(&mCore); addAppTask->setIdentifier(addApp.name()); addAppTask->setStage(taskStage); - addAppTask->setExecutable(addAppPathInfo.canonicalFilePath()); + addAppTask->setExecutable(QDir::cleanPath(addAppPathInfo.absoluteFilePath())); // Like canonical but doesn't care if path DNE addAppTask->setDirectory(addAppPathInfo.absoluteDir()); addAppTask->setParameters(addApp.launchCommand()); addAppTask->setEnvironment(mCore.childTitleProcessEnvironment()); @@ -272,7 +272,7 @@ Qx::Error CPlay::enqueueGame(const Fp::Game& game, const Fp::GameData& gameData, TExec* gameTask = new TExec(&mCore); gameTask->setIdentifier(game.title()); gameTask->setStage(taskStage); - gameTask->setExecutable(gamePathInfo.canonicalFilePath()); + gameTask->setExecutable(QDir::cleanPath(gamePathInfo.absoluteFilePath())); // Like canonical but doesn't care if path DNE gameTask->setDirectory(gamePathInfo.absoluteDir()); gameTask->setParameters(!gameData.isNull() ? gameData.launchCommand() : game.launchCommand()); gameTask->setEnvironment(mCore.childTitleProcessEnvironment()); diff --git a/app/src/command/c-run.cpp b/app/src/command/c-run.cpp index 76a9553..36218c1 100644 --- a/app/src/command/c-run.cpp +++ b/app/src/command/c-run.cpp @@ -53,8 +53,8 @@ Qx::Error CRun::perform() TExec* runTask = new TExec(&mCore); runTask->setIdentifier(NAME + u" program"_s); runTask->setStage(Task::Stage::Primary); - runTask->setExecutable(inputInfo.canonicalFilePath()); - runTask->setDirectory(inputInfo.canonicalPath()); + runTask->setExecutable(QDir::cleanPath(inputInfo.absoluteFilePath())); // Like canonical but doesn't care if path DNE + runTask->setDirectory(inputInfo.absolutePath()); runTask->setParameters(mParser.value(CL_OPTION_PARAM)); runTask->setEnvironment(mCore.childTitleProcessEnvironment()); runTask->setProcessType(TExec::ProcessType::Blocking); From df98abf47399c2fdb87cf20b09c1d82fe7c651a7 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Fri, 5 Jul 2024 21:31:32 -0400 Subject: [PATCH 16/37] TExec: Fix swap of .bat to .sh Was using sizeof() instead of size(). --- app/src/task/t-exec_linux.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/task/t-exec_linux.cpp b/app/src/task/t-exec_linux.cpp index d4fe9a6..21f173b 100644 --- a/app/src/task/t-exec_linux.cpp +++ b/app/src/task/t-exec_linux.cpp @@ -89,12 +89,11 @@ QString TExec::resolveExecutablePath() * of how the system would handle it. */ - // Exception: If a windows batch script is called for (shouldn't happen), see if there is a matching shell script - // as a last resort + // Exception: If a windows batch script is called for by this point (uncommon), see if there is a matching shell script QFileInfo execInfo(mExecutable); if(execInfo.suffix() == SHELL_EXT_WIN) { - execInfo.setFile(mExecutable.chopped(sizeof(SHELL_EXT_WIN)) + SHELL_EXT_LINUX); + execInfo.setFile(mExecutable.chopped(SHELL_EXT_WIN.size()) + SHELL_EXT_LINUX); emit eventOccurred(NAME, LOG_EVENT_FORCED_BASH); } From 4b6cbd469845151a1e445171b2988e42c52110ae Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 7 Jul 2024 00:37:09 -0400 Subject: [PATCH 17/37] Improve TDownload error verbosity --- CMakeLists.txt | 2 +- app/src/task/t-download.cpp | 15 ++++++++++++--- app/src/task/t-download.h | 9 ++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 069b6d0..da734b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ endif() include(OB/FetchQx) ob_fetch_qx( - REF "037a16dd85bb4de9419c7f095a520e898ccacebc" + REF "5dc3b3440442408456a867eb901185e5a281d4af" COMPONENTS ${CLIFP_QX_COMPONENTS} ) diff --git a/app/src/task/t-download.cpp b/app/src/task/t-download.cpp index 8258913..7041bab 100644 --- a/app/src/task/t-download.cpp +++ b/app/src/task/t-download.cpp @@ -10,11 +10,19 @@ //-Constructor------------------------------------------------------------- //Private: -TDownloadError::TDownloadError(Type t, const QString& s) : +TDownloadError::TDownloadError(Type t, const QString& s, const QString& d) : mType(t), - mSpecific(s) + mSpecific(s), + mDetails(d) {} +TDownloadError::TDownloadError(Qx::DownloadManagerReport dmReport) +{ + mType = dmReport.wasSuccessful() ? NoError : Incomplete; + mSpecific = dmReport.outcomeString(); + mDetails = dmReport.details(); +} + //-Instance Functions------------------------------------------------------------- //Public: bool TDownloadError::isValid() const { return mType != NoError; } @@ -26,6 +34,7 @@ Qx::Severity TDownloadError::deriveSeverity() const { return Qx::Critical; } quint32 TDownloadError::deriveValue() const { return mType; } QString TDownloadError::derivePrimary() const { return ERR_STRINGS.value(mType); } QString TDownloadError::deriveSecondary() const { return mSpecific; } +QString TDownloadError::deriveDetails() const { return mDetails; } //=============================================================================================================== // TDownload @@ -146,7 +155,7 @@ void TDownload::postDownload(Qx::DownloadManagerReport downloadReport) emitEventOccurred(LOG_EVENT_DOWNLOAD_SUCC); else { - errorStatus = TDownloadError(TDownloadError::Incomeplete, downloadReport.outcomeString()); + errorStatus = TDownloadError(downloadReport); emitErrorOccurred(errorStatus); } diff --git a/app/src/task/t-download.h b/app/src/task/t-download.h index d5cff61..1662055 100644 --- a/app/src/task/t-download.h +++ b/app/src/task/t-download.h @@ -23,7 +23,7 @@ class QX_ERROR_TYPE(TDownloadError, "TDownloadError", 1252) enum Type { NoError, - Incomeplete, + Incomplete, OfflineEdition }; @@ -31,7 +31,7 @@ class QX_ERROR_TYPE(TDownloadError, "TDownloadError", 1252) private: static inline const QHash ERR_STRINGS{ {NoError, u""_s}, - {Incomeplete, u"The download(s) could not be completed."_s}, + {Incomplete, u"The download(s) could not be completed."_s}, {OfflineEdition, u"A datapack download was prompted in an offline edition of Flashpoint."_s} }; @@ -39,10 +39,12 @@ class QX_ERROR_TYPE(TDownloadError, "TDownloadError", 1252) private: Type mType; QString mSpecific; + QString mDetails; //-Constructor------------------------------------------------------------- private: - TDownloadError(Type t = NoError, const QString& s = {}); + TDownloadError(Type t = NoError, const QString& s = {}, const QString& d = {}); + TDownloadError(Qx::DownloadManagerReport dmReport); //-Instance Functions------------------------------------------------------------- public: @@ -55,6 +57,7 @@ class QX_ERROR_TYPE(TDownloadError, "TDownloadError", 1252) quint32 deriveValue() const override; QString derivePrimary() const override; QString deriveSecondary() const override; + QString deriveDetails() const override; }; class TDownload : public Task From cce47642b56effc381466ff451eb3cb4446325d1 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 7 Jul 2024 02:18:40 -0400 Subject: [PATCH 18/37] Update OBCMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da734b7..7a5c409 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(CLIFp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("v0.3.4") +fetch_ob_cmake("ac9e9e26d29f5f6826d232283e76a7640b8d4844") # Initialize project according to standard rules include(OB/Project) From 167196ade35137629d48863c13ff4b538184ca1b Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 6 Jul 2024 14:50:35 -0400 Subject: [PATCH 19/37] Ignore existing files when performing Linux specific backup/restore Previously would cause an error. --- app/src/kernel/core.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/kernel/core.cpp b/app/src/kernel/core.cpp index 57204b7..8f9e9e2 100644 --- a/app/src/kernel/core.cpp +++ b/app/src/kernel/core.cpp @@ -587,7 +587,7 @@ CoreError Core::enqueueStartupTasks(const QString& serverOverride) { // Copy backup prefix QDir winePrefixBak(mFlashpointInstall->dir().absolutePath() + u"/FPSoftware/.winebak"_s); - if(Qx::copyDirectory(winePrefixBak, winePrefix, true, false).isFailure()) + if(Qx::copyDirectory(winePrefixBak, winePrefix, true, Qx::ReplaceMode::Skip).isFailure()) qWarning("Failed to restore WINE prefix backup"); // Setup WINE registry modification @@ -762,7 +762,7 @@ void Core::enqueueShutdownTasks() wineSaveBackup->setDescription(u"Backup Flash WINE saves"_s); wineSaveBackup->setAction([saveSrc, saveDest]{ saveDest.mkpath(u"."_s); - return Qx::copyDirectory(saveSrc, saveDest, true, false); + return Qx::copyDirectory(saveSrc, saveDest, true, Qx::ReplaceMode::Skip); }); mTaskQueue.push(wineSaveBackup); From 95f4ed5ef6b5757ab8847aae062f7aff9238b3c4 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 6 Jul 2024 14:51:16 -0400 Subject: [PATCH 20/37] Fix Core::postBlockingError() argument passthrough The button related args were unused. --- app/src/kernel/core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/kernel/core.cpp b/app/src/kernel/core.cpp index 8f9e9e2..3521113 100644 --- a/app/src/kernel/core.cpp +++ b/app/src/kernel/core.cpp @@ -295,7 +295,7 @@ void Core::logEvent(const QString& event) { logEvent(NAME, event); } void Core::logTask(const Task* task) { logTask(NAME, task); } ErrorCode Core::logFinish(const Qx::Error& errorState) { return logFinish(NAME, errorState); } void Core::postError(const Qx::Error& error, bool log) { postError(NAME, error, log); } -int Core::postBlockingError(const Qx::Error& error, bool log, QMessageBox::StandardButtons bs, QMessageBox::StandardButton def) { return postBlockingError(NAME, error, log); } +int Core::postBlockingError(const Qx::Error& error, bool log, QMessageBox::StandardButtons bs, QMessageBox::StandardButton def) { return postBlockingError(NAME, error, log, bs, def); } //Public: Qx::Error Core::initialize(QStringList& commandLine) From 39e4ce76e42851cb6faaca5f80a14a444983feae Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 7 Jul 2024 03:46:39 -0400 Subject: [PATCH 21/37] Actions: Update GitHub made action versions --- .github/workflows/build-clifp-linux.yml | 4 ++-- .github/workflows/build-clifp-windows.yml | 4 ++-- .github/workflows/master-pull-request-merge-reaction.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index e1fe072..50c37b7 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -84,7 +84,7 @@ jobs: - name: Install Wayland run: sudo apt-get install libwayland-dev - name: Checkout CLIFp - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ${{ env.clifp_src_suffix }} fetch-depth: 0 # Required for verbose versioning to work correctly @@ -108,7 +108,7 @@ jobs: artifact_name="$(basename "$cpack_name" .zip) [${{ matrix.cxx_comp }}]" echo "current_artifact_name=$artifact_name" >> $GITHUB_ENV - name: Upload CLIFp build artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.current_artifact_name }} path: ${{ env.clifp_install_path }} diff --git a/.github/workflows/build-clifp-windows.yml b/.github/workflows/build-clifp-windows.yml index 57c9375..0a62079 100644 --- a/.github/workflows/build-clifp-windows.yml +++ b/.github/workflows/build-clifp-windows.yml @@ -44,7 +44,7 @@ jobs: path: ${{ env.qt_install_dir }} credentials: ${{ secrets.qt_ffynnon_cred }} - name: Checkout CLIFp - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ${{ env.clifp_src_suffix }} fetch-depth: 0 # Required for verbose versioning to work correctly @@ -70,7 +70,7 @@ jobs: $artifact_name=$((Get-ChildItem -Path "${{ env.clifp_package_path }}" -Filter *.zip)[0].BaseName) + ' [msvc]' echo "current_artifact_name=$artifact_name" >> $Env:GITHUB_ENV - name: Upload CLIFp build artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.current_artifact_name }} path: ${{ env.clifp_install_path }} diff --git a/.github/workflows/master-pull-request-merge-reaction.yml b/.github/workflows/master-pull-request-merge-reaction.yml index 7ccf682..065604b 100644 --- a/.github/workflows/master-pull-request-merge-reaction.yml +++ b/.github/workflows/master-pull-request-merge-reaction.yml @@ -84,7 +84,7 @@ jobs: - name: Checkout repo uses: actions/checkout@v4 - name: Setup pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v4 - name: Upload pages artifact uses: actions/upload-pages-artifact@v1 with: @@ -100,7 +100,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download built CLIFp artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: path: ${{ env.artifacts_path }} - name: Zip up release artifacts From c1a4865038c07a8def6ca0d32caf7b84918a177d Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Mon, 8 Jul 2024 20:51:09 -0400 Subject: [PATCH 22/37] Actions: Simply build matricies Utilize maps for some matrix entries (undocummented feature) to greatly simplify he matricies for builds. Still requires some cruft with the use of "exclude", but overall the setup is much clearer, readable, and less prone to error. --- .github/workflows/build-clifp-linux.yml | 46 +++++++---------------- .github/workflows/build-clifp-windows.yml | 11 ++---- 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index 50c37b7..877c9aa 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -18,35 +18,15 @@ jobs: fail-fast: false matrix: os: [ubuntu-20.04, ubuntu-22.04] - compiler: [clang] - lib_linkage: [shared, static] - include: - - os: ubuntu-20.04 - compiler: clang - c_comp: clang-12 - cxx_comp: clang++-12 - qt_comp: clang12 - - os: ubuntu-22.04 - compiler: gcc - c_comp: gcc-12 - cxx_comp: g++-12 - qt_comp: clang14 - lib_linkage: shared - - os: ubuntu-22.04 - compiler: gcc - c_comp: gcc-12 - cxx_comp: g++-12 - qt_comp: clang14 - lib_linkage: static - - os: ubuntu-22.04 - compiler: clang - c_comp: clang-14 - cxx_comp: clang++-14 - qt_comp: clang14 - - lib_linkage: shared - cmake_bsl: ON - - lib_linkage: static - cmake_bsl: OFF + compiler: [{c: gcc-12, cxx: g++-12, qt: clang14}, {c: clang-12, cxx: clang++-12, qt: clang12}, {c: clang-14, cxx: clang++-14, qt: clang14}] + linkage: [{type: shared, cmake_bsl: ON}, {type: static, cmake_bsl: OFF}] + exclude: + - os: ubuntu-20.04 + compiler: {c: gcc-12, cxx: g++-12, qt: clang14} + - os: ubuntu-20.04 + compiler: {c: clang-14, cxx: clang++-14, qt: clang14} + - os: ubuntu-22.04 + compiler: {c: clang-12, cxx: clang++-12, qt: clang12} runs-on: ${{ matrix.os }} env: cmake_gen: Ninja Multi-Config @@ -62,8 +42,8 @@ jobs: with: version: 6.6.0 os: linux - compiler: ${{ matrix.qt_comp }} - linkage: ${{ matrix.lib_linkage }} + compiler: ${{ matrix.compiler.qt }} + linkage: ${{ matrix.linkage.type }} path: ${{ env.qt_install_dir }} credentials: ${{ secrets.qt_ffynnon_cred }} - name: Update package index @@ -92,7 +72,7 @@ jobs: working-directory: ${{ env.clifp_src_dir }} run: | echo Configuring CMake... - "$qt_cmake" -G "$cmake_gen" -S "$clifp_src_dir" -B "$clifp_build_dir" -D BUILD_SHARED_LIBS="${{ matrix.cmake_bsl }}" -D CMAKE_CXX_COMPILER="${{ matrix.cxx_comp }}" -D CMAKE_C_COMPILER="${{ matrix.c_comp }}" + "$qt_cmake" -G "$cmake_gen" -S "$clifp_src_dir" -B "$clifp_build_dir" -D BUILD_SHARED_LIBS="${{ matrix.linkage.cmake_bsl }}" -D CMAKE_CXX_COMPILER="${{ matrix.compiler.cxx }}" -D CMAKE_C_COMPILER="${{ matrix.compiler.c }}" echo Changing to build directory... cd "$clifp_build_dir" echo Building CLIFp Release... @@ -105,7 +85,7 @@ jobs: - name: Get CLIFp artifact name run: | cpack_name=$(find "${{ env.clifp_package_path }}" -type f -name "*.zip") - artifact_name="$(basename "$cpack_name" .zip) [${{ matrix.cxx_comp }}]" + artifact_name="$(basename "$cpack_name" .zip) [${{ matrix.compiler.cxx }}]" echo "current_artifact_name=$artifact_name" >> $GITHUB_ENV - name: Upload CLIFp build artifact uses: actions/upload-artifact@v4 diff --git a/.github/workflows/build-clifp-windows.yml b/.github/workflows/build-clifp-windows.yml index 0a62079..703aac3 100644 --- a/.github/workflows/build-clifp-windows.yml +++ b/.github/workflows/build-clifp-windows.yml @@ -17,12 +17,7 @@ jobs: strategy: fail-fast: false matrix: - lib_linkage: [shared, static] - include: - - lib_linkage: shared - cmake_bsl: ON - - lib_linkage: static - cmake_bsl: OFF + linkage: [{type: shared, cmake_bsl: ON}, {type: static, cmake_bsl: OFF}] runs-on: windows-latest env: vs_dir: C:/Program Files/Microsoft Visual Studio/2022/Enterprise @@ -40,7 +35,7 @@ jobs: version: 6.6.0 os: windows compiler: msvc2022 - linkage: ${{ matrix.lib_linkage }} + linkage: ${{ matrix.linkage.type }} path: ${{ env.qt_install_dir }} credentials: ${{ secrets.qt_ffynnon_cred }} - name: Checkout CLIFp @@ -55,7 +50,7 @@ jobs: echo "Setup C++ Build Environment..." CALL "${{ env.vs_dir }}\Common7\Tools\VsDevCmd.bat" -arch=amd64 echo "Configure CMake using Qt wrapper..." - CALL "${{ env.qt_cmake }}" -G "${{ env.cmake_gen }}" -S "${{ env.clifp_src_dir}}" -B "${{ env.clifp_build_dir }}" -D BUILD_SHARED_LIBS=${{ matrix.cmake_bsl }} + CALL "${{ env.qt_cmake }}" -G "${{ env.cmake_gen }}" -S "${{ env.clifp_src_dir}}" -B "${{ env.clifp_build_dir }}" -D BUILD_SHARED_LIBS=${{ matrix.linkage.cmake_bsl }} echo "Changing to build directory..." cd "%clifp_build_dir%" echo "Building CLIFp release..." From f81aa6b8656a04612dcc924bc3ce8987673e919c Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Tue, 9 Jul 2024 00:57:56 -0400 Subject: [PATCH 23/37] Actions: Update Qt --- .github/workflows/build-clifp-linux.yml | 2 +- .github/workflows/build-clifp-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index 877c9aa..23ab1a4 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -40,7 +40,7 @@ jobs: - name: Install Qt (custom build) uses: oblivioncth/actions/general/install-and-cache-qt-from-ffynnon@dev with: - version: 6.6.0 + version: 6.7.2 os: linux compiler: ${{ matrix.compiler.qt }} linkage: ${{ matrix.linkage.type }} diff --git a/.github/workflows/build-clifp-windows.yml b/.github/workflows/build-clifp-windows.yml index 703aac3..eb6f224 100644 --- a/.github/workflows/build-clifp-windows.yml +++ b/.github/workflows/build-clifp-windows.yml @@ -32,7 +32,7 @@ jobs: - name: Install Qt (custom build) uses: oblivioncth/actions/general/install-and-cache-qt-from-ffynnon@dev with: - version: 6.6.0 + version: 6.7.2 os: windows compiler: msvc2022 linkage: ${{ matrix.linkage.type }} From b68278e99d49a06204e61b1b3cc7322578e557f0 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Tue, 9 Jul 2024 04:33:13 -0400 Subject: [PATCH 24/37] Update OBCMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a5c409..e8f3b82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(CLIFp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("ac9e9e26d29f5f6826d232283e76a7640b8d4844") +fetch_ob_cmake("5fd04fa2f010cbecaeb336797e1813fb19d7f425") # Initialize project according to standard rules include(OB/Project) From 968c8fc93904e222a614c446d3ae2121bb2e4185 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Tue, 9 Jul 2024 22:12:13 -0400 Subject: [PATCH 25/37] Add missing Core5Compat component for find_package(Qt6) Not sure how it worked before this, but Qt 6.7.2 finally makes a hard check for this. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8f3b82..75b3c71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ endif() # Import Qt set(CLIFP_QT_COMPONENTS Core + Core5Compat Gui Widgets Sql From 90e116128085e0a0b141bc45acd96aa6e2c997a7 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Tue, 9 Jul 2024 23:17:11 -0400 Subject: [PATCH 26/37] Actions: Install DBus on 22.04 for static builds --- .github/workflows/build-clifp-linux.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index 23ab1a4..07eed3e 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -63,6 +63,9 @@ jobs: run: sudo apt-get install libegl1-mesa-dev - name: Install Wayland run: sudo apt-get install libwayland-dev + - name: Install DBus + if: matrix.os == 'ubuntu-22.04' + run: sudo apt-get install libdbus-1-dev - name: Checkout CLIFp uses: actions/checkout@v4 with: From c66dd4face1da5f07f45176c21a7110ba2af071e Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Wed, 10 Jul 2024 03:27:51 -0400 Subject: [PATCH 27/37] Update libfp, update .gitignore --- .gitignore | 3 +++ CMakeLists.txt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4bd8fc8..8d76c0c 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,9 @@ Thumbs.db # Python byte code *.pyc +# Build within source +/build + # Binaries # -------- *.dll diff --git a/CMakeLists.txt b/CMakeLists.txt index 75b3c71..46c3ce9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ ob_fetch_qx( # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("c14360d4306e6f74bce06f98414a3a51f0cf9cd8") +ob_fetch_libfp("086051bca750adac3178a86fc47b61f1770d8b40") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP) From 96af865310fb5ca93fc3e3416f0b5d96c7b168da Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 11 Jul 2024 21:29:57 -0400 Subject: [PATCH 28/37] Update OBCMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 46c3ce9..70cf366 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(CLIFp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("5fd04fa2f010cbecaeb336797e1813fb19d7f425") +fetch_ob_cmake("88b04e6811bb434af4a5ffd8769ce751b024d7eb") # Initialize project according to standard rules include(OB/Project) From 4033b624c1d6b58ae3e6ae422fb9a3555a31b9eb Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 11 Jul 2024 21:36:32 -0400 Subject: [PATCH 29/37] Actions: Insure libzstd-dev is installed for Linux builds --- .github/workflows/build-clifp-linux.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index 07eed3e..b67bd6d 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -63,9 +63,11 @@ jobs: run: sudo apt-get install libegl1-mesa-dev - name: Install Wayland run: sudo apt-get install libwayland-dev - - name: Install DBus + - name: Install DBus [22.04] if: matrix.os == 'ubuntu-22.04' run: sudo apt-get install libdbus-1-dev + - name: Install libzstd-dev + run: sudo apt-get install libzstd-dev - name: Checkout CLIFp uses: actions/checkout@v4 with: From 220af8a182d9eeb1bc42e9edb8a7fe00c8f0427a Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 11 Jul 2024 21:42:19 -0400 Subject: [PATCH 30/37] Actions: Ensure libdbus-1-dev is installed for Linux builds --- .github/workflows/build-clifp-linux.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index b67bd6d..445cfd3 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -68,6 +68,8 @@ jobs: run: sudo apt-get install libdbus-1-dev - name: Install libzstd-dev run: sudo apt-get install libzstd-dev + - name: Install libdbus-1-dev + run: sudo apt-get install libdbus-1-dev - name: Checkout CLIFp uses: actions/checkout@v4 with: From 1ab944209f5746feb6a25162fb8cd20cdd3c536f Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Thu, 11 Jul 2024 21:45:26 -0400 Subject: [PATCH 31/37] Actions: Ensure libbrotli-dev is installed for Linux builds --- .github/workflows/build-clifp-linux.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-clifp-linux.yml b/.github/workflows/build-clifp-linux.yml index 445cfd3..6c95f64 100644 --- a/.github/workflows/build-clifp-linux.yml +++ b/.github/workflows/build-clifp-linux.yml @@ -70,6 +70,8 @@ jobs: run: sudo apt-get install libzstd-dev - name: Install libdbus-1-dev run: sudo apt-get install libdbus-1-dev + - name: Install libbrotli-dev + run: sudo apt-get install libbrotli-dev - name: Checkout CLIFp uses: actions/checkout@v4 with: From 3a9f8a4e8805da75546c717c4ea4449d341d0f3d Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 13 Jul 2024 19:26:16 -0400 Subject: [PATCH 32/37] Update OBCMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70cf366..ef2a2cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(CLIFp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("88b04e6811bb434af4a5ffd8769ce751b024d7eb") +fetch_ob_cmake("6f3d5a21e1bb1c1eb3f07d08cf757a14a85e0b21") # Initialize project according to standard rules include(OB/Project) From 3bf6cb331ff43160ad36fb5c859b6321bf7aa280 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 13 Jul 2024 21:02:28 -0400 Subject: [PATCH 33/37] More properly include wayland support It seems the proper way to include wayland support is to link the app to Qt::WaylandClient, which is also a Qt component. So, we include the component in the find_package() call and ob_add_standard_executable() takes care of linking to the target automatically when it's available. --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef2a2cb..6c3b577 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(CLIFp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("6f3d5a21e1bb1c1eb3f07d08cf757a14a85e0b21") +fetch_ob_cmake("3e6aaf407ba9e2c6025d35702fde3361dca5a0db") # Initialize project according to standard rules include(OB/Project) @@ -51,6 +51,10 @@ set(CLIFP_QT_COMPONENTS Network ) +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + list(APPEND CLIFP_QT_COMPONENTS WaylandClient) # To enable wayland support +endif() + # Find Qt package add_compile_definitions(QT_DISABLE_DEPRECATED_BEFORE=0x060000) find_package(Qt6 REQUIRED COMPONENTS ${CLIFP_QT_COMPONENTS}) From af076f3b5d21baebab94eec9a74d6dd8a1488c8d Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 13 Jul 2024 21:42:22 -0400 Subject: [PATCH 34/37] Add release build guidelines to README.md --- README.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ab4dad9..d9f690e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Other than a few pop-up dialogs used for alerts and errors, CLIFp runs completel ## Quickstart -Download the latest **static** [release](https://github.com/oblivioncth/CLIFp/releases) that's appropriate for your system and place it in the root of your Flashpoint directory. +Download the latest [release](https://github.com/oblivioncth/CLIFp/releases) that's appropriate for your system (see [Release Builds](#release-builds) for guidance on that) and place it in the root of your Flashpoint directory. Play a game: @@ -304,4 +304,31 @@ The functionality of the tray icon may be expanded upon in future releases. - [OBCMake](https://github.com/oblivioncth/OBCmake) ### Details -The source for this project is managed by a sensible CMake configuration that allows for straightforward compilation and consumption of its target(s), either as a sub-project or as an imported package. All required dependencies except for Qt6 are automatically acquired via CMake's FetchContent mechanism. \ No newline at end of file +The source for this project is managed by a sensible CMake configuration that allows for straightforward compilation and consumption of its target(s), either as a sub-project or as an imported package. All required dependencies except for Qt6 are automatically acquired via CMake's FetchContent mechanism. + +## Release Builds +For guidance on which release build is likely best for your system, compare your system to the table below and try whichever is most comparable to yours in the order shown. The compiler used is somewhat arbitrary, so equivalent compilers are combined in the table. If one build type with a given compiler does not work for you it's unlikely the other listed as part of the same line will, but you can try it if you want. + +| System | Builds | +| ----------------------------------------- | ------------------------------------------------------------------------ | +| Windows | 1) Windows Static
2) Windows Shared | +| Ubuntu 24.04, Ubuntu 22.02, Arch, SteamOS | 1) Linux Static Clang++14/GCC++12
2) Linux Shared Clang++14/GCC++12 | +| Ubuntu 20.04 | 1) Linux Static Clang++12
2) Linux Shared Clang++12 | + +Note that for shared builds, you must place the entire directory structure of the release in your Flashpoint folder and run CLIFp from within it's bin directory, like so: +``` +Flashpoint/ +├── CLIFp/ +│ ├── bin/ +│ │ └── clifp.exe +│ ├── cmake +│ ├── LICENSE +│ ├── README.md +│ └── ... +├── version.txt +├── preferences.json +└── ... +``` +For static builds you can simply take the CLIFp executable out of the bin directory and place it directly in your Flashpoint folder. + +Remember these are just guidelines. Ultimately use whichever build you like, or build CLIFp yourself. \ No newline at end of file From 2718cba5adeb98e65f8d9c5f24ee484e94f9a8b5 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sat, 13 Jul 2024 21:58:12 -0400 Subject: [PATCH 35/37] Update OBCMake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c3b577..97846b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(CLIFp # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("3e6aaf407ba9e2c6025d35702fde3361dca5a0db") +fetch_ob_cmake("2356fb3e6f2d5710045cd9dbe66187856418d8ca") # Initialize project according to standard rules include(OB/Project) From ed26160b265cb3603cea9a4efab59d299110530c Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 14 Jul 2024 17:59:09 -0400 Subject: [PATCH 36/37] Bump target FP number --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97846b9..e3fd892 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ ob_standard_project_setup() # Additional Project Variables set(PROJECT_FORMAL_NAME "CLI Flashpoint") -set(TARGET_FP_VERSION_PREFIX 12.1) +set(TARGET_FP_VERSION_PREFIX 13.0) # Configuration options # Handled by fetched libs, but set this here formally since they aren't part of the main project From fb3915fced0e8f6759639e049dda55a6c946a439 Mon Sep 17 00:00:00 2001 From: Christian Heimlich Date: Sun, 14 Jul 2024 18:10:51 -0400 Subject: [PATCH 37/37] Bump for release --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3fd892..457b3ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,14 +6,14 @@ cmake_minimum_required(VERSION 3.24.0...3.26.0) # Project # NOTE: DON'T USE TRAILING ZEROS IN VERSIONS project(CLIFp - VERSION 0.9.10 + VERSION 0.9.11 LANGUAGES CXX DESCRIPTION "Command-line Interface for Flashpoint Archive" ) # Get helper scripts include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake) -fetch_ob_cmake("2356fb3e6f2d5710045cd9dbe66187856418d8ca") +fetch_ob_cmake("v0.3.5") # Initialize project according to standard rules include(OB/Project) @@ -77,14 +77,14 @@ endif() include(OB/FetchQx) ob_fetch_qx( - REF "5dc3b3440442408456a867eb901185e5a281d4af" + REF "v0.5.7" COMPONENTS ${CLIFP_QX_COMPONENTS} ) # Fetch libfp (build and import from source) include(OB/Fetchlibfp) -ob_fetch_libfp("086051bca750adac3178a86fc47b61f1770d8b40") +ob_fetch_libfp("v0.5.3") # Fetch QI-QMP (build and import from source) include(OB/FetchQI-QMP)