mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-27 21:01:37 +00:00
Linux flatpak. (#51)
* Add flatpak support. * Add game install directory override for flatpak. * Flatpak'ing. * Flatpak it some more. * We flat it, we pak it. * Flatpak'd. * The Marvelous Misadventures of Flatpak. * Attempt to change logic of NFD and show error. * Flattenpakken. * Use game install directory instead of current path. * Attempt to fix line endings.
This commit is contained in:
parent
279390f1fe
commit
bbbcdf1566
11 changed files with 148 additions and 23 deletions
|
|
@ -5,6 +5,10 @@ if (WIN32)
|
||||||
option(SWA_D3D12 "Add D3D12 support for rendering" ON)
|
option(SWA_D3D12 "Add D3D12 support for rendering" ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
option(SWA_FLATPAK "Configure the build for Flatpak compatibility." OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
option(SWA_XAUDIO2 "Use XAudio2 for audio playback" OFF)
|
option(SWA_XAUDIO2 "Use XAudio2 for audio playback" OFF)
|
||||||
|
|
||||||
function(BIN2C)
|
function(BIN2C)
|
||||||
|
|
@ -257,7 +261,11 @@ else()
|
||||||
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES})
|
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(UnleashedRecomp PROPERTIES OUTPUT_NAME ${TARGET_NAME})
|
set_target_properties(UnleashedRecomp PROPERTIES OUTPUT_NAME ${TARGET_NAME})
|
||||||
|
|
||||||
|
if (SWA_FLATPAK)
|
||||||
|
target_compile_definitions(UnleashedRecomp PRIVATE "GAME_INSTALL_DIRECTORY=\"/var/data\"")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (SWA_D3D12)
|
if (SWA_D3D12)
|
||||||
find_package(directx-headers CONFIG REQUIRED)
|
find_package(directx-headers CONFIG REQUIRED)
|
||||||
|
|
|
||||||
|
|
@ -313,11 +313,11 @@ SWA_API uint32_t XamContentCreateEx(uint32_t dwUserIndex, const char* szRootName
|
||||||
}
|
}
|
||||||
else if (pContentData->dwContentType == XCONTENTTYPE_DLC)
|
else if (pContentData->dwContentType == XCONTENTTYPE_DLC)
|
||||||
{
|
{
|
||||||
root = "./dlc";
|
root = GAME_INSTALL_DIRECTORY "/dlc";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
root = ".";
|
root = GAME_INSTALL_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
XamRegisterContent(*pContentData, root);
|
XamRegisterContent(*pContentData, root);
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ void KiSystemStartup()
|
||||||
{
|
{
|
||||||
const auto gameContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Game");
|
const auto gameContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Game");
|
||||||
const auto updateContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Update");
|
const auto updateContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Update");
|
||||||
XamRegisterContent(gameContent, std::filesystem::exists("./game") ? "./game" : ".");
|
XamRegisterContent(gameContent, GAME_INSTALL_DIRECTORY "/game");
|
||||||
XamRegisterContent(updateContent, "./update");
|
XamRegisterContent(updateContent, GAME_INSTALL_DIRECTORY "/update");
|
||||||
|
|
||||||
const auto savePath = GetSavePath();
|
const auto savePath = GetSavePath();
|
||||||
const auto saveName = "SYS-DATA";
|
const auto saveName = "SYS-DATA";
|
||||||
|
|
@ -70,7 +70,7 @@ void KiSystemStartup()
|
||||||
XamContentCreateEx(0, "D", &gameContent, OPEN_EXISTING, nullptr, nullptr, 0, 0, nullptr);
|
XamContentCreateEx(0, "D", &gameContent, OPEN_EXISTING, nullptr, nullptr, 0, 0, nullptr);
|
||||||
|
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
for (auto& file : std::filesystem::directory_iterator("./dlc", ec))
|
for (auto& file : std::filesystem::directory_iterator(GAME_INSTALL_DIRECTORY "/dlc", ec))
|
||||||
{
|
{
|
||||||
if (file.is_directory())
|
if (file.is_directory())
|
||||||
{
|
{
|
||||||
|
|
@ -151,13 +151,13 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
HostStartup();
|
HostStartup();
|
||||||
|
|
||||||
bool isGameInstalled = Installer::checkGameInstall(".");
|
bool isGameInstalled = Installer::checkGameInstall(GAME_INSTALL_DIRECTORY);
|
||||||
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
|
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
|
||||||
if (runInstallerWizard)
|
if (runInstallerWizard)
|
||||||
{
|
{
|
||||||
Video::CreateHostDevice();
|
Video::CreateHostDevice();
|
||||||
|
|
||||||
if (!InstallerWizard::Run(isGameInstalled && forceDLCInstaller))
|
if (!InstallerWizard::Run(GAME_INSTALL_DIRECTORY, isGameInstalled && forceDLCInstaller))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ static double g_appearTime = 0.0;
|
||||||
static double g_disappearTime = DBL_MAX;
|
static double g_disappearTime = DBL_MAX;
|
||||||
static bool g_isDisappearing = false;
|
static bool g_isDisappearing = false;
|
||||||
|
|
||||||
static std::filesystem::path g_installPath = ".";
|
static std::filesystem::path g_installPath;
|
||||||
static std::filesystem::path g_gameSourcePath;
|
static std::filesystem::path g_gameSourcePath;
|
||||||
static std::filesystem::path g_updateSourcePath;
|
static std::filesystem::path g_updateSourcePath;
|
||||||
static std::array<std::filesystem::path, int(DLC::Count)> g_dlcSourcePaths;
|
static std::array<std::filesystem::path, int(DLC::Count)> g_dlcSourcePaths;
|
||||||
|
|
@ -135,6 +135,7 @@ static std::string g_currentMessagePrompt = "";
|
||||||
static bool g_currentMessagePromptConfirmation = false;
|
static bool g_currentMessagePromptConfirmation = false;
|
||||||
static std::list<std::filesystem::path> g_currentPickerResults;
|
static std::list<std::filesystem::path> g_currentPickerResults;
|
||||||
static std::atomic<bool> g_currentPickerResultsReady = false;
|
static std::atomic<bool> g_currentPickerResultsReady = false;
|
||||||
|
static std::string g_currentPickerErrorMessage;
|
||||||
static std::unique_ptr<std::thread> g_currentPickerThread;
|
static std::unique_ptr<std::thread> g_currentPickerThread;
|
||||||
static bool g_currentPickerVisible = false;
|
static bool g_currentPickerVisible = false;
|
||||||
static bool g_currentPickerFolderMode = false;
|
static bool g_currentPickerFolderMode = false;
|
||||||
|
|
@ -872,15 +873,15 @@ static bool ConvertPathSet(const nfdpathset_t *pathSet, std::list<std::filesyste
|
||||||
|
|
||||||
for (nfdpathsetsize_t i = 0; i < pathSetCount; i++)
|
for (nfdpathsetsize_t i = 0; i < pathSetCount; i++)
|
||||||
{
|
{
|
||||||
char *pathSetPath = nullptr;
|
nfdnchar_t *pathSetPath = nullptr;
|
||||||
if (NFD_PathSet_GetPathU8(pathSet, i, &pathSetPath) != NFD_OKAY)
|
if (NFD_PathSet_GetPathN(pathSet, i, &pathSetPath) != NFD_OKAY)
|
||||||
{
|
{
|
||||||
filePaths.clear();
|
filePaths.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
filePaths.emplace_back(std::filesystem::path(std::u8string_view((const char8_t *)(pathSetPath))));
|
filePaths.emplace_back(std::filesystem::path(pathSetPath));
|
||||||
NFD_PathSet_FreePathU8(pathSetPath);
|
NFD_PathSet_FreePathN(pathSetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -892,13 +893,11 @@ static void PickerThreadProcess()
|
||||||
nfdresult_t result = NFD_ERROR;
|
nfdresult_t result = NFD_ERROR;
|
||||||
if (g_currentPickerFolderMode)
|
if (g_currentPickerFolderMode)
|
||||||
{
|
{
|
||||||
nfdpickfolderu8args_t openArgs = {};
|
result = NFD_PickFolderMultipleN(&pathSet, nullptr);
|
||||||
result = NFD_PickFolderMultipleU8_With(&pathSet, &openArgs);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nfdopendialogu8args_t openArgs = {};
|
result = NFD_OpenDialogMultipleN(&pathSet, nullptr, 0, nullptr);
|
||||||
result = NFD_OpenDialogMultipleU8_With(&pathSet, &openArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == NFD_OKAY)
|
if (result == NFD_OKAY)
|
||||||
|
|
@ -906,6 +905,10 @@ static void PickerThreadProcess()
|
||||||
bool pathsConverted = ConvertPathSet(pathSet, g_currentPickerResults);
|
bool pathsConverted = ConvertPathSet(pathSet, g_currentPickerResults);
|
||||||
NFD_PathSet_Free(pathSet);
|
NFD_PathSet_Free(pathSet);
|
||||||
}
|
}
|
||||||
|
else if (result == NFD_ERROR)
|
||||||
|
{
|
||||||
|
g_currentPickerErrorMessage = NFD_GetError();
|
||||||
|
}
|
||||||
|
|
||||||
g_currentPickerResultsReady = true;
|
g_currentPickerResultsReady = true;
|
||||||
g_currentPickerVisible = false;
|
g_currentPickerVisible = false;
|
||||||
|
|
@ -1343,6 +1346,13 @@ static void CheckPickerResults()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_currentPickerErrorMessage.empty())
|
||||||
|
{
|
||||||
|
g_currentMessagePrompt = g_currentPickerErrorMessage;
|
||||||
|
g_currentMessagePromptConfirmation = false;
|
||||||
|
g_currentPickerErrorMessage.clear();
|
||||||
|
}
|
||||||
|
|
||||||
ParseSourcePaths(g_currentPickerResults);
|
ParseSourcePaths(g_currentPickerResults);
|
||||||
g_currentPickerResultsReady = false;
|
g_currentPickerResultsReady = false;
|
||||||
g_currentPickerVisible = false;
|
g_currentPickerVisible = false;
|
||||||
|
|
@ -1426,8 +1436,10 @@ void InstallerWizard::Shutdown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstallerWizard::Run(bool skipGame)
|
bool InstallerWizard::Run(std::filesystem::path installPath, bool skipGame)
|
||||||
{
|
{
|
||||||
|
g_installPath = installPath;
|
||||||
|
|
||||||
EmbeddedPlayer::Init();
|
EmbeddedPlayer::Init();
|
||||||
NFD_Init();
|
NFD_Init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,5 @@ struct InstallerWizard
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Draw();
|
static void Draw();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
static bool Run(bool skipGame);
|
static bool Run(std::filesystem::path installPath, bool skipGame);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public:
|
||||||
|
|
||||||
#define WINDOWPOS_CENTRED 0x2FFF0000
|
#define WINDOWPOS_CENTRED 0x2FFF0000
|
||||||
|
|
||||||
static inline std::vector<IConfigDef*> g_configDefinitions{};
|
inline std::vector<IConfigDef*> g_configDefinitions;
|
||||||
|
|
||||||
CONFIG_DEFINE_ENUM_TEMPLATE(ELanguage)
|
CONFIG_DEFINE_ENUM_TEMPLATE(ELanguage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,19 @@
|
||||||
|
|
||||||
#define USER_DIRECTORY "SWA"
|
#define USER_DIRECTORY "SWA"
|
||||||
|
|
||||||
|
#ifndef GAME_INSTALL_DIRECTORY
|
||||||
|
#define GAME_INSTALL_DIRECTORY "."
|
||||||
|
#endif
|
||||||
|
|
||||||
inline std::filesystem::path GetGamePath()
|
inline std::filesystem::path GetGamePath()
|
||||||
{
|
{
|
||||||
return std::filesystem::current_path();
|
return GAME_INSTALL_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::filesystem::path GetUserPath()
|
inline std::filesystem::path GetUserPath()
|
||||||
{
|
{
|
||||||
if (std::filesystem::exists("portable.txt"))
|
if (std::filesystem::exists(GAME_INSTALL_DIRECTORY "portable.txt"))
|
||||||
return std::filesystem::current_path();
|
return GAME_INSTALL_DIRECTORY;
|
||||||
|
|
||||||
std::filesystem::path userPath;
|
std::filesystem::path userPath;
|
||||||
|
|
||||||
|
|
|
||||||
10
flatpak/README.md
Normal file
10
flatpak/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
Build
|
||||||
|
```sh
|
||||||
|
flatpak-builder --force-clean --user --install-deps-from=flathub --repo=repo --install builddir io.github.hedge_dev.unleashedrecomp.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Bundle
|
||||||
|
```sh
|
||||||
|
flatpak build-bundle repo io.github.hedge_dev.unleashedrecomp.flatpak io.github.hedge_dev.unleashedrecomp --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo
|
||||||
|
```
|
||||||
|
|
||||||
7
flatpak/io.github.hedge_dev.unleashedrecomp.desktop
Normal file
7
flatpak/io.github.hedge_dev.unleashedrecomp.desktop
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Unleashed Recompiled
|
||||||
|
Exec=/app/bin/SWA
|
||||||
|
Type=Application
|
||||||
|
Icon=io.github.hedge_dev.unleashedrecomp
|
||||||
|
Categories=Game;
|
||||||
|
Comment=Static recompilation of Sonic Unleashed.
|
||||||
58
flatpak/io.github.hedge_dev.unleashedrecomp.json
Normal file
58
flatpak/io.github.hedge_dev.unleashedrecomp.json
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"id": "io.github.hedge_dev.unleashedrecomp",
|
||||||
|
"runtime": "org.freedesktop.Platform",
|
||||||
|
"runtime-version": "23.08",
|
||||||
|
"sdk": "org.freedesktop.Sdk",
|
||||||
|
"sdk-extensions" : [ "org.freedesktop.Sdk.Extension.llvm18" ],
|
||||||
|
"finish-args": [
|
||||||
|
"--share=network",
|
||||||
|
"--socket=wayland",
|
||||||
|
"--socket=fallback-x11",
|
||||||
|
"--socket=pulseaudio",
|
||||||
|
"--device=all",
|
||||||
|
"--filesystem=host",
|
||||||
|
"--filesystem=/media",
|
||||||
|
"--filesystem=/run/media",
|
||||||
|
"--filesystem=/mnt"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"name": "UnleashedRecomp",
|
||||||
|
"buildsystem": "simple",
|
||||||
|
"build-commands": [
|
||||||
|
"cmake --preset linux-release -DSWA_FLATPAK=ON",
|
||||||
|
"cmake --build out/build/linux-release",
|
||||||
|
"mkdir -p /app/bin",
|
||||||
|
"cp out/build/linux-release/UnleashedRecomp/SWA /app/bin/SWA",
|
||||||
|
"install -Dm644 UnleashedRecompResources/images/game_icon.png /app/share/icons/hicolor/128x128/apps/${FLATPAK_ID}.png",
|
||||||
|
"install -Dm644 flatpak/io.github.hedge_dev.unleashedrecomp.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml",
|
||||||
|
"install -Dm644 flatpak/io.github.hedge_dev.unleashedrecomp.desktop /app/share/applications/${FLATPAK_ID}.desktop"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"branch": "linux-flatpak",
|
||||||
|
"disable-shallow-clone": true,
|
||||||
|
"url": "https://github.com/hedge-dev/UnleashedRecomp.git"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"path": "default.xex",
|
||||||
|
"dest": "UnleashedRecompLib/private"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "file",
|
||||||
|
"path": "shader.ar",
|
||||||
|
"dest": "UnleashedRecompLib/private"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"build-options": {
|
||||||
|
"append-path": "/usr/lib/sdk/llvm18/bin",
|
||||||
|
"prepend-ld-library-path": "/usr/lib/sdk/llvm18/lib",
|
||||||
|
"build-args": [
|
||||||
|
"--share=network"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
26
flatpak/io.github.hedge_dev.unleashedrecomp.metainfo.xml
Normal file
26
flatpak/io.github.hedge_dev.unleashedrecomp.metainfo.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component type="desktop-application">
|
||||||
|
<id>io.github.hedge_dev.unleashedrecomp</id>
|
||||||
|
|
||||||
|
<name>Unleashed Recompiled</name>
|
||||||
|
<summary>Static recompilation of Sonic Unleashed.</summary>
|
||||||
|
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-3.0+</project_license>
|
||||||
|
|
||||||
|
<supports>
|
||||||
|
<control>pointing</control>
|
||||||
|
<control>keyboard</control>
|
||||||
|
<control>touch</control>
|
||||||
|
</supports>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
A native PC port of Sonic Unleashed for Xbox 360 achieved through static recompilation.
|
||||||
|
|
||||||
|
https://github.com/hedge-dev/UnleashedRecomp
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<launchable type="desktop-id">io.github.hedge_dev.unleashedrecomp.desktop</launchable>
|
||||||
|
</component>
|
||||||
Loading…
Add table
Reference in a new issue