feat: initial Elsword-GE builder

This commit is contained in:
magges
2026-06-27 10:26:21 +02:00
commit f3817f7c82
6 changed files with 822 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
name: build-elsword-ge
on:
schedule:
- cron: "0 4 * * *"
workflow_dispatch:
permissions:
contents: write
jobs:
build-release:
runs-on: self-hosted
steps:
- name: Checkout repository
run: |
git init .
git config --global --add safe.directory "$PWD"
git remote add origin "${{ gitea.server_url }}/${{ gitea.repository }}.git"
git -c http.extraHeader="Authorization: token ${{ secrets.GITEA_TOKEN }}" fetch --depth 1 origin "${{ gitea.sha }}"
git checkout --detach FETCH_HEAD
- name: Build Elsword Proton-GE 10-34 tool
run: |
nix develop -c ./build.sh --no-install
- name: Create or update Gitea release
env:
GITEA_SERVER_URL: ${{ gitea.server_url }}
GITEA_REPOSITORY: ${{ gitea.repository }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
GITEA_SHA: ${{ gitea.sha }}
run: |
nix develop -c bash -lc '
set -euo pipefail
set -a
. dist/package-info.env
set +a
RELEASE_API="${GITEA_SERVER_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases"
RELEASE_TAG_URL="$(python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=\"\"))" "$RELEASE_TAG")"
ARCHIVE_URL_NAME="$(python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=\"\"))" "$ARCHIVE_FILE")"
HTTP_CODE="$(curl -s -o /tmp/release.json -w "%{http_code}" \
-H "Authorization: token ${GITEA_TOKEN}" \
"${RELEASE_API}/tags/${RELEASE_TAG_URL}")"
if [ "$HTTP_CODE" = "200" ]; then
RELEASE_ID="$(python3 -c "import json; print(json.load(open(\"/tmp/release.json\"))[\"id\"])" )"
elif [ "$HTTP_CODE" = "404" ]; then
python3 -c "import json, pathlib, os; pathlib.Path(\"/tmp/release-create.json\").write_text(json.dumps({
\"tag_name\": os.environ[\"RELEASE_TAG\"],
\"target_commitish\": os.environ[\"GITEA_SHA\"],
\"name\": os.environ[\"RELEASE_TAG\"],
\"body\": pathlib.Path(\"dist/release-notes.md\").read_text(),
\"draft\": False,
\"prerelease\": False,
}))"
curl --fail-with-body \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
--data-binary @/tmp/release-create.json \
"${RELEASE_API}" > /tmp/release.json
RELEASE_ID="$(python3 -c "import json; print(json.load(open(\"/tmp/release.json\"))[\"id\"])" )"
else
cat /tmp/release.json
exit 1
fi
python3 -c "import json, pathlib, os; pathlib.Path(\"/tmp/release-update.json\").write_text(json.dumps({
\"tag_name\": os.environ[\"RELEASE_TAG\"],
\"target_commitish\": os.environ[\"GITEA_SHA\"],
\"name\": os.environ[\"RELEASE_TAG\"],
\"body\": pathlib.Path(\"dist/release-notes.md\").read_text(),
\"draft\": False,
\"prerelease\": False,
}))"
curl --fail-with-body \
-X PATCH \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
--data-binary @/tmp/release-update.json \
"${RELEASE_API}/${RELEASE_ID}" > /tmp/release.json
curl --fail-with-body \
-H "Authorization: token ${GITEA_TOKEN}" \
"${RELEASE_API}/${RELEASE_ID}/assets" > /tmp/assets.json
EXISTING_ASSET_ID="$(python3 -c "import json, os; data=json.load(open(\"/tmp/assets.json\")); target=os.environ[\"ARCHIVE_FILE\"]; print(next((str(item[\"id\"]) for item in data if item.get(\"name\") == target), \"\"))")"
if [ -n "$EXISTING_ASSET_ID" ]; then
curl --fail-with-body \
-X DELETE \
-H "Authorization: token ${GITEA_TOKEN}" \
"${RELEASE_API}/${RELEASE_ID}/assets/${EXISTING_ASSET_ID}"
fi
curl --fail-with-body \
-H "Authorization: token ${GITEA_TOKEN}" \
--data-binary @"dist/${ARCHIVE_FILE}" \
"${RELEASE_API}/${RELEASE_ID}/assets?name=${ARCHIVE_URL_NAME}"
'
+2
View File
@@ -0,0 +1,2 @@
.cache/
dist/
+95
View File
@@ -0,0 +1,95 @@
# Elsword Proton-GE Builder
Dieses Repo baut per Gitea Actions versionierte Proton-GE-Kompatibilitätstools
für Elsword mit `dxvk-git` und Steam Linux Runtime 3.0 (`sniper`).
## Was gebaut wird
- Tool-Name: `Elsword-GE-(Version)`
- Beispiel: `Elsword-GE-11-1`
- Runtime: `1628350` (`Steam Linux Runtime 3.0`)
- DXVK: standardmäßig `dxvk-git`
- Ausgabe: versionierte `.tar.xz`-Archive in `dist/`
Ältere lokal installierte Versionen wie `Elsword-GE-10-30` bleiben bestehen,
weil jede Build ihren eigenen Tool-Namen bekommt.
## Ablauf
1. Das Repo nutzt standardmäßig `GE-Proton10-34`.
2. DXVK wird aus Upstream gebaut, standardmäßig als `dxvk-git`.
3. Die GE-Basis wird auf `sniper` umgestellt.
4. Die DXVK-DLLs in Proton-GE werden ersetzt.
5. Das Ergebnis wird als eigenes Steam-Compatibility-Tool paketiert.
6. Die Gitea Action erstellt oder aktualisiert ein Release und lädt das Archiv hoch.
## Standardverhalten
Ohne Parameter baut `build.sh`:
- `GE-Proton10-34`
- mit `dxvk-git`
- als Tool `Elsword-GE-(Version)`
- mit `sniper`
## Lokaler Build
```bash
nix develop -c ./build.sh
```
Nur Archiv bauen, nicht lokal installieren:
```bash
nix develop -c ./build.sh --no-install
```
Einen bestimmten GE-Tag bauen:
```bash
nix develop -c ./build.sh --proton-tag GE-Proton11-1
```
Eigenen Tool-Namen setzen:
```bash
nix develop -c ./build.sh --tool-name Elsword-GE-test
```
## Wichtige Optionen
- `--proton-tag TAG`
- `--proton-asset x86_64|aarch64`
- `--dxvk-channel git|stable`
- `--dxvk-tag TAG`
- `--tool-prefix PREFIX`
- `--tool-name NAME`
- `--runtime-appid APPID`
- `--no-install`
## Gitea Actions
Der Workflow liegt unter:
- `.gitea/workflows/build.yml`
Er läuft bei:
- manuellem Start per `workflow_dispatch`
- automatischem Zeitplan täglich
Für Release-Uploads braucht der Workflow ein Secret:
- `GITEA_TOKEN`
Dieses Token muss Release-Schreibrechte auf das Repo haben.
## Release-Ausgabe
Nach einem Build schreibt das Skript nach `dist/`:
- das fertige `.tar.xz`-Archiv
- `package-info.env`
- `release-notes.md`
Die Gitea Action nutzt diese Dateien direkt für das Release.
Executable
+570
View File
@@ -0,0 +1,570 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CACHE_DIR="$REPO_ROOT/.cache"
DIST_DIR="$REPO_ROOT/dist"
WORK_BASE="$CACHE_DIR/work"
DXVK_CACHE_DIR="$CACHE_DIR/dxvk"
STEAM_COMPAT_DIR="${HOME}/.local/share/Steam/compatibilitytools.d"
UPSTREAM_REPO="GloriousEggroll/proton-ge-custom"
PROTON_TAG="GE-Proton10-34"
PROTON_ASSET="x86_64"
DXVK_CHANNEL="git"
DXVK_TAG="latest"
RUNTIME_APPID="1628350"
TOOL_PREFIX="Elsword-GE"
TOOL_NAME=""
KEEP_WORK=0
DXVK_SRC_OVERRIDE=""
MINGW_PTHREAD_ROOT="${MINGW_PTHREAD_ROOT:-}"
INSTALL_TOOL=1
DXVK_DESCRIBE=""
DXVK_FULL_SHA=""
DXVK_SHORT_SHA=""
usage() {
cat <<'EOF'
Usage: ./build.sh [options]
Build a custom Proton-GE compatibility tool for Elsword and replace its bundled
DXVK with a chosen DXVK build, defaulting to GE-Proton10-34 plus dxvk-git on
Steam Linux Runtime 3.0 (sniper).
Options:
--proton-tag TAG Build a specific Proton-GE release tag, default: GE-Proton10-34
--proton-asset x86_64|aarch64 Choose which Proton-GE asset to use
--dxvk-channel git|stable Choose DXVK source channel, default: git
--dxvk-tag TAG Stable DXVK tag to use when --dxvk-channel stable
--tool-prefix PREFIX Tool name prefix, default: Elsword-GE
--tool-name NAME Override final tool name completely
--runtime-appid APPID Steam Runtime appid, default: 1628350 (sniper)
--steam-compat-dir PATH Override compatibilitytools.d path
--dxvk-src PATH Use an existing dxvk checkout instead of cache
--mingw-pthread-root PATH Path with x32/libpthread.a and x64/libpthread.a
--dist-dir PATH Output directory for sendable archives
--no-install Build/package only, do not install into Steam
--keep-work Keep temporary work directory
-h, --help Show this help
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--proton-tag)
PROTON_TAG="${2:?missing value for --proton-tag}"
shift 2
;;
--proton-asset)
PROTON_ASSET="${2:?missing value for --proton-asset}"
shift 2
;;
--dxvk-channel)
DXVK_CHANNEL="${2:?missing value for --dxvk-channel}"
shift 2
;;
--dxvk-tag)
DXVK_TAG="${2:?missing value for --dxvk-tag}"
shift 2
;;
--tool-prefix)
TOOL_PREFIX="${2:?missing value for --tool-prefix}"
shift 2
;;
--tool-name)
TOOL_NAME="${2:?missing value for --tool-name}"
shift 2
;;
--runtime-appid)
RUNTIME_APPID="${2:?missing value for --runtime-appid}"
shift 2
;;
--steam-compat-dir)
STEAM_COMPAT_DIR="${2:?missing value for --steam-compat-dir}"
shift 2
;;
--dxvk-src)
DXVK_SRC_OVERRIDE="${2:?missing value for --dxvk-src}"
shift 2
;;
--mingw-pthread-root)
MINGW_PTHREAD_ROOT="${2:?missing value for --mingw-pthread-root}"
shift 2
;;
--dist-dir)
DIST_DIR="${2:?missing value for --dist-dir}"
shift 2
;;
--no-install)
INSTALL_TOOL=0
shift
;;
--keep-work)
KEEP_WORK=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done
case "$PROTON_ASSET" in
x86_64|aarch64) ;;
*)
echo "Unsupported --proton-asset: $PROTON_ASSET" >&2
exit 1
;;
esac
case "$DXVK_CHANNEL" in
git|stable) ;;
*)
echo "Unsupported --dxvk-channel: $DXVK_CHANNEL" >&2
exit 1
;;
esac
require_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "Missing required command: $1" >&2
exit 1
}
}
for cmd in \
curl \
git \
nix \
tar \
meson \
ninja \
python3 \
realpath \
glslangValidator \
x86_64-w64-mingw32-gcc \
x86_64-w64-mingw32-g++ \
i686-w64-mingw32-gcc \
i686-w64-mingw32-g++ \
wine; do
require_cmd "$cmd"
done
mkdir -p "$CACHE_DIR" "$WORK_BASE" "$DIST_DIR"
if [[ "$INSTALL_TOOL" -eq 1 ]]; then
mkdir -p "$STEAM_COMPAT_DIR"
fi
WORK_DIR="$(mktemp -d "$WORK_BASE/build.XXXXXX")"
cleanup() {
if [[ "$KEEP_WORK" -ne 1 ]]; then
rm -rf "$WORK_DIR"
fi
}
trap cleanup EXIT
say() {
printf '\n==> %s\n' "$1" >&2
}
tool_version_from_tag() {
local tag="$1"
local version="${tag#GE-Proton}"
if [[ "$version" == "$tag" ]]; then
printf '%s\n' "$tag"
else
printf '%s\n' "$version"
fi
}
get_latest_proton_tag() {
curl -fsSL "https://api.github.com/repos/${UPSTREAM_REPO}/releases/latest" \
| grep -oP '"tag_name":\s*"\K[^"]+' \
| head -n1
}
get_latest_dxvk_tag() {
curl -fsSL https://api.github.com/repos/doitsujin/dxvk/releases/latest \
| grep -oP '"tag_name":\s*"\K[^"]+' \
| head -n1
}
prepare_dxvk_cache() {
if [[ ! -d "$DXVK_CACHE_DIR/.git" ]]; then
say "Clone dxvk"
git clone --recursive https://github.com/doitsujin/dxvk.git "$DXVK_CACHE_DIR" >&2
else
say "Update dxvk cache"
git -C "$DXVK_CACHE_DIR" fetch --tags origin >&2
git -C "$DXVK_CACHE_DIR" checkout master >&2
git -C "$DXVK_CACHE_DIR" reset --hard origin/master >&2
git -C "$DXVK_CACHE_DIR" submodule update --init --recursive >&2
git -C "$DXVK_CACHE_DIR" clean -fdx >&2
fi
}
prepare_dxvk_repo() {
local source_repo ref_name checkout_dir
checkout_dir="$WORK_DIR/dxvk-src"
if [[ -n "$DXVK_SRC_OVERRIDE" ]]; then
source_repo="$DXVK_SRC_OVERRIDE"
else
prepare_dxvk_cache
source_repo="$DXVK_CACHE_DIR"
fi
if [[ "$DXVK_CHANNEL" == "stable" ]]; then
ref_name="$DXVK_TAG"
if [[ -z "$ref_name" || "$ref_name" == "latest" ]]; then
ref_name="$(get_latest_dxvk_tag)"
fi
if [[ -z "$ref_name" ]]; then
echo "Failed to resolve DXVK stable tag" >&2
exit 1
fi
else
ref_name="HEAD"
fi
say "Prepare DXVK source ($DXVK_CHANNEL)"
git clone --recursive "$source_repo" "$checkout_dir" >&2
if [[ "$DXVK_CHANNEL" == "stable" ]]; then
git -C "$checkout_dir" fetch --tags https://github.com/doitsujin/dxvk.git >&2
git -C "$checkout_dir" checkout "refs/tags/$ref_name" >&2
git -C "$checkout_dir" submodule update --init --recursive >&2
fi
echo "$checkout_dir"
}
build_dxvk() {
local dxvk_src="$1"
local dxvk_build_dir="$WORK_DIR/dxvk-out/dxvk-${DXVK_CHANNEL}"
local toolchain_dir="$WORK_DIR/toolchain"
local pthread_dir="$WORK_DIR/mingw-pthread"
DXVK_SHORT_SHA="$(git -C "$dxvk_src" rev-parse --short HEAD)"
DXVK_FULL_SHA="$(git -C "$dxvk_src" rev-parse HEAD)"
DXVK_DESCRIBE="$(git -C "$dxvk_src" describe --always --tags --dirty)"
say "Build DXVK ($DXVK_DESCRIBE)"
rm -rf "$WORK_DIR/dxvk-out" "$toolchain_dir" "$pthread_dir"
mkdir -p "$dxvk_build_dir" "$toolchain_dir" "$pthread_dir/x32" "$pthread_dir/x64"
if [[ -n "$MINGW_PTHREAD_ROOT" \
&& -f "$MINGW_PTHREAD_ROOT/x32/libpthread.a" \
&& -f "$MINGW_PTHREAD_ROOT/x64/libpthread.a" ]]; then
ln -sf "$MINGW_PTHREAD_ROOT/x32/libpthread.a" "$pthread_dir/x32/libpthread.a"
ln -sf "$MINGW_PTHREAD_ROOT/x64/libpthread.a" "$pthread_dir/x64/libpthread.a"
else
local mcfg32 mcfg64
mcfg32="$(NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix path-info --impure nixpkgs#pkgsCross.mingw32.windows.mcfgthreads)"
mcfg64="$(NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix path-info --impure nixpkgs#pkgsCross.mingwW64.windows.mcfgthreads)"
ln -sf "$mcfg32/lib/libmcfgthread.a" "$pthread_dir/x32/libpthread.a"
ln -sf "$mcfg64/lib/libmcfgthread.a" "$pthread_dir/x64/libpthread.a"
fi
cat > "$toolchain_dir/x86_64-w64-mingw32-gcc" <<EOF
#!/usr/bin/env bash
exec "$(command -v x86_64-w64-mingw32-gcc)" "\$@" -L"$pthread_dir/x64" -lmcfgthread -lpthread
EOF
cat > "$toolchain_dir/x86_64-w64-mingw32-g++" <<EOF
#!/usr/bin/env bash
exec "$(command -v x86_64-w64-mingw32-g++)" "\$@" -L"$pthread_dir/x64" -lmcfgthread -lpthread
EOF
cat > "$toolchain_dir/i686-w64-mingw32-gcc" <<EOF
#!/usr/bin/env bash
exec "$(command -v i686-w64-mingw32-gcc)" "\$@" -L"$pthread_dir/x32" -lmcfgthread -lpthread
EOF
cat > "$toolchain_dir/i686-w64-mingw32-g++" <<EOF
#!/usr/bin/env bash
exec "$(command -v i686-w64-mingw32-g++)" "\$@" -L"$pthread_dir/x32" -lmcfgthread -lpthread
EOF
chmod +x \
"$toolchain_dir/x86_64-w64-mingw32-gcc" \
"$toolchain_dir/x86_64-w64-mingw32-g++" \
"$toolchain_dir/i686-w64-mingw32-gcc" \
"$toolchain_dir/i686-w64-mingw32-g++"
cat > "$toolchain_dir/build-win64-mcfg.txt" <<EOF
[binaries]
c = '$toolchain_dir/x86_64-w64-mingw32-gcc'
cpp = '$toolchain_dir/x86_64-w64-mingw32-g++'
ar = '$(command -v x86_64-w64-mingw32-ar)'
strip = '$(command -v x86_64-w64-mingw32-strip)'
windres = '$(command -v x86_64-w64-mingw32-windres)'
[properties]
needs_exe_wrapper = true
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
EOF
cat > "$toolchain_dir/build-win32-mcfg.txt" <<EOF
[binaries]
c = '$toolchain_dir/i686-w64-mingw32-gcc'
cpp = '$toolchain_dir/i686-w64-mingw32-g++'
ar = '$(command -v i686-w64-mingw32-ar)'
strip = '$(command -v i686-w64-mingw32-strip)'
windres = '$(command -v i686-w64-mingw32-windres)'
[properties]
needs_exe_wrapper = true
[host_machine]
system = 'windows'
cpu_family = 'x86'
cpu = 'x86'
endian = 'little'
EOF
(
cd "$dxvk_src"
meson setup --cross-file "$toolchain_dir/build-win64-mcfg.txt" \
--buildtype release \
--prefix "$dxvk_build_dir" \
--strip \
--bindir x64 \
--libdir x64 \
-Db_ndebug=if-release \
"$dxvk_build_dir/build.64" >&2
ninja -C "$dxvk_build_dir/build.64" install >&2
meson setup --cross-file "$toolchain_dir/build-win32-mcfg.txt" \
--buildtype release \
--prefix "$dxvk_build_dir" \
--strip \
--bindir x32 \
--libdir x32 \
-Db_ndebug=if-release \
"$dxvk_build_dir/build.32" >&2
ninja -C "$dxvk_build_dir/build.32" install >&2
)
rm -f "$dxvk_build_dir/x64/"*.a "$dxvk_build_dir/x32/"*.a
rm -rf "$dxvk_build_dir/build.64" "$dxvk_build_dir/build.32"
echo "$DXVK_SHORT_SHA"
}
download_proton() {
local proton_tag="$1"
local asset_file
local proton_tarball
local proton_url
if [[ "$PROTON_ASSET" == "aarch64" ]]; then
asset_file="${proton_tag}-aarch64.tar.gz"
else
asset_file="${proton_tag}.tar.gz"
fi
proton_tarball="$CACHE_DIR/${asset_file}"
proton_url="https://github.com/${UPSTREAM_REPO}/releases/download/${proton_tag}/${asset_file}"
if [[ ! -f "$proton_tarball" ]]; then
say "Download Proton-GE ${proton_tag} (${PROTON_ASSET})"
curl -fL "$proton_url" -o "$proton_tarball"
else
say "Reuse cached Proton tarball"
fi
echo "$proton_tarball"
}
replace_tree() {
local source_dir="$1"
local target_dir="$2"
mkdir -p "$target_dir"
for dll in d3d8.dll d3d9.dll d3d10core.dll d3d11.dll dxgi.dll openvr_api_dxvk.dll; do
if [[ -f "$source_dir/$dll" ]]; then
cp -f "$source_dir/$dll" "$target_dir/$dll"
fi
done
}
replace_base_dlls() {
local source_dir="$1"
local target_dir="$2"
mkdir -p "$target_dir"
for dll in d3d8.dll d3d9.dll d3d10core.dll d3d11.dll ddraw.dll dxgi.dll; do
if [[ -f "$source_dir/$dll" ]]; then
cp -f "$source_dir/$dll" "$target_dir/$dll"
fi
done
}
patch_tool() {
local tool_root="$1"
local tool_name="$2"
local proton_tag="$3"
local dxvk_src="$4"
local dxvk_short_dir="$WORK_DIR/dxvk-out/dxvk-${DXVK_CHANNEL}"
local timestamp
timestamp="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
say "Replace DXVK payload"
replace_tree "$dxvk_short_dir/x64" "$tool_root/files/lib/wine/dxvk/x86_64-windows"
replace_tree "$dxvk_short_dir/x32" "$tool_root/files/lib/wine/dxvk/i386-windows"
replace_base_dlls "$dxvk_short_dir/x64" "$tool_root/files/lib/wine/x86_64-windows"
replace_base_dlls "$dxvk_short_dir/x32" "$tool_root/files/lib/wine/i386-windows"
replace_base_dlls "$dxvk_short_dir/x64" "$tool_root/files/share/default_pfx/drive_c/windows/system32"
replace_base_dlls "$dxvk_short_dir/x32" "$tool_root/files/share/default_pfx/drive_c/windows/syswow64"
chmod u+w \
"$tool_root/files/lib/wine/dxvk/version" \
"$tool_root/version" \
"$tool_root/toolmanifest.vdf" 2>/dev/null || true
printf '%s dxvk (%s)\n' "$DXVK_FULL_SHA" "$DXVK_DESCRIBE" > "$tool_root/files/lib/wine/dxvk/version"
printf '%s %s\n' "$(date +%s)" "$tool_name" > "$tool_root/version"
cat > "$tool_root/compatibilitytool.vdf" <<EOF
"compatibilitytools"
{
"compat_tools"
{
"${tool_name}"
{
"install_path" "."
"display_name" "${tool_name}"
"from_oslist" "windows"
"to_oslist" "linux"
}
}
}
EOF
cat > "$tool_root/toolmanifest.vdf" <<EOF
"manifest"
{
"version" "2"
"commandline" "/proton %verb%"
"require_tool_appid" "${RUNTIME_APPID}"
"use_sessions" "1"
"compatmanager_layer_name" "proton"
}
EOF
cat > "$tool_root/BUILD-INFO.txt" <<EOF
Tool name: ${tool_name}
Built at: ${timestamp}
Upstream repo: ${UPSTREAM_REPO}
Proton-GE tag: ${proton_tag}
Proton asset: ${PROTON_ASSET}
DXVK source: ${dxvk_src}
DXVK commit: ${DXVK_FULL_SHA}
DXVK describe: ${DXVK_DESCRIBE}
DXVK channel: ${DXVK_CHANNEL}
Runtime appid: ${RUNTIME_APPID}
EOF
}
install_tool() {
local tool_root="$1"
local tool_name="$2"
local destination="$STEAM_COMPAT_DIR/$tool_name"
say "Install tool"
rm -rf "$destination"
mv "$tool_root" "$destination"
echo "$destination"
}
package_tool() {
local tool_root="$1"
local tool_name="$2"
local archive_path="$DIST_DIR/${tool_name}-dxvk-${DXVK_SHORT_SHA}.tar.xz"
say "Create shareable archive"
mkdir -p "$DIST_DIR"
rm -f "$archive_path"
tar -C "$(dirname "$tool_root")" -cJf "$archive_path" "$(basename "$tool_root")"
echo "$archive_path"
}
write_dist_metadata() {
local archive_path="$1"
local tool_name="$2"
local proton_tag="$3"
mkdir -p "$DIST_DIR"
cat > "$DIST_DIR/package-info.env" <<EOF
TOOL_NAME=${tool_name}
PROTON_TAG=${proton_tag}
PROTON_VERSION=$(tool_version_from_tag "$proton_tag")
PROTON_ASSET=${PROTON_ASSET}
DXVK_CHANNEL=${DXVK_CHANNEL}
DXVK_TAG=${DXVK_TAG}
DXVK_COMMIT=${DXVK_FULL_SHA}
DXVK_DESCRIBE=${DXVK_DESCRIBE}
RUNTIME_APPID=${RUNTIME_APPID}
ARCHIVE_FILE=$(basename "$archive_path")
RELEASE_TAG=${tool_name}
EOF
cat > "$DIST_DIR/release-notes.md" <<EOF
# ${tool_name}
- Proton-GE: \`${proton_tag}\`
- DXVK: \`${DXVK_DESCRIBE}\`
- Runtime appid: \`${RUNTIME_APPID}\`
- Archive: \`$(basename "$archive_path")\`
This release is built for Elsword and uses Steam Linux Runtime 3.0 (sniper).
EOF
}
if [[ -z "$TOOL_NAME" ]]; then
TOOL_NAME="${TOOL_PREFIX}-$(tool_version_from_tag "$PROTON_TAG")"
fi
DXVK_SRC="$(prepare_dxvk_repo)"
build_dxvk "$DXVK_SRC" >/dev/null
PROTON_TARBALL="$(download_proton "$PROTON_TAG")"
say "Extract Proton-GE"
mkdir -p "$WORK_DIR/proton"
tar -xf "$PROTON_TARBALL" -C "$WORK_DIR/proton"
TOOL_ROOT="$(find "$WORK_DIR/proton" -mindepth 1 -maxdepth 1 -type d | head -n1)"
if [[ -z "$TOOL_ROOT" ]]; then
echo "Could not find extracted Proton tool root" >&2
exit 1
fi
patch_tool "$TOOL_ROOT" "$TOOL_NAME" "$PROTON_TAG" "$DXVK_SRC"
ARCHIVE_PATH="$(package_tool "$TOOL_ROOT" "$TOOL_NAME")"
write_dist_metadata "$ARCHIVE_PATH" "$TOOL_NAME" "$PROTON_TAG"
if [[ "$INSTALL_TOOL" -eq 1 ]]; then
INSTALLED_PATH="$(install_tool "$TOOL_ROOT" "$TOOL_NAME")"
fi
say "Done"
printf 'Archive: %s\n' "$ARCHIVE_PATH"
if [[ "$INSTALL_TOOL" -eq 1 ]]; then
printf 'Installed: %s\n' "$INSTALLED_PATH"
fi
printf 'Proton-GE: %s (%s)\n' "$PROTON_TAG" "$PROTON_ASSET"
printf 'DXVK: %s\n' "$DXVK_DESCRIBE"
printf 'Runtime: %s\n' "$RUNTIME_APPID"
if [[ "$INSTALL_TOOL" -eq 1 ]]; then
printf '\nRestart Steam and choose "%s" as compatibility tool.\n' "$TOOL_NAME"
else
printf '\nShare the archive or unpack it into compatibilitytools.d on another system.\n'
fi
Generated
+27
View File
@@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1782467914,
"narHash": "sha256-pGvFkM8N0xEkIIXDe5YYfbEAvHrk4IxBrjB/x8OomhE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e73de5be04e0eff4190a1432b946d469c794e7b4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
+27
View File
@@ -0,0 +1,27 @@
{
description = "Build versioned Elsword Proton-GE tools with DXVK and sniper runtime";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
in
{
devShells.${system}.default = pkgs.mkShell {
packages = with pkgs; [
curl
git
glslang
meson
ninja
pkg-config
python3
wineWow64Packages.stable
pkgsCross.mingw32.stdenv.cc
pkgsCross.mingwW64.stdenv.cc
];
};
};
}