mega big fix for shaders

This commit is contained in:
bryanthaboi
2026-08-26 10:29:16 -04:00
parent 40075ae469
commit 522d8cecf3
14 changed files with 391 additions and 30 deletions
+121 -3
View File
@@ -143,7 +143,7 @@ jobs:
linux-arm64:
name: build Linux arm64 AppImage
needs: [version, love-payload]
needs: [version, love-payload, shaderfx-bridge]
# GitHub's free arm64 runner for public repos. It has to be arm64: the
# AppImage compiles LÖVE natively inside a Debian bullseye arm64
# container, and the qemu-emulated alternative takes hours.
@@ -155,13 +155,22 @@ jobs:
with:
name: gen1recomp-release-love
path: .bazinga/work
- name: Download the ShaderFX bridge
uses: actions/download-artifact@v8
with:
name: shaderfx-bridge-linux-arm64
path: dist/native/linux-arm64
- name: Build Linux arm64 AppImage
env:
SHADERFX_BRIDGE_REQUIRED: "1"
run: |
set -euo pipefail
scripts/build_linux_arm64.sh \
--version "${{ needs.version.outputs.version }}" \
--game-love .bazinga/work/game.love
- name: Verify the AppImage is self-contained and bullseye-compatible
env:
SHADERFX_BRIDGE_REQUIRED: "1"
run: bash scripts/linux-arm64/verify_appimage.sh "dist/linux-arm64/gen1recomp-${{ needs.version.outputs.version }}-linux-arm64.AppImage"
- name: Upload Linux arm64 release
uses: actions/upload-artifact@v7
@@ -175,7 +184,7 @@ jobs:
linux-flatpak:
name: build Linux Flatpak
needs: [version, love-payload]
needs: [version, love-payload, shaderfx-bridge]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
@@ -189,7 +198,14 @@ jobs:
with:
name: gen1recomp-release-love
path: .bazinga/work
- name: Download the ShaderFX bridge
uses: actions/download-artifact@v8
with:
name: shaderfx-bridge-linux-x64
path: dist/native/linux-x64
- name: Build Flatpak bundle
env:
SHADERFX_BRIDGE_REQUIRED: "1"
run: |
set -euo pipefail
scripts/build_flatpak.sh \
@@ -318,8 +334,82 @@ jobs:
if-no-files-found: error
retention-days: 1
shaderfx-bridge:
name: build ShaderFX bridge (${{ matrix.plat }})
needs: version
strategy:
fail-fast: false
matrix:
include:
- plat: win-x64
runs-on: windows-2022
lib: librashader_bridge.dll
- plat: mac
runs-on: macos-latest
lib: liblibrashader_bridge.dylib
- plat: linux-x64
runs-on: ubuntu-24.04
lib: liblibrashader_bridge.so
glibc_triple: x86_64-unknown-linux-gnu.2.17
- plat: linux-arm64
runs-on: ubuntu-24.04-arm
lib: liblibrashader_bridge.so
glibc_triple: aarch64-unknown-linux-gnu.2.17
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v7
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry and build dir
uses: Swatinem/rust-cache@v2
with:
workspaces: tools/shaderfx-bridge
key: ${{ matrix.plat }}-${{ matrix.glibc_triple }}
- name: Build the bridge
shell: bash
env:
PLAT: ${{ matrix.plat }}
LIB: ${{ matrix.lib }}
GLIBC_TRIPLE: ${{ matrix.glibc_triple }}
run: |
set -euo pipefail
out="dist/native/$PLAT"
mkdir -p "$out"
cd tools/shaderfx-bridge
case "$PLAT" in
win-x64)
rustup target add x86_64-pc-windows-msvc
cargo build --release --target x86_64-pc-windows-msvc
cp "target/x86_64-pc-windows-msvc/release/$LIB" "$GITHUB_WORKSPACE/$out/$LIB"
;;
mac)
rustup target add x86_64-apple-darwin aarch64-apple-darwin
cargo build --release --target x86_64-apple-darwin
cargo build --release --target aarch64-apple-darwin
lipo -create -output "$GITHUB_WORKSPACE/$out/$LIB" \
"target/x86_64-apple-darwin/release/$LIB" \
"target/aarch64-apple-darwin/release/$LIB"
lipo -info "$GITHUB_WORKSPACE/$out/$LIB"
;;
linux-x64|linux-arm64)
pipx install cargo-zigbuild
pipx inject cargo-zigbuild ziglang
triple="$GLIBC_TRIPLE"
rustup target add "${triple%%.*}"
cargo zigbuild --release --target "$triple"
cp "target/${triple%%.*}/release/$LIB" "$GITHUB_WORKSPACE/$out/$LIB"
;;
esac
- name: Upload the bridge
uses: actions/upload-artifact@v7
with:
name: shaderfx-bridge-${{ matrix.plat }}
path: dist/native/${{ matrix.plat }}/${{ matrix.lib }}
if-no-files-found: error
retention-days: 1
release:
needs: [version, love-payload, xbox-uwp, linux-arm64, linux-flatpak, native-tls-win]
needs: [version, love-payload, xbox-uwp, linux-arm64, linux-flatpak, native-tls-win, shaderfx-bridge]
runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }}
steps:
@@ -341,6 +431,28 @@ jobs:
name: gen1tls-win-x64
path: dist/native/win-x64
- name: Download ShaderFX bridge libraries
uses: actions/download-artifact@v8
with:
pattern: shaderfx-bridge-*
path: dist/native
- name: Flatten the ShaderFX bridge artifact layout
run: |
set -euo pipefail
shopt -s nullglob
for d in dist/native/shaderfx-bridge-*/; do
d="${d%/}"
plat="${d#dist/native/shaderfx-bridge-}"
mkdir -p "dist/native/$plat"
for f in "$d"/*; do mv "$f" "dist/native/$plat/"; done
rmdir "$d"
done
for plat in mac win-x64 linux-x64 linux-arm64; do
ls "dist/native/$plat" >/dev/null \
|| { echo "::error::no ShaderFX bridge staged for $plat"; exit 1; }
done
ls -lR dist/native
# The same game.love the arm64 AppImage and Xbox UWP builds fused, so
# every release asset ships one identical payload (build.sh's own pack
# would omit PATCH_NOTES.md and mobile/ios/app-repo.json).
@@ -390,6 +502,7 @@ jobs:
- name: Build macOS + Windows + Linux
env:
GEN1TLS_DLL: ${{ github.workspace }}/dist/native/win-x64/gen1tls.dll
SHADERFX_BRIDGE_REQUIRED: "1"
run: |
set -euo pipefail
# Sign in-build (identity auto-detected from the temp keychain);
@@ -404,6 +517,8 @@ jobs:
--game-love dist/payload/game.love
unzip -l dist/win/gen1recomp-win64.zip | grep -F gen1tls.dll \
|| { echo "::error::Windows zip is missing gen1tls.dll"; exit 1; }
unzip -l dist/win/gen1recomp-win64.zip | grep -F librashader_bridge.dll \
|| { echo "::error::Windows zip is missing librashader_bridge.dll"; exit 1; }
- name: Materialize Android release signing key
env:
@@ -461,6 +576,8 @@ jobs:
--version "${{ needs.version.outputs.version }}"
- name: Build Anbernic RG34XXSP port
env:
SHADERFX_BRIDGE_REQUIRED: "1"
run: |
set -euo pipefail
# Self-contained aarch64 PortMaster-style pack; pulls the LÖVE 11.5
@@ -474,6 +591,7 @@ jobs:
# builds, while this explicit local override keeps CI source-aligned.
GEN1RECOMP_SOURCE_DIR: ${{ github.workspace }}
GEN1RECOMP_RELEASE_TAG: v${{ needs.version.outputs.version }}
SHADERFX_BRIDGE_REQUIRED: "1"
run: |
set -euo pipefail
# Same aarch64 PortMaster-style pack for Linux ARM SBC PortMaster. The build
+5 -5
View File
@@ -1,19 +1,19 @@
# Gen1Recomp
A native LÖVE2D recreation of Poke Red, Blue and Yellow. The engine and map
behavior are hand-written Lua; game data and graphics are decoded from a ROM
supplied by the player.
A native LÖVE2D recreation of Poke Red, Blue, Gold, Silver, and Crystal. The
engine and map behavior are hand-written Lua; game data and graphics are
decoded from a ROM supplied by the player.
And before you say, "that's not a recomp", you're wrong. Recomp is an acronym. ***Reverse Engineering Causes Obsessive Mental Problems***
[Click Here for the AI Use Disclosure!](AIDisclosure.md)
> [!CAUTION]
> **We are NOT affiliated with the website `gen1recomp[.]com`** That website is not run by this project, was not authorized by us, and we have no idea who operates it. It is impersonating this project; do not download anything from it, and treat anything it hosts or claims as untrustworthy. Even if the site currently links back to this repository, the people behind it can change its content at any time, so nothing on it should ever be trusted. This GitHub repository and the Discord linked below are the only official sources for this project. Also, as I assumed would eventually happen, the idiot that made that website now pumped it full of adware. Please stay away from that website.
> **We are NOT affiliated with the website `gen1recomp[.]com`** That website is not run by this project, was not authorized by us, and we have no idea who operates it. It is impersonating this project; do not download anything from it, and treat anything it hosts or claims as untrustworthy. Even if the site currently links back to this repository, the people behind it can change its content at any time, so nothing on it should ever be trusted. This GitHub repository, the Discord, and https://gen1re.com are the only official sources for this project. Also, as I assumed would eventually happen, the idiot that made that website now pumped it full of adware. Please stay away from that website.
<p align="center"><img src="https://raw.githubusercontent.com/bryanthaboi/gen1recomp/refs/heads/dev/assets/logo/logo.png"></p>
**SUPPORT / ANNOUNCEMENTS / MODS:** [Discord](https://bois.icu)
# [SUPPORT / ANNOUNCEMENTS / MODS ALL FOUND ON THE DISCORD](https://bois.icu)
<p align="center">
+14
View File
@@ -192,6 +192,20 @@ chmod +x "$PORT_ROOT/$PORT_DIR_NAME/bin/love.aarch64"
cp "$LOVE_LIB" "$LUAJIT_LIB" "$MODPLUG_LIB" "$OGG_LIB" \
"$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64/"
BRIDGE_LIB="liblibrashader_bridge.so"
BRIDGE_SRC="${SHADERFX_BRIDGE_LINUX_ARM64:-}"
if [ -z "$BRIDGE_SRC" ] && [ -f "$ROOT/dist/native/linux-arm64/$BRIDGE_LIB" ]; then
BRIDGE_SRC="$ROOT/dist/native/linux-arm64/$BRIDGE_LIB"
fi
if [ -n "$BRIDGE_SRC" ] && [ -f "$BRIDGE_SRC" ]; then
cp "$BRIDGE_SRC" "$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64/$BRIDGE_LIB"
say "bundled $BRIDGE_LIB for SHADER FX preset conversion"
elif [ "${SHADERFX_BRIDGE_REQUIRED:-}" = "1" ]; then
fail "$BRIDGE_LIB not found: set SHADERFX_BRIDGE_LINUX_ARM64 or stage it at dist/native/linux-arm64/$BRIDGE_LIB"
else
warn "$BRIDGE_LIB not found: this port can run converted presets but not CONVERT new ones"
fi
# Drop a short license pointer for the bundled LÖVE bits.
cat > "$PORT_ROOT/$PORT_DIR_NAME/licenses/LICENSE.love2d.txt" <<'EOF'
This port bundles the LÖVE 11.5 aarch64 runtime from PortMaster
+14
View File
@@ -156,6 +156,20 @@ chmod +x "$PORT_ROOT/$PORT_DIR_NAME/bin/love.aarch64"
cp "$LOVE_LIB" "$LUAJIT_LIB" "$MODPLUG_LIB" "$OGG_LIB" \
"$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64/"
BRIDGE_LIB="liblibrashader_bridge.so"
BRIDGE_SRC="${SHADERFX_BRIDGE_LINUX_ARM64:-}"
if [ -z "$BRIDGE_SRC" ] && [ -f "$ROOT/dist/native/linux-arm64/$BRIDGE_LIB" ]; then
BRIDGE_SRC="$ROOT/dist/native/linux-arm64/$BRIDGE_LIB"
fi
if [ -n "$BRIDGE_SRC" ] && [ -f "$BRIDGE_SRC" ]; then
cp "$BRIDGE_SRC" "$PORT_ROOT/$PORT_DIR_NAME/libs.aarch64/$BRIDGE_LIB"
say "bundled $BRIDGE_LIB for SHADER FX preset conversion"
elif [ "${SHADERFX_BRIDGE_REQUIRED:-}" = "1" ]; then
fail "$BRIDGE_LIB not found: set SHADERFX_BRIDGE_LINUX_ARM64 or stage it at dist/native/linux-arm64/$BRIDGE_LIB"
else
warn "$BRIDGE_LIB not found: this port can run converted presets but not CONVERT new ones"
fi
# Drop a short license pointer for the bundled LÖVE bits.
cat > "$PORT_ROOT/$PORT_DIR_NAME/licenses/LICENSE.love2d.txt" <<'EOF'
This port bundles the LÖVE 11.5 aarch64 runtime from PortMaster
+42 -3
View File
@@ -214,12 +214,51 @@ finally the bare name handed to the system loader. Per-OS names are
`librashader_bridge.dylib` (macOS), and `liblibrashader_bridge.so` or
`librashader_bridge.so` (Linux and Android). Android resolves the bare name
because the `.so` ships as an ordinary `jniLibs` entry, so `dlopen` finds it
without a path. The desktop path is still a developer build sitting in cargo's
output directory; nothing packages it next to a shipped game yet.
`ShaderFX.canConvert()` reports whether the library resolved on this machine,
without a path. `ShaderFX.canConvert()` reports whether the library resolved on this machine,
and `ShaderFX.bridgeError()` says why not. Activating an already-converted
preset never needs any of this.
**Shipped builds carry it.** `cargo` only ever emits the host's library, and
the macOS release runner packs macOS, Windows and Linux in a single
`scripts/build.sh all`, so release CI cross-builds one cdylib per platform on
its own native runner (the `shaderfx-bridge` matrix in
`.github/workflows/release.yml`) and stages it at `dist/native/<plat>/`.
`bundle_shader_bridge` in `scripts/build.sh` reads that directory, and
`SHADERFX_BRIDGE_<PLAT>` overrides it. Where each artifact puts the library:
| Artifact | Location | Found by |
| --- | --- | --- |
| macOS .app | `Contents/MacOS/` | source base directory |
| Windows zip | next to `love.exe` | source base directory |
| Linux AppImage (both arches) | AppDir root, next to `game.love` | source base directory |
| Flatpak | `/app/share/gen1recomp/` | source base directory |
| RG34XXSP / ARM SBC ports | `libs.aarch64/` | bare name via `LD_LIBRARY_PATH` |
| Android APK | `jniLibs/<abi>/` | bare name |
| iOS | linked into the binary | `ffi.C` |
The macOS library is a universal binary, because LÖVE.app is: an arm64-only
bridge would fail `ffi.load` on Intel Macs the moment they hit CONVERT. The
two Linux libraries are built with `cargo-zigbuild` against
`{x86_64,aarch64}-unknown-linux-gnu.2.17`, below every consumer: the upstream
x86_64 LÖVE AppImage floors at GLIBC_2.29, the arm64 AppImage's own gate is
GLIBC_2.31, PortMaster's aarch64 LÖVE runtime floors at GLIBC_2.17, and ArkOS
is glibc 2.30. 2.17 is the oldest glibc with aarch64 support, so one library
per arch clears the whole fleet. `scripts/linux-arm64/verify_appimage.sh`
discovers every ELF object in the AppDir rather than globbing `bin/love` and
`lib/*.so*`, so the bridge is held to the same floor, resolution and
dlopen-not-linked rules as everything else, then dlopened once to prove
relocations and constructors run.
Setting `SHADERFX_BRIDGE_REQUIRED=1` turns the packagers' "not found" warning
into a hard error. Release CI sets it on every job that ships a bridge, so a
release cannot silently go out without one again.
**Where CONVERT is unavailable.** Switch and Xbox UWP ship without a bridge.
The Switch build uses devkitPro's toolchain, which is not a rustc target; the
UWP appcontainer is unproven for loading a desktop MSVC DLL. On both, presets
converted elsewhere still activate and run normally, and `ShaderFX.canConvert()`
returns false with `ShaderFX.bridgeError()` explaining why.
**Statically linked bridges.** On iOS there is no loadable library at all:
the bridge is linked straight into the app binary, so its symbols live in the
main image and are reachable only through `ffi.C`. The candidate list is empty
+7
View File
@@ -43,6 +43,9 @@ modules:
EOF
- chmod +x /app/bin/gen1recomp
- install -Dm644 game.love /app/share/gen1recomp/game.love
# BRIDGE-BEGIN
- install -Dm755 liblibrashader_bridge.so /app/share/gen1recomp/liblibrashader_bridge.so
# BRIDGE-END
- install -Dm644 com.theboisclub.gen1recomp.desktop /app/share/applications/com.theboisclub.gen1recomp.desktop
- install -Dm644 com.theboisclub.gen1recomp.metainfo.xml /app/share/metainfo/com.theboisclub.gen1recomp.metainfo.xml
- install -Dm644 icon.png /app/share/icons/hicolor/512x512/apps/com.theboisclub.gen1recomp.png
@@ -53,6 +56,10 @@ modules:
dest-filename: love-x86_64.AppImage
- type: file
path: game.love
# BRIDGE-BEGIN
- type: file
path: liblibrashader_bridge.so
# BRIDGE-END
- type: file
path: com.theboisclub.gen1recomp.metainfo.xml
- type: file
+40 -14
View File
@@ -170,27 +170,53 @@ make_ico() { # $1 = output .ico path
# --------------------------------------------------------------- macOS
# ShaderFX's librashader bridge. Only the CONVERT action needs it, so a build
# without it still runs presets that were converted elsewhere.
# SHADERFX_BRIDGE points at a prebuilt library; otherwise cargo builds it.
# SHADERFX_BRIDGE_<PLAT> or dist/native/<plat>/ points at a prebuilt library;
# otherwise cargo builds it, host platform only.
shader_bridge_host_plat() {
case "$(uname -s)-$(uname -m)" in
Darwin-*) printf 'mac' ;;
Linux-x86_64) printf 'linux-x64' ;;
Linux-aarch64|Linux-arm64) printf 'linux-arm64' ;;
*) printf '' ;;
esac
}
bundle_shader_bridge() {
local dest="$1" name="$2"
local src="${SHADERFX_BRIDGE:-}"
local dest="$1" name="$2" plat="$3"
local crate="$ROOT/tools/shaderfx-bridge"
if [ -z "$src" ] && [ -f "$crate/target/release/$name" ]; then
src="$crate/target/release/$name"
local src="" var
[ -n "$plat" ] || fail "bundle_shader_bridge: no platform key for $name"
var="SHADERFX_BRIDGE_$(printf '%s' "$plat" | tr 'a-z-' 'A-Z_')"
eval "src=\${$var:-}"
if [ -z "$src" ] && [ -f "$DIST/native/$plat/$name" ]; then
src="$DIST/native/$plat/$name"
fi
if [ -z "$src" ] && command -v cargo >/dev/null 2>&1; then
say "building the ShaderFX bridge with cargo"
if (cd "$crate" && cargo build --release >/dev/null 2>&1); then
if [ -z "$src" ] && [ -n "${SHADERFX_BRIDGE:-}" ]; then
src="$SHADERFX_BRIDGE"
fi
if [ -z "$src" ] && [ "$plat" = "$(shader_bridge_host_plat)" ]; then
if [ -f "$crate/target/release/$name" ]; then
src="$crate/target/release/$name"
elif command -v cargo >/dev/null 2>&1; then
say "building the ShaderFX bridge with cargo"
if (cd "$crate" && cargo build --release >/dev/null 2>&1); then
src="$crate/target/release/$name"
fi
fi
fi
if [ -n "$src" ] && [ -f "$src" ]; then
mkdir -p "$dest"
cp "$src" "$dest/$name"
say "bundled $name for SHADER FX preset conversion"
else
warn "$name not found: this build can run converted presets but not CONVERT new ones (set SHADERFX_BRIDGE or install cargo)"
say "bundled $name for SHADER FX preset conversion ($plat)"
return 0
fi
if [ "${SHADERFX_BRIDGE_REQUIRED:-}" = "1" ]; then
fail "$name ($plat) not found: set $var or stage it at dist/native/$plat/$name"
fi
warn "$name not found: this build can run converted presets but not CONVERT new ones (set $var or install cargo)"
}
build_mac() {
@@ -205,7 +231,7 @@ build_mac() {
# drop any bundled placeholder .love and fuse ours in
find "$out_app/Contents/Resources" -maxdepth 1 -name '*.love' -delete
cp "$LOVE_FILE" "$out_app/Contents/Resources/game.love"
bundle_shader_bridge "$out_app/Contents/MacOS" "liblibrashader_bridge.dylib"
bundle_shader_bridge "$out_app/Contents/MacOS" "liblibrashader_bridge.dylib" mac
local plist="$out_app/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleName $APP_NAME" "$plist" 2>/dev/null \
@@ -322,7 +348,7 @@ build_win() {
warn "gen1tls.dll not found: Windows zip will not support wss:// (set GEN1TLS_DLL or build native/tls_dial)"
fi
bundle_shader_bridge "$out_dir" "librashader_bridge.dll"
bundle_shader_bridge "$out_dir" "librashader_bridge.dll" win-x64
# The exe's icon lives in love.exe's PE resources, so it must be patched
# BEFORE the .love is appended: peresed rewrites the whole file and would
@@ -419,7 +445,7 @@ build_linux() {
unsquashfs -q -no-xattrs -o "$sfs_offset" -d "$appdir" "$love_appimage" >/dev/null
cp "$LOVE_FILE" "$appdir/game.love"
bundle_shader_bridge "$appdir" "liblibrashader_bridge.so"
bundle_shader_bridge "$appdir" "liblibrashader_bridge.so" linux-x64
# Replace LÖVE's own desktop entry rather than keeping it: it says
# Name=LÖVE / Icon=love, which is what appimaged, app menus and file
+24 -1
View File
@@ -86,7 +86,25 @@ text = re.sub(
pathlib.Path(dst).write_text(text, encoding="utf-8")
PY
cp "$ROOT/flatpak/$APP_ID.yml" "$CACHE/$APP_ID.yml"
BRIDGE_LIB="liblibrashader_bridge.so"
BRIDGE_SRC="${SHADERFX_BRIDGE_LINUX_X64:-}"
if [ -z "$BRIDGE_SRC" ] && [ -f "$ROOT/dist/native/linux-x64/$BRIDGE_LIB" ]; then
BRIDGE_SRC="$ROOT/dist/native/linux-x64/$BRIDGE_LIB"
fi
if [ -z "$BRIDGE_SRC" ] && [ -f "$ROOT/tools/shaderfx-bridge/target/release/$BRIDGE_LIB" ]; then
BRIDGE_SRC="$ROOT/tools/shaderfx-bridge/target/release/$BRIDGE_LIB"
fi
rm -f "$CACHE/$BRIDGE_LIB"
if [ -n "$BRIDGE_SRC" ] && [ -f "$BRIDGE_SRC" ]; then
cp "$BRIDGE_SRC" "$CACHE/$BRIDGE_LIB"
cp "$ROOT/flatpak/$APP_ID.yml" "$CACHE/$APP_ID.yml"
say "staged $BRIDGE_LIB for SHADER FX preset conversion"
elif [ "${SHADERFX_BRIDGE_REQUIRED:-}" = "1" ]; then
fail "$BRIDGE_LIB not found: set SHADERFX_BRIDGE_LINUX_X64 or stage it at dist/native/linux-x64/$BRIDGE_LIB"
else
warn "$BRIDGE_LIB not found: this bundle can run converted presets but not CONVERT new ones"
sed '/# BRIDGE-BEGIN/,/# BRIDGE-END/d' "$ROOT/flatpak/$APP_ID.yml" > "$CACHE/$APP_ID.yml"
fi
say "installing Freedesktop runtime (no-op if present)"
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo || true
@@ -116,5 +134,10 @@ if command -v sha256sum >/dev/null 2>&1; then
else
printf '%s %s\n' "$(shasum -a 256 "$OUT" | awk '{print $1}')" "$(basename "$OUT")" > "$OUT.sha256"
fi
if [ -f "$CACHE/$BRIDGE_LIB" ]; then
[ -f "$BUILD_DIR/files/share/gen1recomp/$BRIDGE_LIB" ] \
|| fail "$BRIDGE_LIB was staged but is missing from the built /app/share/gen1recomp"
say "verified $BRIDGE_LIB in the Flatpak"
fi
say "Flatpak build: $OUT ($(du -h "$OUT" | cut -f1))"
say "sha256: $(cut -d' ' -f1 "$OUT.sha256")"
+15
View File
@@ -100,6 +100,21 @@ then
fi
cp "$GAME_LOVE" "$IN_DIR/game.love"
BRIDGE_LIB="liblibrashader_bridge.so"
BRIDGE_SRC="${SHADERFX_BRIDGE_LINUX_ARM64:-}"
if [ -z "$BRIDGE_SRC" ] && [ -f "$ROOT/dist/native/linux-arm64/$BRIDGE_LIB" ]; then
BRIDGE_SRC="$ROOT/dist/native/linux-arm64/$BRIDGE_LIB"
fi
rm -f "$IN_DIR/$BRIDGE_LIB"
if [ -n "$BRIDGE_SRC" ] && [ -f "$BRIDGE_SRC" ]; then
cp "$BRIDGE_SRC" "$IN_DIR/$BRIDGE_LIB"
say "staged $BRIDGE_LIB for SHADER FX preset conversion"
elif [ "${SHADERFX_BRIDGE_REQUIRED:-}" = "1" ]; then
fail "$BRIDGE_LIB not found: set SHADERFX_BRIDGE_LINUX_ARM64 or stage it at dist/native/linux-arm64/$BRIDGE_LIB"
else
warn "$BRIDGE_LIB not found: this build can run converted presets but not CONVERT new ones"
fi
# --------------------------------------------------------------- downloads
# Fetched on the host and checksum-pinned here so the container never needs
# network access and every input is verified in exactly one place.
+9 -1
View File
@@ -327,6 +327,14 @@ bundle_needed "$APPDIR/lib/liblove-$LOVE_VERSION.so"
say "bundled $(ls "$APPDIR/lib" | wc -l) libraries: $(ls "$APPDIR/lib" | tr '\n' ' ')"
# ------------------------------------------------- host dependency contract
SHADER_BRIDGE=()
if [ -f "$IN/liblibrashader_bridge.so" ]; then
cp "$IN/liblibrashader_bridge.so" "$APPDIR/liblibrashader_bridge.so"
chmod 0755 "$APPDIR/liblibrashader_bridge.so"
SHADER_BRIDGE=("$APPDIR/liblibrashader_bridge.so")
say "bundled liblibrashader_bridge.so for SHADER FX preset conversion"
fi
# The portability promise, stated as an assertion instead of a paragraph in a
# README: these are the ONLY sonames the shipped objects may require from the
# host. Everything driver-, session- or audio-related has to be reached
@@ -339,7 +347,7 @@ say "bundled $(ls "$APPDIR/lib" | wc -l) libraries: $(ls "$APPDIR/lib" | tr '\n'
HOST_ALLOWED_RE='^(ld-linux-aarch64\.so\.1|libc\.so\.6|libm\.so\.6|libdl\.so\.2|libpthread\.so\.0|librt\.so\.1|libstdc\+\+\.so\.6|libgcc_s\.so\.1|libatomic\.so\.1|libfreetype\.so\.6|libpng[0-9]*\.so\.[0-9]+|libz\.so\.1|libbrotli(dec|common)\.so\.1)$'
unexpected=""
for object in "$APPDIR/bin/love" "$APPDIR"/lib/*.so*; do
for object in "$APPDIR/bin/love" "$APPDIR"/lib/*.so* ${SHADER_BRIDGE[@]+"${SHADER_BRIDGE[@]}"}; do
while read -r soname; do
[ -n "$soname" ] || continue
# Satisfied from inside the AppDir, so not a host requirement at all.
+28 -3
View File
@@ -20,6 +20,23 @@ for required in AppRun bin/love game.love lib/liblove-11.5.so; do
|| { echo "::error::AppImage is missing $required"; exit 1; }
done
bridge="squashfs-root/liblibrashader_bridge.so"
if [ "${SHADERFX_BRIDGE_REQUIRED:-}" = "1" ] && [ ! -e "$bridge" ]; then
echo "::error::AppImage is missing liblibrashader_bridge.so"
exit 1
fi
# Discovered, not enumerated: bin/love and lib/*.so* miss anything native at
# the AppDir root, which is where ShaderFX's bridge sits and where the next
# root-level library would land too.
scan=()
while IFS= read -r f; do
scan+=("$f")
done < <(find squashfs-root -type f -exec sh -c \
'head -c4 "$1" | od -An -tx1 | tr -d " \n" | grep -q "^7f454c46$"' _ {} \; -print | sort)
[ "${#scan[@]}" -gt 0 ] || { echo "::error::found no ELF objects in the AppDir"; exit 1; }
echo "scanning ${#scan[@]} ELF objects: ${scan[*]#squashfs-root/}"
# Every bundled object must resolve once AppRun's LD_LIBRARY_PATH is
# applied; an unresolved soname here is a user-visible launch crash.
#
@@ -28,14 +45,14 @@ done
# hard-links libpulse/libasound/libX11/libwayland, so it only ever
# started on a full desktop -- a bare runner is what exposed it.
missing="$(LD_LIBRARY_PATH="$PWD/squashfs-root/lib" \
ldd squashfs-root/bin/love squashfs-root/lib/*.so* 2>/dev/null \
ldd "${scan[@]}" 2>/dev/null \
| grep 'not found' || true)"
[ -z "$missing" ] || { echo "::error::unresolved deps:"; echo "$missing"; exit 1; }
# Nothing may hard-link a driver, session or audio-stack library:
# those must be reached through dlopen so the AppImage runs on a box
# with only ALSA, only Wayland, or only KMSDRM.
linked="$(for f in squashfs-root/bin/love squashfs-root/lib/*.so*; do
linked="$(for f in "${scan[@]}"; do
objdump -p "$f" 2>/dev/null | awk '/NEEDED/{print $2}'
done | sort -u | grep -E '^lib(pulse|asound|X11|wayland|GL|EGL|drm|gbm|xcb|cairo|sndio|dbus)' || true)"
[ -z "$linked" ] \
@@ -45,7 +62,7 @@ done | sort -u | grep -E '^lib(pulse|asound|X11|wayland|GL|EGL|drm|gbm|xcb|cairo
# the builder to a newer base, the glibc floor silently rises and
# every user on an older distro gets "GLIBC_2.xx not found" -- catch
# it here instead of in a release.
floor="$(objdump -T squashfs-root/bin/love squashfs-root/lib/*.so* 2>/dev/null \
floor="$(objdump -T "${scan[@]}" 2>/dev/null \
| grep -o 'GLIBC_[0-9.]*' | sort -V | tail -1)"
echo "highest required glibc symbol version: $floor"
[ -n "$floor" ] \
@@ -54,4 +71,12 @@ highest="$(printf '%s\n' "$floor" "GLIBC_2.31" | sort -V | tail -1)"
[ "$highest" = "GLIBC_2.31" ] \
|| { echo "::error::AppImage requires $floor, above the bullseye 2.31 floor"; exit 1; }
# The floor grep proves symbol versions; an actual dlopen additionally proves
# relocations and constructors. Native arch only, so it is skipped elsewhere.
if [ -e "$bridge" ] && [ "$(uname -m)" = "aarch64" ] && command -v python3 >/dev/null 2>&1; then
python3 -c "import ctypes,sys; ctypes.CDLL(sys.argv[1])" "$PWD/$bridge" \
|| { echo "::error::liblibrashader_bridge.so failed to dlopen"; exit 1; }
echo "librashader bridge dlopens cleanly"
fi
echo "AppImage verified: $image"
+1
View File
@@ -118,6 +118,7 @@ run_tier "T0 Yellow title OBP eye remap" python3 tests/title_pikachu_obp_test.py
run_tier "T0 Crystal manifest + specials coverage" "$LUA" tests/crystal_import_test.lua
run_tier "T0 switch CI workflow content gate" "$LUA" tests/switch_ci_workflows_test.lua
run_tier "T0 switch transfer docs gate" "$LUA" tests/switch_transfer_docs_test.lua
run_tier "T0 ShaderFX bridge packaging gate" "$LUA" tests/shaderfx_bridge_packaging_test.lua
# NX Blue/Yellow asset overlay: ROM-free, must run on every checkout so a
# Sound.lua / overlay regression is not gated only on switch-changes paths.
run_tier "T0 NX asset overlay fallback" "$LUA" tests/engine/assets_version_fallback_test.lua
+71
View File
@@ -0,0 +1,71 @@
-- Content gate: every shipped artifact carries ShaderFX's librashader bridge.
-- Self-contained: luajit tests/shaderfx_bridge_packaging_test.lua
local T = require("tests.harness")
local check = T.check
local function read(path)
local f, err = io.open(path, "r")
if not f then error("cannot read " .. path .. ": " .. tostring(err)) end
local s = f:read("*a")
f:close()
return s
end
local function mustContain(body, needle, label)
check(body:find(needle, 1, true) ~= nil,
label .. " must contain " .. string.format("%q", needle))
end
local build = read("scripts/build.sh")
local release = read(".github/workflows/release.yml")
local flatpak = read("scripts/build_flatpak.sh")
local manifest = read("flatpak/com.theboisclub.gen1recomp.yml")
local arm64 = read("scripts/build_linux_arm64.sh")
local arm64_pack = read("scripts/linux-arm64/build_appimage.sh")
local verify = read("scripts/linux-arm64/verify_appimage.sh")
local rg34 = read("build-rg34xxsp.sh")
local sbc = read("build-linux-arm-sbc.sh")
for _, call in ipairs({
'bundle_shader_bridge "$out_app/Contents/MacOS" "liblibrashader_bridge.dylib" mac',
'bundle_shader_bridge "$out_dir" "librashader_bridge.dll" win-x64',
'bundle_shader_bridge "$appdir" "liblibrashader_bridge.so" linux-x64',
}) do
mustContain(build, call, "build.sh")
end
mustContain(build, '$DIST/native/$plat/$name', "build.sh staged lookup")
mustContain(build, 'SHADERFX_BRIDGE_REQUIRED', "build.sh hard-fail switch")
mustContain(build, '[ "$plat" = "$(shader_bridge_host_plat)" ]', "build.sh host guard")
mustContain(release, "shaderfx-bridge:", "release.yml bridge job")
for _, plat in ipairs({ "win-x64", "mac", "linux-x64", "linux-arm64" }) do
mustContain(release, "plat: " .. plat, "release.yml matrix")
end
mustContain(release, "lipo -create", "release.yml universal macOS bridge")
local requiredIn = select(2, release:gsub('SHADERFX_BRIDGE_REQUIRED: "1"', ""))
check(requiredIn >= 6,
'release.yml must set SHADERFX_BRIDGE_REQUIRED on every shipping job, found ' .. requiredIn)
mustContain(release, "librashader_bridge.dll", "release.yml Windows zip assertion")
mustContain(manifest, "# BRIDGE-BEGIN", "flatpak manifest markers")
mustContain(manifest, "/app/share/gen1recomp/liblibrashader_bridge.so", "flatpak install path")
mustContain(flatpak, "/# BRIDGE-BEGIN/,/# BRIDGE-END/d", "build_flatpak.sh strip")
mustContain(flatpak, "$BUILD_DIR/files/share/gen1recomp/$BRIDGE_LIB", "build_flatpak.sh verify")
mustContain(arm64, "SHADERFX_BRIDGE_LINUX_ARM64", "build_linux_arm64.sh override")
mustContain(arm64_pack, '$APPDIR/liblibrashader_bridge.so', "build_appimage.sh AppDir root")
mustContain(arm64_pack, '${SHADER_BRIDGE[@]+"${SHADER_BRIDGE[@]}"}', "build_appimage.sh contract scan")
mustContain(verify, "7f454c46", "verify_appimage.sh discovers ELF objects")
mustContain(verify, 'ctypes.CDLL', "verify_appimage.sh dlopen smoke")
for _, scanned in ipairs({ 'ldd "${scan[@]}"', 'for f in "${scan[@]}"', 'objdump -T "${scan[@]}"' }) do
mustContain(verify, scanned, "verify_appimage.sh")
end
for _, pair in ipairs({ { rg34, "build-rg34xxsp.sh" }, { sbc, "build-linux-arm-sbc.sh" } }) do
mustContain(pair[1], 'libs.aarch64/$BRIDGE_LIB', pair[2])
mustContain(pair[1], "SHADERFX_BRIDGE_REQUIRED", pair[2])
end
T.finish("shaderfx_bridge_packaging_test")