From 4aaf9c4f926a656b888a47eb37899c7f0f581494 Mon Sep 17 00:00:00 2001 From: Matthew Stanley <1379tech@gmail.com> Date: Wed, 26 Aug 2026 13:02:53 -0700 Subject: [PATCH] Adopt SDL3 default for MPH launcher builds --- docs/sdl3-first-target.md | 38 ++++++++++++++++++++++++++++ launcher/recomp-ui/CMakeLists.txt | 19 +++++++++++--- packaging/linux/steamdeck.Dockerfile | 37 +++++++++++++++++++++++++++ tools/build-linux.sh | 12 ++++++++- tools/build-windows.ps1 | 9 +++++-- tools/make_linux_appimage.sh | 3 ++- tools/make_release.ps1 | 6 +++-- 7 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 docs/sdl3-first-target.md diff --git a/docs/sdl3-first-target.md b/docs/sdl3-first-target.md new file mode 100644 index 0000000..6f6db68 --- /dev/null +++ b/docs/sdl3-first-target.md @@ -0,0 +1,38 @@ +# SDL3 first-target adoption + +## Goal + +Metroid Prime Hunters is the first title worktree consuming the ndsrecomp SDL3 +default. The title build should use SDL3 for both the shared runner and the +recomp-ui launcher unless a developer explicitly selects SDL2. + +## Build contract + +- `tools/build-windows.ps1` defaults `-SdlBackend SDL3`. +- `tools/build-linux.sh` defaults `--sdl-backend SDL3`. +- The launcher CMake option is `MPH_LAUNCHER_SDL_BACKEND=SDL3|SDL2`. +- The runner option remains the framework-level `NDS_SDL_BACKEND=SDL3|SDL2`. +- Windows packaging stages `SDL3.dll` by default and stages `SDL2.dll` only + when `-SdlBackend SDL2` is selected. +- The Steam Deck AppImage container remains on Ubuntu 22.04 for the older + glibc floor and builds a pinned SDL3 from source; `libsdl2-dev` remains + installed for explicit SDL2 fallback builds. + +## Validation target + +The first practical validation is the standalone launcher CMake target because +it exercises recomp-ui's SDL3 backend without requiring the private ROM or +generated title-bank artifacts: + +```powershell +& C:\msys64\mingw64\bin\cmake.exe -G Ninja ` + -S F:\Projects\ndsrecomp\worktrees\mph-sdl3-default\launcher\recomp-ui ` + -B F:\Projects\ndsrecomp\worktrees\mph-sdl3-default\launcher\recomp-ui\build-sdl3-default ` + -DCMAKE_BUILD_TYPE=Release ` + -DNDSRECOMP_ROOT=F:\Projects\ndsrecomp\worktrees\ndsrecomp-sdl3-default ` + -DRECOMP_UI_ROOT=F:\Projects\recomp-ui ` + -DCMAKE_PREFIX_PATH=C:\msys64\mingw64\lib\cmake +& C:\msys64\mingw64\bin\cmake.exe --build ` + F:\Projects\ndsrecomp\worktrees\mph-sdl3-default\launcher\recomp-ui\build-sdl3-default ` + --target mph-recomp-ui -j 12 +``` diff --git a/launcher/recomp-ui/CMakeLists.txt b/launcher/recomp-ui/CMakeLists.txt index f4fe4a7..0a6ccff 100644 --- a/launcher/recomp-ui/CMakeLists.txt +++ b/launcher/recomp-ui/CMakeLists.txt @@ -5,7 +5,19 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -find_package(SDL2 CONFIG REQUIRED) +set(MPH_LAUNCHER_SDL_BACKEND "SDL3" CACHE STRING + "Launcher SDL backend: SDL3 or SDL2") +set_property(CACHE MPH_LAUNCHER_SDL_BACKEND PROPERTY STRINGS SDL3 SDL2) + +if(MPH_LAUNCHER_SDL_BACKEND STREQUAL "SDL3") + find_package(SDL3 CONFIG REQUIRED) + set(MPH_LAUNCHER_SDL_TARGET SDL3::SDL3) +elseif(MPH_LAUNCHER_SDL_BACKEND STREQUAL "SDL2") + find_package(SDL2 CONFIG REQUIRED) + set(MPH_LAUNCHER_SDL_TARGET SDL2::SDL2) +else() + message(FATAL_ERROR "MPH_LAUNCHER_SDL_BACKEND must be SDL3 or SDL2") +endif() set(NDSRECOMP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../ndsrecomp" CACHE PATH "Path to the ndsrecomp framework checkout (for the shared SHA-1 helper)") @@ -14,7 +26,7 @@ add_executable(mph-recomp-ui launcher_main.cpp "${NDSRECOMP_ROOT}/recompiler/support/sha1.cpp") target_include_directories(mph-recomp-ui PRIVATE "${NDSRECOMP_ROOT}/recompiler/support") -target_link_libraries(mph-recomp-ui PRIVATE SDL2::SDL2) +target_link_libraries(mph-recomp-ui PRIVATE ${MPH_LAUNCHER_SDL_TARGET}) set(RECOMP_UI_ROOT "F:/Projects/recomp-ui" CACHE PATH "Path to the shared recomp-ui checkout") @@ -34,7 +46,8 @@ target_include_directories(mph-mod-provider-test PRIVATE target_compile_definitions(mph-mod-provider-test PRIVATE MPH_RECOMP_UI_NO_MAIN) -set(RECOMP_UI_SDL3 OFF) +set(SNESRECOMP_SDL_BACKEND "${MPH_LAUNCHER_SDL_BACKEND}" CACHE STRING + "SDL backend consumed by recomp-ui" FORCE) set(RECOMP_UI_ENABLE_MODS ON CACHE BOOL "" FORCE) include("${RECOMP_UI_ROOT}/recomp_ui.cmake") recomp_target_launcher_ui(mph-recomp-ui CONSOLE nds diff --git a/packaging/linux/steamdeck.Dockerfile b/packaging/linux/steamdeck.Dockerfile index e027a59..dd8b238 100644 --- a/packaging/linux/steamdeck.Dockerfile +++ b/packaging/linux/steamdeck.Dockerfile @@ -1,6 +1,7 @@ FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive +ARG SDL3_VERSION=3.2.20 RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ @@ -9,17 +10,53 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ file \ git \ + libasound2-dev \ + libdbus-1-dev \ + libdecor-0-dev \ + libdrm-dev \ + libegl-dev \ + libfribidi-dev \ libfuse2 \ + libgbm-dev \ + libgles-dev \ libgl1-mesa-dev \ + libibus-1.0-dev \ + libpulse-dev \ libsdl2-dev \ + libudev-dev \ + libwayland-dev \ + libx11-dev \ + libxcursor-dev \ + libxext-dev \ + libxfixes-dev \ + libxi-dev \ + libxkbcommon-dev \ + libxrandr-dev \ + libxrender-dev \ + libxss-dev \ + libxtst-dev \ ninja-build \ pkg-config \ python3 \ python3-pip \ squashfs-tools \ + wayland-protocols \ xz-utils \ && rm -rf /var/lib/apt/lists/* +RUN curl -fsSL "https://www.libsdl.org/release/SDL3-${SDL3_VERSION}.tar.gz" \ + -o /tmp/SDL3.tar.gz \ + && mkdir -p /tmp/SDL3-src /tmp/SDL3-build \ + && tar -xzf /tmp/SDL3.tar.gz -C /tmp/SDL3-src --strip-components=1 \ + && cmake -S /tmp/SDL3-src -B /tmp/SDL3-build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DSDL_TESTS=OFF \ + -DSDL_EXAMPLES=OFF \ + && cmake --build /tmp/SDL3-build -j"$(nproc)" \ + && cmake --install /tmp/SDL3-build \ + && ldconfig \ + && rm -rf /tmp/SDL3.tar.gz /tmp/SDL3-src /tmp/SDL3-build + RUN python3 -m pip install --no-cache-dir \ cmake==3.29.6 \ ninja==1.11.1.1 \ diff --git a/tools/build-linux.sh b/tools/build-linux.sh index 9632003..e24d427 100644 --- a/tools/build-linux.sh +++ b/tools/build-linux.sh @@ -19,6 +19,7 @@ VERSION="0.1.0" JOBS="$(nproc 2>/dev/null || echo 4)" DO_PACKAGE=1 BUILD_FLAVOR="release" +SDL_BACKEND="${NDS_SDL_BACKEND:-SDL3}" REPO="$(cd "$(dirname "$0")/.." && pwd)" FRAMEWORK_ROOT="${NDSRECOMP_ROOT:-$REPO/../ndsrecomp}" @@ -35,6 +36,7 @@ while [ $# -gt 0 ]; do --ndsrecomp-root) FRAMEWORK_ROOT="$(cd "$2" && pwd)"; shift 2;; --recomp-ui-root) RECOMP_UI_ROOT="$(cd "$2" && pwd)"; shift 2;; --build-flavor) BUILD_FLAVOR="$2"; shift 2;; + --sdl-backend) SDL_BACKEND="$2"; shift 2;; --no-package) DO_PACKAGE=0; shift;; -h|--help) sed -n '2,14p' "$0" @@ -44,6 +46,11 @@ while [ $# -gt 0 ]; do esac done +case "$SDL_BACKEND" in + SDL3|SDL2) ;; + *) echo "ERROR: --sdl-backend must be SDL3 or SDL2." >&2; exit 2;; +esac + GAME_BUILD="$REPO/build-linux-$BUILD_FLAVOR" RUNNER_BUILD="$FRAMEWORK_ROOT/runner/build-mph-linux-$BUILD_FLAVOR" LAUNCHER_BUILD="$REPO/launcher/recomp-ui/build-linux-$BUILD_FLAVOR" @@ -73,6 +80,7 @@ cmake --build "$GAME_BUILD" --target "$TITLE_TARGET" -j"$JOBS" echo "[3/4] configure runner" cmake -S "$FRAMEWORK_ROOT/runner" -B "$RUNNER_BUILD" -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ + -DNDS_SDL_BACKEND="$SDL_BACKEND" \ -DNDS_BOOTSTRAP_FIRMWARE=ON \ -DNDS_TITLE_BANK_DIR="$TITLE_BANK_DIR" \ -DNDS_TITLE_ROM_SHA1="$ROM_SHA1" @@ -83,7 +91,8 @@ echo " configure Linux launcher" cmake -S "$REPO/launcher/recomp-ui" -B "$LAUNCHER_BUILD" -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ -DNDSRECOMP_ROOT="$FRAMEWORK_ROOT" \ - -DRECOMP_UI_ROOT="$RECOMP_UI_ROOT" + -DRECOMP_UI_ROOT="$RECOMP_UI_ROOT" \ + -DMPH_LAUNCHER_SDL_BACKEND="$SDL_BACKEND" echo " build Linux launcher" cmake --build "$LAUNCHER_BUILD" --target "$LAUNCHER_NAME" -j"$JOBS" @@ -182,6 +191,7 @@ HERE="$(dirname "$(readlink -f "$0")")" export LD_LIBRARY_PATH="$HERE/usr/lib:${LD_LIBRARY_PATH:-}" export SDL_JOYSTICK_HIDAPI_STEAM=1 export SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD=1 +export SDL_GAMEPAD_ALLOW_STEAM_VIRTUAL_GAMEPAD=1 SELF="${APPIMAGE:-$0}" RUNDIR="$(dirname "$(readlink -f "$SELF")")" export RECOMP_APPIMAGE_PATH="$SELF" diff --git a/tools/build-windows.ps1 b/tools/build-windows.ps1 index 7e85076..f250edf 100644 --- a/tools/build-windows.ps1 +++ b/tools/build-windows.ps1 @@ -19,7 +19,9 @@ param( [string]$LauncherBuildDir = 'launcher\recomp-ui\build-release', [string]$RuntimeBinDir = 'C:\msys64\mingw64\bin', [string]$NdsrecompRoot = '..\ndsrecomp', - [string]$RecompUiRoot = 'F:\Projects\recomp-ui' + [string]$RecompUiRoot = 'F:\Projects\recomp-ui', + [ValidateSet('SDL3', 'SDL2')] + [string]$SdlBackend = 'SDL3' ) $ErrorActionPreference = 'Stop' @@ -51,6 +53,7 @@ try { & $cmakePath -G $Generator -S "$frameworkRoot\runner" -B $runnerBuild ` -DCMAKE_BUILD_TYPE=Release ` + "-DNDS_SDL_BACKEND=$SdlBackend" ` -DNDS_BOOTSTRAP_FIRMWARE=ON ` "-DNDS_TITLE_BANK_DIR=$titleBankDir" ` "-DNDS_TITLE_ROM_SHA1=$romSha1" @@ -62,6 +65,7 @@ try { -DCMAKE_BUILD_TYPE=Release ` -DNDSRECOMP_ROOT="$frameworkRoot" ` -DRECOMP_UI_ROOT="$RecompUiRoot" ` + "-DMPH_LAUNCHER_SDL_BACKEND=$SdlBackend" ` -DCMAKE_PREFIX_PATH="$RuntimeBinDir\..\lib\cmake" if ($LASTEXITCODE -ne 0) { throw 'Launcher CMake configure failed.' } & $cmakePath --build $launcherBuild -j $Jobs @@ -72,7 +76,8 @@ try { -Version $Version ` -RunnerBuildDir $RunnerBuildDir ` -LauncherBuildDir $LauncherBuildDir ` - -RuntimeBinDir $RuntimeBinDir + -RuntimeBinDir $RuntimeBinDir ` + -SdlBackend $SdlBackend if ($LASTEXITCODE -ne 0) { throw 'Release packaging failed.' } } finally { Pop-Location diff --git a/tools/make_linux_appimage.sh b/tools/make_linux_appimage.sh index 3b2bda8..a274d49 100644 --- a/tools/make_linux_appimage.sh +++ b/tools/make_linux_appimage.sh @@ -42,7 +42,7 @@ cp "$BIN" "$APP/usr/bin/nds_runner" cp "$ROOT/game.toml" "$APP/usr/bin/" cp "$ROOT/README.md" "$APP/usr/bin/" 2>/dev/null || true -# Bundle non-core shared libraries (SDL2, libstdc++, libgcc, slirp deps…) +# Bundle non-core shared libraries (SDL, libstdc++, libgcc, slirp deps…) # so the ELF runs without the build distro. glibc itself stays on the host. echo "=== bundle shared libraries ===" ldd "$BIN" | awk '/=> \// {print $3}' | while read -r lib; do @@ -64,6 +64,7 @@ HERE="$(dirname "$(readlink -f "$0")")" export LD_LIBRARY_PATH="$HERE/usr/lib:${LD_LIBRARY_PATH:-}" export SDL_JOYSTICK_HIDAPI_STEAM=1 export SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD=1 +export SDL_GAMEPAD_ALLOW_STEAM_VIRTUAL_GAMEPAD=1 ANCHOR="$(dirname "$(readlink -f "${APPIMAGE:-$0}")")" cd "$ANCHOR" 2>/dev/null || true [ "$#" -gt 0 ] && exec "$HERE/usr/bin/nds_runner" "$@" diff --git a/tools/make_release.ps1 b/tools/make_release.ps1 index 84de180..bae6695 100644 --- a/tools/make_release.ps1 +++ b/tools/make_release.ps1 @@ -16,7 +16,9 @@ param( [Parameter(Mandatory = $true)][string]$Version, [string]$RunnerBuildDir = '..\ndsrecomp\runner\build-mph-release', [string]$LauncherBuildDir = 'launcher\recomp-ui\build-release', - [string]$RuntimeBinDir = 'C:\msys64\mingw64\bin' + [string]$RuntimeBinDir = 'C:\msys64\mingw64\bin', + [ValidateSet('SDL3', 'SDL2')] + [string]$SdlBackend = 'SDL3' ) $ErrorActionPreference = 'Stop' @@ -81,7 +83,7 @@ Copy-Item -LiteralPath (Join-Path $root 'packaging\BIOS_README.txt') ` -Destination (Join-Path $stage 'bios\README.txt') $runtimeDlls = @( - 'SDL2.dll', + "$SdlBackend.dll", 'libgcc_s_seh-1.dll', 'libstdc++-6.dll', 'libwinpthread-1.dll'