mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 02:00:14 +02:00
Add a Steam Frame install script and base the quick start on it
Launcher/steam-frame-install.sh does the whole quick start in one command: it downloads the newest release (or builds the tree it is in), extracts the disc with nodtool, builds in a long-lived Debian ARM64 container (podman or docker, under qemu on x86_64), copies the game and disc to the Frame over SSH (or locally with --frame local), points Config.toml at the disc, and registers the game with Steam through Valve's devkit tools when present. Running it again updates: only changed source files are replaced, so the build recompiles just those and Dawn is reused. The README's quick start now runs the script; the manual steps move to a "Building by hand" section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019HBRGKTE1GnN2ah8gcZKr3
This commit is contained in:
2 files changed
+545
-118
No files matched your search
Executable
+390
@@ -0,0 +1,390 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Builds WiiCompiled VR for the Steam Frame from a release and your own disc, and installs it on the
|
||||||
|
# Frame. Run it again to update: it fetches the newest release and rebuilds only what changed.
|
||||||
|
#
|
||||||
|
# Launcher/steam-frame-install.sh --disc PATH [--frame HOST] [options]
|
||||||
|
#
|
||||||
|
# Or without downloading anything first:
|
||||||
|
#
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/mitch030504/Wiicompiled_VR_Frame/openxr-work/Launcher/steam-frame-install.sh \
|
||||||
|
# | bash -s -- --disc "/path/to/Mario Kart Wii.wbfs" --frame steamos@<frame-ip>
|
||||||
|
#
|
||||||
|
# It runs on an x86_64 or ARM64 Linux PC with podman (or docker), or on the Frame itself. The game
|
||||||
|
# is built in a Debian ARM64 container, under qemu emulation on x86_64; the first build takes a few
|
||||||
|
# hours there, mostly compiling Dawn, and later ones reuse it.
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --disc PATH your clean PAL RMCP01 disc: an image nodtool reads (ISO, WBFS, RVZ, ...) or an
|
||||||
|
# extracted disc folder holding sys/ and files/. Needed for the first build only.
|
||||||
|
# --frame HOST where to install: an SSH destination (steamos@<frame-ip>, or an ~/.ssh/config
|
||||||
|
# host such as Frame Control's "frame"), or "local" when running on the Frame.
|
||||||
|
# Without it the game is only built.
|
||||||
|
# --work-dir DIR where the toolchain, Dawn, the build and the extracted disc live
|
||||||
|
# (default ~/wiicompiled-frame; about 20 GB)
|
||||||
|
# --release TAG the release to build (default: the newest one). Ignored with --source.
|
||||||
|
# --source DIR build this source tree instead of a release (default when the script runs
|
||||||
|
# from inside one)
|
||||||
|
# --jobs N parallel compiles (default: a quarter of the memory in GB; under emulation each
|
||||||
|
# compile needs a lot of it)
|
||||||
|
# --frame-disc DIR where the extracted disc goes on the Frame: absolute, or relative to the
|
||||||
|
# Frame's home (default wiicompiled/disc; with --frame local, the disc folder
|
||||||
|
# the build used)
|
||||||
|
# -h, --help
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Everything is in main, so bash has read the whole script before running any of it: when it comes
|
||||||
|
# through curl | bash, a step that reads stdin cannot eat the rest. (Not indented, for the heredocs.)
|
||||||
|
main() {
|
||||||
|
trap 'printf "\nsteam-frame-install.sh: stopped by a failed step (line %s); the output above says why.\n" "$LINENO" >&2' ERR
|
||||||
|
|
||||||
|
repo=mitch030504/Wiicompiled_VR_Frame
|
||||||
|
game_id=WiiCompiled
|
||||||
|
image=docker.io/library/debian:trixie
|
||||||
|
container=wiicompiled-frame-build
|
||||||
|
nodtool_version=v2.0.0-alpha.10
|
||||||
|
|
||||||
|
say() { printf '\n\033[1m==> %s\033[0m\n' "$*"; }
|
||||||
|
note() { printf ' %s\n' "$*"; }
|
||||||
|
fail() {
|
||||||
|
printf '\nsteam-frame-install.sh: error: %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
usage() { awk 'NR == 1 { next } /^#/ { sub(/^# ?/, ""); print; next } { exit }' "$script_path"; }
|
||||||
|
|
||||||
|
script_path=${BASH_SOURCE[0]:-}
|
||||||
|
script_dir=""
|
||||||
|
if [[ -n "$script_path" && -f "$script_path" ]]; then
|
||||||
|
script_dir=$(cd "$(dirname "$script_path")" && pwd)
|
||||||
|
fi
|
||||||
|
|
||||||
|
disc=""
|
||||||
|
frame=""
|
||||||
|
work_dir="$HOME/wiicompiled-frame"
|
||||||
|
release=""
|
||||||
|
source_dir=""
|
||||||
|
jobs=""
|
||||||
|
frame_disc=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--disc) disc=$2; shift 2 ;;
|
||||||
|
--frame) frame=$2; shift 2 ;;
|
||||||
|
--work-dir) work_dir=$2; shift 2 ;;
|
||||||
|
--release) release=$2; shift 2 ;;
|
||||||
|
--source) source_dir=$2; shift 2 ;;
|
||||||
|
--jobs) jobs=$2; shift 2 ;;
|
||||||
|
--frame-disc) frame_disc=$2; shift 2 ;;
|
||||||
|
-h|--help)
|
||||||
|
if [[ -n "$script_dir" ]]; then usage; else echo "See the comment at the top of the script."; fi
|
||||||
|
exit 0 ;;
|
||||||
|
*) fail "unknown argument: $1 (see --help)" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p "$work_dir"
|
||||||
|
work_dir=$(cd "$work_dir" && pwd)
|
||||||
|
host_arch=$(uname -m)
|
||||||
|
case "$host_arch" in
|
||||||
|
x86_64|aarch64) ;;
|
||||||
|
*) fail "this machine is $host_arch; the build needs an x86_64 or ARM64 Linux machine" ;;
|
||||||
|
esac
|
||||||
|
[[ "$(uname -s)" == Linux ]] || fail "run this on Linux (the build uses a Linux container)"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------
|
||||||
|
say "Checking the container runtime"
|
||||||
|
runtime=""
|
||||||
|
for candidate in podman docker; do
|
||||||
|
if command -v "$candidate" >/dev/null 2>&1; then runtime=$candidate; break; fi
|
||||||
|
done
|
||||||
|
[[ -n "$runtime" ]] || fail "neither podman nor docker is installed.
|
||||||
|
Arch, CachyOS: sudo pacman -S --needed podman qemu-user-static qemu-user-static-binfmt
|
||||||
|
Debian, Ubuntu: sudo apt install podman qemu-user-static binfmt-support
|
||||||
|
Fedora: sudo dnf install podman qemu-user-static
|
||||||
|
SteamOS (the Frame) already has podman."
|
||||||
|
note "using $runtime"
|
||||||
|
for tool in curl tar; do
|
||||||
|
command -v "$tool" >/dev/null 2>&1 || fail "'$tool' is not installed"
|
||||||
|
done
|
||||||
|
|
||||||
|
platform_args=()
|
||||||
|
if [[ "$host_arch" == x86_64 ]]; then
|
||||||
|
platform_args=(--platform linux/arm64)
|
||||||
|
say "Checking ARM64 emulation"
|
||||||
|
seen=$("$runtime" run --rm "${platform_args[@]}" "$image" uname -m 2>&1 | tail -n 1 || true)
|
||||||
|
case "$seen" in
|
||||||
|
aarch64) note "ARM64 programs run under qemu" ;;
|
||||||
|
Linux)
|
||||||
|
fail "qemu is registered without the P (preserve argv[0]) flag its build needs, so every
|
||||||
|
program loses its first argument (uname -m printed 'Linux'). Register it again with flags POCF;
|
||||||
|
the README's 'Other ways to build' shows how." ;;
|
||||||
|
*)
|
||||||
|
fail "ARM64 programs do not run in containers here ($seen).
|
||||||
|
Arch, CachyOS: sudo pacman -S --needed qemu-user-static qemu-user-static-binfmt
|
||||||
|
sudo systemctl restart systemd-binfmt
|
||||||
|
Debian, Ubuntu: sudo apt install qemu-user-static binfmt-support
|
||||||
|
Fedora: sudo dnf install qemu-user-static && sudo systemctl restart systemd-binfmt
|
||||||
|
Then run this script again. On hosts whose binfmt_misc is per container (Unraid), see the
|
||||||
|
README's 'Other ways to build'." ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$jobs" ]]; then
|
||||||
|
mem_gb=$(( $(awk '/^MemTotal:/{print $2}' /proc/meminfo) / 1024 / 1024 ))
|
||||||
|
jobs=$(( mem_gb / 4 ))
|
||||||
|
(( jobs < 1 )) && jobs=1
|
||||||
|
(( jobs > $(nproc) )) && jobs=$(nproc)
|
||||||
|
fi
|
||||||
|
[[ "$jobs" =~ ^[1-9][0-9]*$ ]] || fail "--jobs must be a positive number"
|
||||||
|
note "$jobs parallel compiles"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------
|
||||||
|
# The source: the tree this script is in, an explicit --source, or a release kept in the work dir.
|
||||||
|
if [[ -z "$source_dir" && -z "$release" && -n "$script_dir" && -f "$script_dir/../runtime/CMakeLists.txt" ]]; then
|
||||||
|
source_dir=$(cd "$script_dir/.." && pwd)
|
||||||
|
fi
|
||||||
|
if [[ -n "$source_dir" ]]; then
|
||||||
|
source_dir=$(cd "$source_dir" && pwd)
|
||||||
|
[[ -f "$source_dir/Launcher/local-build.sh" ]] || fail "$source_dir is not a WiiCompiled VR source tree"
|
||||||
|
say "Building the source in $source_dir"
|
||||||
|
else
|
||||||
|
if [[ -z "$release" ]]; then
|
||||||
|
release=$(curl -fsSL "https://api.github.com/repos/$repo/releases?per_page=1" |
|
||||||
|
sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p' | head -n 1)
|
||||||
|
[[ -n "$release" ]] || fail "could not find the newest release on github.com/$repo (try --release TAG)"
|
||||||
|
fi
|
||||||
|
source_dir="$work_dir/source"
|
||||||
|
have=$(cat "$source_dir/.release-tag" 2>/dev/null || true)
|
||||||
|
if [[ "$have" == "$release" ]]; then
|
||||||
|
say "Release $release is already unpacked"
|
||||||
|
else
|
||||||
|
say "Downloading release $release"
|
||||||
|
rm -rf "$work_dir/source-new"
|
||||||
|
mkdir -p "$work_dir/source-new" "$source_dir"
|
||||||
|
curl -fL --progress-bar "https://github.com/$repo/archive/refs/tags/$release.tar.gz" |
|
||||||
|
tar -xz --strip-components=1 -C "$work_dir/source-new" ||
|
||||||
|
fail "could not download release $release; the Releases page on github.com/$repo lists them"
|
||||||
|
# Only files whose content changed are copied, stamped with the current time, so the build
|
||||||
|
# recompiles exactly those; the release's own file dates can be older than the last build.
|
||||||
|
if command -v rsync >/dev/null 2>&1; then
|
||||||
|
rsync -rcE "$work_dir/source-new/" "$source_dir/"
|
||||||
|
else
|
||||||
|
(cd "$work_dir/source-new" && find . -type f -print0) |
|
||||||
|
while IFS= read -r -d '' file; do
|
||||||
|
if ! cmp -s "$work_dir/source-new/$file" "$source_dir/$file"; then
|
||||||
|
mkdir -p "$source_dir/$(dirname "$file")"
|
||||||
|
cp "$work_dir/source-new/$file" "$source_dir/$file"
|
||||||
|
touch "$source_dir/$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
rm -rf "$work_dir/source-new"
|
||||||
|
printf '%s\n' "$release" > "$source_dir/.release-tag"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------
|
||||||
|
# The disc: the two files the translation reads, and the extracted disc the game reads at run time.
|
||||||
|
disc_dir="$work_dir/disc"
|
||||||
|
if [[ -n "$disc" ]]; then
|
||||||
|
[[ -e "$disc" ]] || fail "no disc at $disc"
|
||||||
|
if [[ -d "$disc" ]]; then
|
||||||
|
disc_dir=$(cd "$disc" && pwd)
|
||||||
|
elif [[ ! -f "$disc_dir/sys/main.dol" ]]; then
|
||||||
|
say "Extracting your disc"
|
||||||
|
nodtool="$work_dir/nodtool-$nodtool_version"
|
||||||
|
if [[ ! -x "$nodtool" ]]; then
|
||||||
|
curl -fL -o "$nodtool.partial" \
|
||||||
|
"https://github.com/encounter/nod/releases/download/$nodtool_version/nodtool-linux-$host_arch"
|
||||||
|
chmod +x "$nodtool.partial"
|
||||||
|
mv "$nodtool.partial" "$nodtool"
|
||||||
|
fi
|
||||||
|
rm -rf "$disc_dir.partial"
|
||||||
|
"$nodtool" extract "$disc" "$disc_dir.partial"
|
||||||
|
mv "$disc_dir.partial" "$disc_dir"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$disc_dir/sys/main.dol" || ! -f "$disc_dir/files/rel/StaticR.rel" ]]; then
|
||||||
|
if [[ -f "$source_dir/Assets/main.dol" && -f "$source_dir/Assets/StaticR.rel" ]]; then
|
||||||
|
disc_dir=""
|
||||||
|
else
|
||||||
|
fail "no disc yet: pass --disc with your disc image or an extracted disc folder"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
mkdir -p "$source_dir/Assets"
|
||||||
|
if [[ -n "$disc_dir" ]]; then
|
||||||
|
cp "$disc_dir/sys/main.dol" "$disc_dir/files/rel/StaticR.rel" "$source_dir/Assets/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------
|
||||||
|
say "Preparing the ARM64 build container"
|
||||||
|
cat > "$work_dir/container-build.sh" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Written by steam-frame-install.sh and run inside its build container.
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ ! -f /var/lib/wiicompiled-build-deps ]]; then
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y -qq --no-install-recommends \
|
||||||
|
ca-certificates curl git python3 xz-utils unzip file pkg-config g++ binutils libicu-dev \
|
||||||
|
zlib1g-dev libvulkan-dev libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxrandr-dev \
|
||||||
|
libxinerama-dev libxcursor-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev \
|
||||||
|
libwayland-dev wayland-protocols libdecor-0-dev libegl-dev libgl-dev libgles-dev libdrm-dev \
|
||||||
|
libgbm-dev libasound2-dev libpulse-dev libpipewire-0.3-dev libudev-dev libdbus-1-dev \
|
||||||
|
libusb-1.0-0-dev >/dev/null
|
||||||
|
touch /var/lib/wiicompiled-build-deps
|
||||||
|
fi
|
||||||
|
cd /src
|
||||||
|
Launcher/prepare-portable-tools.sh --arch aarch64 --destination /work/tools
|
||||||
|
T=/work/tools/toolchain-aarch64/bin
|
||||||
|
if [[ ! -x /work/dotnet/dotnet ]]; then
|
||||||
|
curl -fsSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 8.0 --install-dir /work/dotnet
|
||||||
|
fi
|
||||||
|
echo "== Dawn (built once; reused until a release changes its patches)"
|
||||||
|
Launcher/build-dawn-linux.sh --work-dir /work/dawn --cc "$T/clang" --cxx "$T/clang++" \
|
||||||
|
--cmake "$T/cmake" --ninja "$T/ninja" --jobs "$JOBS"
|
||||||
|
echo "== The game"
|
||||||
|
Launcher/local-build.sh --output-dir /work/out --cc "$T/clang" --cxx "$T/clang++" --fuse-ld lld \
|
||||||
|
--cmake "$T/cmake" --ninja "$T/ninja" --dotnet /work/dotnet/dotnet --parallel "$JOBS" \
|
||||||
|
--openxr --dawn-package /work/dawn/package --headset steam_frame
|
||||||
|
EOF
|
||||||
|
chmod +x "$work_dir/container-build.sh"
|
||||||
|
|
||||||
|
# One long-lived container, so its packages are installed once; recreated if its folders changed.
|
||||||
|
want_mounts="$work_dir=/work;$source_dir=/src;"
|
||||||
|
if "$runtime" container inspect "$container" >/dev/null 2>&1; then
|
||||||
|
mounts=$("$runtime" container inspect -f '{{range .Mounts}}{{.Source}}={{.Destination}};{{end}}' "$container")
|
||||||
|
if [[ "$mounts" != *"$work_dir=/work;"* || "$mounts" != *"$source_dir=/src;"* ]]; then
|
||||||
|
note "its folders changed; recreating it"
|
||||||
|
"$runtime" rm -f "$container" >/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if ! "$runtime" container inspect "$container" >/dev/null 2>&1; then
|
||||||
|
"$runtime" run -d --name "$container" "${platform_args[@]}" \
|
||||||
|
-v "$work_dir:/work:z" -v "$source_dir:/src:z" "$image" sleep infinity >/dev/null
|
||||||
|
fi
|
||||||
|
"$runtime" start "$container" >/dev/null
|
||||||
|
note "container $container (mounts ${want_mounts//;/ })"
|
||||||
|
|
||||||
|
say "Building (the first time takes hours under emulation; a log is in $work_dir/build.log)"
|
||||||
|
if ! "$runtime" exec -e JOBS="$jobs" "$container" bash /work/container-build.sh 2>&1 | tee "$work_dir/build.log"; then
|
||||||
|
fail "the build stopped; the end of $work_dir/build.log says why. Run the script again to resume.
|
||||||
|
A machine that froze ran out of memory: pass a lower --jobs."
|
||||||
|
fi
|
||||||
|
[[ -x "$work_dir/out/$game_id" ]] || fail "the build finished without $work_dir/out/$game_id"
|
||||||
|
note "built $work_dir/out/$game_id"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------
|
||||||
|
if [[ -z "$frame" ]]; then
|
||||||
|
say "Done"
|
||||||
|
note "The game is in $work_dir/out. Run the script again with --frame steamos@<frame-ip> to install it."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
say "Installing on the Frame"
|
||||||
|
# One SSH connection for every step, so a password is asked for once.
|
||||||
|
ssh_opts=(-o ControlMaster=auto -o "ControlPath=${XDG_RUNTIME_DIR:-/tmp}/wiicompiled-ssh-%C" -o ControlPersist=600)
|
||||||
|
on_frame() {
|
||||||
|
# Runs a bash script, given on stdin, on the Frame; its arguments follow.
|
||||||
|
if [[ "$frame" == local ]]; then bash -s -- "$@"; else ssh "${ssh_opts[@]}" "$frame" bash -s -- "$@"; fi
|
||||||
|
}
|
||||||
|
copy_to_frame() {
|
||||||
|
# copy_to_frame SOURCE DEST: DEST is absolute or relative to the Frame's home. A DEST ending in
|
||||||
|
# / is an existing folder SOURCE goes into; otherwise SOURCE is copied to that new name.
|
||||||
|
local source=$1 dest=$2
|
||||||
|
if [[ "$frame" == local ]]; then
|
||||||
|
[[ "$dest" == /* ]] || dest="$HOME/$dest"
|
||||||
|
cp -R "$source" "$dest"
|
||||||
|
elif [[ "$frame_rsync" == yes ]]; then
|
||||||
|
# rsync copies a folder without a trailing slash into DEST rather than as DEST.
|
||||||
|
[[ -d "$source" && "$dest" != */ ]] && source="$source/"
|
||||||
|
rsync -a -e "ssh ${ssh_opts[*]}" "$source" "$frame:$dest"
|
||||||
|
else
|
||||||
|
scp -rq "${ssh_opts[@]}" "$source" "$frame:$dest"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
on_frame <<<'true' || fail "cannot reach $frame over SSH. Turn on Developer Mode and set a user password on the
|
||||||
|
Frame (Steam Settings > System), then check the address."
|
||||||
|
frame_rsync=no
|
||||||
|
if [[ "$frame" != local ]] && command -v rsync >/dev/null 2>&1 &&
|
||||||
|
[[ "$(on_frame <<<'command -v rsync >/dev/null && echo yes || true')" == yes ]]; then
|
||||||
|
frame_rsync=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
game_dir="devkit-game/$game_id"
|
||||||
|
on_frame "$game_dir" <<'EOF'
|
||||||
|
mkdir -p "$HOME/$1"
|
||||||
|
EOF
|
||||||
|
note "copying the game to ~/$game_dir"
|
||||||
|
(cd "$work_dir/out" && find . -mindepth 1 -maxdepth 1 ! -name "$game_id" -print0) |
|
||||||
|
while IFS= read -r -d '' item; do copy_to_frame "$work_dir/out/${item#./}" "$game_dir/"; done
|
||||||
|
# The executable goes in under a new name and is moved into place: that works while it runs.
|
||||||
|
copy_to_frame "$work_dir/out/$game_id" "$game_dir/$game_id.new"
|
||||||
|
on_frame "$game_dir" "$game_id" <<'EOF'
|
||||||
|
cd "$HOME/$1" && mv -f "$2.new" "$2" && chmod -R u=rwX,go=rX . && chmod 755 "$2"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# The Frame's disc folder, absolute or relative to its home.
|
||||||
|
if [[ -z "$frame_disc" ]]; then
|
||||||
|
if [[ "$frame" == local && -n "$disc_dir" ]]; then frame_disc=$disc_dir; else frame_disc=wiicompiled/disc; fi
|
||||||
|
fi
|
||||||
|
frame_disc_path=${frame_disc#\~/}
|
||||||
|
has_disc=$(on_frame "$frame_disc_path" <<'EOF'
|
||||||
|
[[ "$1" = /* ]] && d=$1 || d="$HOME/$1"
|
||||||
|
[[ -f "$d/sys/main.dol" ]] && echo yes || true
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
if [[ "$has_disc" != yes ]]; then
|
||||||
|
[[ -n "$disc_dir" ]] || fail "the Frame has no disc at $frame_disc yet: pass --disc"
|
||||||
|
note "copying the extracted disc to $frame_disc (a few GB)"
|
||||||
|
on_frame "$frame_disc_path" <<'EOF'
|
||||||
|
[[ "$1" = /* ]] && d=$1 || d="$HOME/$1"
|
||||||
|
mkdir -p "$(dirname "$d")" && rm -rf "$d.partial"
|
||||||
|
EOF
|
||||||
|
copy_to_frame "$disc_dir" "$frame_disc_path.partial"
|
||||||
|
on_frame "$frame_disc_path" <<'EOF'
|
||||||
|
[[ "$1" = /* ]] && d=$1 || d="$HOME/$1"
|
||||||
|
rm -rf "$d" && mv "$d.partial" "$d"
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
note "pointing the game at the disc"
|
||||||
|
on_frame "$frame_disc_path" <<'EOF'
|
||||||
|
[[ "$1" = /* ]] && d=$1 || d="$HOME/$1"
|
||||||
|
config="$HOME/.local/share/WiiCompiled/Config.toml"
|
||||||
|
mkdir -p "$(dirname "$config")"
|
||||||
|
if [[ ! -f "$config" ]]; then
|
||||||
|
printf '[paths]\ndvd_root = "%s"\n' "$d" > "$config"
|
||||||
|
elif ! grep -q '^dvd_root *=' "$config"; then
|
||||||
|
if grep -q '^\[paths\]' "$config"; then
|
||||||
|
sed -i "/^\[paths\]/a dvd_root = \"$d\"" "$config"
|
||||||
|
else
|
||||||
|
printf '\n[paths]\ndvd_root = "%s"\n' "$d" >> "$config"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Steam's library: through Valve's devkit tools when Frame Control or the Devkit Client put them on
|
||||||
|
# the Frame, as a Steam Linux Runtime ARM64 title (Steam starts an ARM64 program natively).
|
||||||
|
# Registering again is harmless and refreshes the entry, as Valve's Devkit Client does each upload.
|
||||||
|
registered=$(on_frame "$game_dir" "$game_id" <<'EOF'
|
||||||
|
if [[ ! -f "$HOME/devkit-utils/steam-client-create-shortcut" ]]; then echo no-tools; exit 0; fi
|
||||||
|
parms=$(printf '{"gameid": "%s", "directory": "%s", "argv": ["%s"], "env": {}, "settings": {"steam_play": "0", "compat_tool": "SteamLinuxRuntime_4-arm64"}, "clear_settings": true, "force_appid": "", "lepton_args": ""}' "$2" "$HOME/$1" "$2")
|
||||||
|
reply=$(python3 "$HOME/devkit-utils/steam-client-create-shortcut" --parms "$parms" 2>/dev/null | tail -n 1)
|
||||||
|
case "$reply" in *'"success"'*) echo added ;; *) echo "failed $reply" ;; esac
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
case "$registered" in
|
||||||
|
added) note "it is in your Steam library" ;;
|
||||||
|
no-tools|failed*)
|
||||||
|
[[ "$registered" == failed* ]] && note "Steam did not take the shortcut: ${registered#failed }"
|
||||||
|
note "Add it to your Steam library once: in Frame Control, Send to Frame the folder"
|
||||||
|
note " $work_dir/out (name it $game_id), or on the Frame in Desktop Mode, Steam >"
|
||||||
|
note " Add a Non-Steam Game > ~/$game_dir/$game_id. Later runs of this script keep it updated." ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
say "Done"
|
||||||
|
note "Start $game_id from your library in the headset. Settings: left shoulder button, VR tab."
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@" </dev/null
|
||||||
@@ -31,11 +31,12 @@ C++ and compiled for the Frame's ARM64 CPU, and it renders through SteamVR's Ope
|
|||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
This is the whole way from a [release](https://github.com/mitch030504/Wiicompiled_VR_Frame/releases)
|
This is the whole way from your disc to playing in the headset. An install script does the work: it
|
||||||
and your disc to playing in the headset, building on an x86_64 Linux PC. Releases are source only:
|
downloads the newest [release](https://github.com/mitch030504/Wiicompiled_VR_Frame/releases),
|
||||||
the game is always built from your own disc, so there is nothing ready-built to download. The
|
extracts your disc, builds the game in an ARM64 container on your PC, copies it and the disc to the
|
||||||
first build takes a few hours, most of it compiling Dawn under emulation; later builds reuse it.
|
Frame, and adds it to your Steam library. Releases are source only: the game is always built from
|
||||||
[Other ways to build](#other-ways-to-build) covers a faster machine and the Frame itself.
|
your own disc, so there is nothing ready-built to download. The first build takes a few hours, most
|
||||||
|
of it compiling Dawn under emulation; later builds reuse it.
|
||||||
|
|
||||||
**You need:**
|
**You need:**
|
||||||
- a Steam Frame with Developer Mode on (Steam Settings → System → Enable Developer Mode, then set a
|
- a Steam Frame with Developer Mode on (Steam Settings → System → Enable Developer Mode, then set a
|
||||||
@@ -61,109 +62,43 @@ podman run --rm --platform linux/arm64 docker.io/library/debian:trixie uname -m
|
|||||||
The last command must print `aarch64`. On Debian or Ubuntu install `podman qemu-user-static
|
The last command must print `aarch64`. On Debian or Ubuntu install `podman qemu-user-static
|
||||||
binfmt-support` instead. If podman complains about subordinate ids, run
|
binfmt-support` instead. If podman complains about subordinate ids, run
|
||||||
`sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER` and log in again.
|
`sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER` and log in again.
|
||||||
|
Docker works too, in place of podman.
|
||||||
|
|
||||||
### 2. Download the release and extract your disc
|
### 2. Run the installer
|
||||||
|
|
||||||
Take the newest release from the [Releases](https://github.com/mitch030504/Wiicompiled_VR_Frame/releases)
|
With the path to your disc image and your Frame's address:
|
||||||
page; the commands use `frame-beta-1`, so put the newest release's tag in its place:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/wiicompiled/Wiicompiled_VR_Frame; cd ~/wiicompiled
|
curl -fsSL https://raw.githubusercontent.com/mitch030504/Wiicompiled_VR_Frame/openxr-work/Launcher/steam-frame-install.sh \
|
||||||
curl -fL https://github.com/mitch030504/Wiicompiled_VR_Frame/archive/refs/tags/frame-beta-1.tar.gz \
|
| bash -s -- --disc "/path/to/Mario Kart Wii.wbfs" --frame steamos@<frame-ip>
|
||||||
| tar -xz --strip-components=1 -C Wiicompiled_VR_Frame
|
|
||||||
curl -fL -o nodtool https://github.com/encounter/nod/releases/download/v2.0.0-alpha.10/nodtool-linux-x86_64
|
|
||||||
chmod +x nodtool
|
|
||||||
./nodtool extract "/path/to/Mario Kart Wii.wbfs" disc-extract
|
|
||||||
mkdir -p Wiicompiled_VR_Frame/Assets
|
|
||||||
cp disc-extract/sys/main.dol disc-extract/files/rel/StaticR.rel Wiicompiled_VR_Frame/Assets/
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`disc-extract` must hold `sys/` and `files/` directly; keep it, the game reads it when it runs.
|
- It asks for the Frame's password when it gets there. If you use
|
||||||
|
[Frame Control](https://github.com/saphid/frame-control), pass `--frame frame` instead: its SSH
|
||||||
|
key answers to that name.
|
||||||
|
- Everything it builds lives in `~/wiicompiled-frame` (`--work-dir` to change that): the toolchain,
|
||||||
|
Dawn, the source, the extracted disc and the build log, `build.log`.
|
||||||
|
- It runs as many compiles at once as fit in memory (a quarter of your memory in GB). If the machine
|
||||||
|
still freezes, run it again with a lower `--jobs`, such as `--jobs 2`.
|
||||||
|
- If it stops for any reason, the same command picks up where it left off.
|
||||||
|
- On the Frame, the game goes to `~/devkit-game/WiiCompiled/` and the disc to `~/wiicompiled/disc`.
|
||||||
|
It is added to your Steam library through Valve's devkit tools in `~/devkit-utils`, which Frame
|
||||||
|
Control and Valve's Devkit Client put there. Without them, the script says how to add it once
|
||||||
|
yourself. Steam must be running on the Frame for this step.
|
||||||
|
- `--help` lists every option. From a downloaded release, run `Launcher/steam-frame-install.sh`
|
||||||
|
with the same options: it then builds that release's source.
|
||||||
|
|
||||||
### 3. Build, inside an ARM64 container
|
### 3. Play
|
||||||
|
|
||||||
```bash
|
|
||||||
podman run -it --name wiicompiled-frame --platform linux/arm64 -v ~/wiicompiled:/work docker.io/library/debian:trixie bash
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, in the container's bash prompt:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
ca-certificates curl git python3 xz-utils unzip file pkg-config g++ binutils libicu-dev zlib1g-dev \
|
|
||||||
libvulkan-dev libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxrandr-dev libxinerama-dev \
|
|
||||||
libxcursor-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev libwayland-dev wayland-protocols \
|
|
||||||
libdecor-0-dev libegl-dev libgl-dev libgles-dev libdrm-dev libgbm-dev libasound2-dev libpulse-dev \
|
|
||||||
libpipewire-0.3-dev libudev-dev libdbus-1-dev libusb-1.0-0-dev
|
|
||||||
cd /work/Wiicompiled_VR_Frame
|
|
||||||
Launcher/prepare-portable-tools.sh --arch aarch64 --destination /work/tools # clang 22, CMake, Ninja
|
|
||||||
T=/work/tools/toolchain-aarch64/bin
|
|
||||||
curl -fsSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 8.0 --install-dir /work/dotnet
|
|
||||||
Launcher/build-dawn-linux.sh --work-dir /work/dawn --cc $T/clang --cxx $T/clang++ \
|
|
||||||
--cmake $T/cmake --ninja $T/ninja --jobs 4 2>&1 | tee -a /work/dawn.log
|
|
||||||
Launcher/local-build.sh --output-dir /work/out --cc $T/clang --cxx $T/clang++ --fuse-ld lld \
|
|
||||||
--cmake $T/cmake --ninja $T/ninja --dotnet /work/dotnet/dotnet --parallel 4 \
|
|
||||||
--openxr --dawn-package /work/dawn/package --headset steam_frame 2>&1 | tee -a /work/game.log
|
|
||||||
exit
|
|
||||||
```
|
|
||||||
|
|
||||||
- Dawn is done when it prints `Patched Dawn for Linux ready`, the game when it prints
|
|
||||||
`MKWCBUILD:OUTPUT=/work/out`.
|
|
||||||
- `--jobs 4` and `--parallel 4` suit 16 GB of memory. Compiles take more memory under emulation, and
|
|
||||||
16 at once froze a 16 GB laptop. Use 8 with 32 GB.
|
|
||||||
- If it stops, `podman start -ai wiicompiled-frame` gets you back in. Run `cd /work/Wiicompiled_VR_Frame;
|
|
||||||
T=/work/tools/toolchain-aarch64/bin`, then the step that stopped: both scripts resume.
|
|
||||||
|
|
||||||
### 4. Install on the Frame
|
|
||||||
|
|
||||||
The easiest way is [Frame Control](https://github.com/saphid/frame-control): set up its connection
|
|
||||||
to the Frame, then drag `~/wiicompiled/out` onto **Send to Frame**. Name it `WiiCompiled` and keep
|
|
||||||
**Launches** on `WiiCompiled`. It adds the game to your Steam library, in `~/devkit-game/WiiCompiled/`
|
|
||||||
on the Frame.
|
|
||||||
|
|
||||||
Then copy the disc over and, on a first install, tell the game where it is (Frame Control's SSH
|
|
||||||
key answers to `frame`; use `steamos@<frame-ip>` otherwise):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh frame mkdir -p wiicompiled
|
|
||||||
scp -r ~/wiicompiled/disc-extract frame:wiicompiled/disc
|
|
||||||
ssh frame 'mkdir -p ~/.local/share/WiiCompiled && printf "[paths]\ndvd_root = \"/home/steamos/wiicompiled/disc\"\n" > ~/.local/share/WiiCompiled/Config.toml'
|
|
||||||
```
|
|
||||||
|
|
||||||
Without Frame Control, `scp -r ~/wiicompiled/out frame:wiicompiled/` and start
|
|
||||||
`~/wiicompiled/out/WiiCompiled` from a terminal in the Frame's Desktop Mode, with SteamVR running.
|
|
||||||
|
|
||||||
### 5. Play
|
|
||||||
|
|
||||||
Start **WiiCompiled** from the library in the headset. Open the settings panel with the left
|
Start **WiiCompiled** from the library in the headset. Open the settings panel with the left
|
||||||
shoulder button, go to the **VR** tab and set the [recommended settings](#recommended-settings).
|
shoulder button, go to the **VR** tab and set the [recommended settings](#recommended-settings).
|
||||||
|
|
||||||
### Updating
|
### Updating
|
||||||
|
|
||||||
When a new release comes out, put its changed files over the old source, rebuild, and replace only
|
Run the same command again; you can leave out `--disc`. The script downloads the newest release,
|
||||||
the executable. `rsync -c` copies just the files whose content changed and stamps them with the
|
puts only the files that changed over the old source, rebuilds what they touch, and replaces the
|
||||||
current time, so the build recompiles exactly those. Unpacking over the source would restore each
|
game on the Frame. Dawn is only rebuilt when a release changes its patches (the release notes say
|
||||||
file's commit date, which can be older than the last build, and changes would be skipped. Your
|
so), so an update usually takes minutes. `--release <tag>` builds a given release instead.
|
||||||
`Assets/` and build folders stay. Install `rsync` if your system lacks it, and put the new release's
|
|
||||||
tag in place of `frame-beta-2`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ~/wiicompiled
|
|
||||||
mkdir -p release-new
|
|
||||||
curl -fL https://github.com/mitch030504/Wiicompiled_VR_Frame/archive/refs/tags/frame-beta-2.tar.gz \
|
|
||||||
| tar -xz --strip-components=1 -C release-new
|
|
||||||
rsync -rcE release-new/ Wiicompiled_VR_Frame/
|
|
||||||
rm -rf release-new
|
|
||||||
podman start -ai wiicompiled-frame
|
|
||||||
# in the container: cd /work/Wiicompiled_VR_Frame; T=/work/tools/toolchain-aarch64/bin, then the
|
|
||||||
# build-dawn-linux.sh and local-build.sh lines from step 3, then exit. Dawn only rebuilds when the
|
|
||||||
# release changed its patches (the release notes say so); otherwise both finish quickly.
|
|
||||||
scp ~/wiicompiled/out/WiiCompiled frame:devkit-game/WiiCompiled/WiiCompiled.new
|
|
||||||
ssh frame 'cd ~/devkit-game/WiiCompiled && chmod 755 WiiCompiled.new && mv -f WiiCompiled.new WiiCompiled'
|
|
||||||
```
|
|
||||||
|
|
||||||
The executable is copied under a new name and moved into place, which works even while an old copy
|
|
||||||
is open.
|
|
||||||
|
|
||||||
## Recommended settings
|
## Recommended settings
|
||||||
|
|
||||||
@@ -238,43 +173,145 @@ frames means the GPU is over budget: lower `render_scale` or `resolution_multipl
|
|||||||
|
|
||||||
**Crashes.** `console.log` then names the faulting thread and gives its pc and a backtrace as
|
**Crashes.** `console.log` then names the faulting thread and gives its pc and a backtrace as
|
||||||
`module+offset`. On the build machine,
|
`module+offset`. On the build machine,
|
||||||
`addr2line -f -C -e Wiicompiled_VR_Frame/native-build/WiiCompiled 0x<offset>` turns an offset in
|
`addr2line -f -C -e ~/wiicompiled-frame/source/native-build/WiiCompiled 0x<offset>` turns an offset
|
||||||
`WiiCompiled` into a function: the executable is not stripped.
|
in `WiiCompiled` into a function: the executable is not stripped. (Built by hand, the executable is
|
||||||
|
in `~/wiicompiled/Wiicompiled_VR_Frame/native-build/`.)
|
||||||
|
|
||||||
**Building.** A build that freezes the machine has run out of memory: lower `--jobs` or
|
**Building.** The install script's log is `~/wiicompiled-frame/build.log`; its end says why a build
|
||||||
`--parallel`. A missing CMake package means installing its `-dev` package in the container and
|
stopped. A build that freezes the machine has run out of memory: lower `--jobs` (or, by hand,
|
||||||
|
`--parallel`). A missing CMake package means installing its `-dev` package in the container and
|
||||||
running the same command again.
|
running the same command again.
|
||||||
|
|
||||||
|
## Building by hand
|
||||||
|
|
||||||
|
These are the steps the install script runs, for when you want to see or change each one. Set up
|
||||||
|
emulation as in [Quick start](#quick-start) step 1 first.
|
||||||
|
|
||||||
|
### 1. Download the release and extract your disc
|
||||||
|
|
||||||
|
Take the newest release from the [Releases](https://github.com/mitch030504/Wiicompiled_VR_Frame/releases)
|
||||||
|
page; the commands use `frame-beta-1`, so put the newest release's tag in its place:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/wiicompiled/Wiicompiled_VR_Frame; cd ~/wiicompiled
|
||||||
|
curl -fL https://github.com/mitch030504/Wiicompiled_VR_Frame/archive/refs/tags/frame-beta-1.tar.gz \
|
||||||
|
| tar -xz --strip-components=1 -C Wiicompiled_VR_Frame
|
||||||
|
curl -fL -o nodtool https://github.com/encounter/nod/releases/download/v2.0.0-alpha.10/nodtool-linux-x86_64
|
||||||
|
chmod +x nodtool
|
||||||
|
./nodtool extract "/path/to/Mario Kart Wii.wbfs" disc-extract
|
||||||
|
mkdir -p Wiicompiled_VR_Frame/Assets
|
||||||
|
cp disc-extract/sys/main.dol disc-extract/files/rel/StaticR.rel Wiicompiled_VR_Frame/Assets/
|
||||||
|
```
|
||||||
|
|
||||||
|
`disc-extract` must hold `sys/` and `files/` directly; keep it, the game reads it when it runs.
|
||||||
|
|
||||||
|
### 2. Build, inside an ARM64 container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
podman run -it --name wiicompiled-frame --platform linux/arm64 -v ~/wiicompiled:/work docker.io/library/debian:trixie bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, in the container's bash prompt:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates curl git python3 xz-utils unzip file pkg-config g++ binutils libicu-dev zlib1g-dev \
|
||||||
|
libvulkan-dev libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxrandr-dev libxinerama-dev \
|
||||||
|
libxcursor-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev libwayland-dev wayland-protocols \
|
||||||
|
libdecor-0-dev libegl-dev libgl-dev libgles-dev libdrm-dev libgbm-dev libasound2-dev libpulse-dev \
|
||||||
|
libpipewire-0.3-dev libudev-dev libdbus-1-dev libusb-1.0-0-dev
|
||||||
|
cd /work/Wiicompiled_VR_Frame
|
||||||
|
Launcher/prepare-portable-tools.sh --arch aarch64 --destination /work/tools # clang 22, CMake, Ninja
|
||||||
|
T=/work/tools/toolchain-aarch64/bin
|
||||||
|
curl -fsSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 8.0 --install-dir /work/dotnet
|
||||||
|
Launcher/build-dawn-linux.sh --work-dir /work/dawn --cc $T/clang --cxx $T/clang++ \
|
||||||
|
--cmake $T/cmake --ninja $T/ninja --jobs 4 2>&1 | tee -a /work/dawn.log
|
||||||
|
Launcher/local-build.sh --output-dir /work/out --cc $T/clang --cxx $T/clang++ --fuse-ld lld \
|
||||||
|
--cmake $T/cmake --ninja $T/ninja --dotnet /work/dotnet/dotnet --parallel 4 \
|
||||||
|
--openxr --dawn-package /work/dawn/package --headset steam_frame 2>&1 | tee -a /work/game.log
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
- Dawn is done when it prints `Patched Dawn for Linux ready`, the game when it prints
|
||||||
|
`MKWCBUILD:OUTPUT=/work/out`.
|
||||||
|
- `--jobs 4` and `--parallel 4` suit 16 GB of memory. Compiles take more memory under emulation, and
|
||||||
|
16 at once froze a 16 GB laptop. Use 8 with 32 GB.
|
||||||
|
- If it stops, `podman start -ai wiicompiled-frame` gets you back in. Run `cd /work/Wiicompiled_VR_Frame;
|
||||||
|
T=/work/tools/toolchain-aarch64/bin`, then the step that stopped: both scripts resume.
|
||||||
|
|
||||||
|
### 3. Install on the Frame
|
||||||
|
|
||||||
|
The easiest way is [Frame Control](https://github.com/saphid/frame-control): set up its connection
|
||||||
|
to the Frame, then drag `~/wiicompiled/out` onto **Send to Frame**. Name it `WiiCompiled` and keep
|
||||||
|
**Launches** on `WiiCompiled`. It adds the game to your Steam library, in `~/devkit-game/WiiCompiled/`
|
||||||
|
on the Frame.
|
||||||
|
|
||||||
|
Then copy the disc over and, on a first install, tell the game where it is (Frame Control's SSH
|
||||||
|
key answers to `frame`; use `steamos@<frame-ip>` otherwise):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh frame mkdir -p wiicompiled
|
||||||
|
scp -r ~/wiicompiled/disc-extract frame:wiicompiled/disc
|
||||||
|
ssh frame 'mkdir -p ~/.local/share/WiiCompiled && printf "[paths]\ndvd_root = \"/home/steamos/wiicompiled/disc\"\n" > ~/.local/share/WiiCompiled/Config.toml'
|
||||||
|
```
|
||||||
|
|
||||||
|
Without Frame Control, `scp -r ~/wiicompiled/out frame:wiicompiled/` and start
|
||||||
|
`~/wiicompiled/out/WiiCompiled` from a terminal in the Frame's Desktop Mode, with SteamVR running.
|
||||||
|
|
||||||
|
### Updating by hand
|
||||||
|
|
||||||
|
When a new release comes out, put its changed files over the old source, rebuild, and replace only
|
||||||
|
the executable. `rsync -c` copies just the files whose content changed and stamps them with the
|
||||||
|
current time, so the build recompiles exactly those. Unpacking over the source would restore each
|
||||||
|
file's commit date, which can be older than the last build, and changes would be skipped. Your
|
||||||
|
`Assets/` and build folders stay. Install `rsync` if your system lacks it, and put the new release's
|
||||||
|
tag in place of `frame-beta-2`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/wiicompiled
|
||||||
|
mkdir -p release-new
|
||||||
|
curl -fL https://github.com/mitch030504/Wiicompiled_VR_Frame/archive/refs/tags/frame-beta-2.tar.gz \
|
||||||
|
| tar -xz --strip-components=1 -C release-new
|
||||||
|
rsync -rcE release-new/ Wiicompiled_VR_Frame/
|
||||||
|
rm -rf release-new
|
||||||
|
podman start -ai wiicompiled-frame
|
||||||
|
# in the container: cd /work/Wiicompiled_VR_Frame; T=/work/tools/toolchain-aarch64/bin, then the
|
||||||
|
# build-dawn-linux.sh and local-build.sh lines from step 2, then exit. Dawn only rebuilds when the
|
||||||
|
# release changed its patches (the release notes say so); otherwise both finish quickly.
|
||||||
|
scp ~/wiicompiled/out/WiiCompiled frame:devkit-game/WiiCompiled/WiiCompiled.new
|
||||||
|
ssh frame 'cd ~/devkit-game/WiiCompiled && chmod 755 WiiCompiled.new && mv -f WiiCompiled.new WiiCompiled'
|
||||||
|
```
|
||||||
|
|
||||||
|
The executable is copied under a new name and moved into place, which works even while an old copy
|
||||||
|
is open.
|
||||||
|
|
||||||
## Other ways to build
|
## Other ways to build
|
||||||
|
|
||||||
**On the Frame itself.** SteamOS's root file system is read-only, but it ships podman. Over SSH,
|
**On the Frame itself.** SteamOS's root file system is read-only, but it ships podman, and the
|
||||||
with the newest release's tag:
|
install script runs there too. Over SSH (`ssh steamos@<frame-ip>`), or in a Desktop Mode terminal:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/wiicompiled/Wiicompiled_VR_Frame && cd ~/wiicompiled
|
curl -fsSL https://raw.githubusercontent.com/mitch030504/Wiicompiled_VR_Frame/openxr-work/Launcher/steam-frame-install.sh \
|
||||||
curl -fL https://github.com/mitch030504/Wiicompiled_VR_Frame/archive/refs/tags/frame-beta-1.tar.gz \
|
| bash -s -- --disc "/path/to/Mario Kart Wii.wbfs" --frame local
|
||||||
| tar -xz --strip-components=1 -C Wiicompiled_VR_Frame
|
|
||||||
podman run -it --name wiicompiled-frame -v ~/wiicompiled:/work:Z docker.io/library/debian:trixie bash
|
|
||||||
```
|
```
|
||||||
|
|
||||||
It is native ARM64, so no emulation, but the Frame has less memory and cooling than a PC. Extract
|
It is native ARM64, so no emulation, but the Frame has less memory and cooling than a PC; keep it
|
||||||
your disc as in step 2, with `nodtool-linux-aarch64` instead of `nodtool-linux-x86_64`, copy
|
on its charger. The game then reads the disc straight from `~/wiicompiled-frame/disc`. By hand, the
|
||||||
`main.dol` and `StaticR.rel` into `Assets/`, and run step 3's commands in the container. The game
|
steps under [Building by hand](#building-by-hand) work the same in a container started without
|
||||||
lands in `~/wiicompiled/out`.
|
`--platform linux/arm64`, with `nodtool-linux-aarch64` in place of `nodtool-linux-x86_64`.
|
||||||
|
|
||||||
**With Docker on a stronger machine** (a server, for example). The same container and commands
|
**On a stronger machine** (a server, for example). The script works with Docker as well as podman,
|
||||||
work, and much faster with more cores and memory. Copy `~/wiicompiled` over without Dawn's build
|
and runs much faster with more cores and memory. A machine that cannot reach the Frame builds
|
||||||
tree, and run the build detached so a closed SSH session does not stop it:
|
without `--frame`; give it more compiles at once if it has the memory, `--jobs 8` for 32 GB:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
rsync -a --exclude dawn/build --exclude 'dawn/dawn-*' --exclude disc-extract \
|
curl -fsSL https://raw.githubusercontent.com/mitch030504/Wiicompiled_VR_Frame/openxr-work/Launcher/steam-frame-install.sh \
|
||||||
~/wiicompiled/ root@<server>:/srv/wiicompiled/ # from the PC
|
| bash -s -- --disc "/path/to/Mario Kart Wii.wbfs" --jobs 8
|
||||||
docker run -d --name wiicompiled-frame --platform linux/arm64 -v /srv/wiicompiled:/work \
|
|
||||||
debian:trixie bash -c 'bash /work/build-game.sh >> /work/game.log 2>&1'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`build-game.sh` holds step 3's `apt-get` line and `local-build.sh` command, with `--parallel 8` for
|
Run it in `tmux` or `screen` so a closed SSH session does not stop it. Copy `~/wiicompiled-frame/out`
|
||||||
32 GB. `docker start wiicompiled-frame` runs it again after an update.
|
and `~/wiicompiled-frame/disc` back to the PC, send `out` to the Frame with Frame Control and copy
|
||||||
|
the disc over as in [Install on the Frame](#3-install-on-the-frame).
|
||||||
|
|
||||||
On some hosts, for example Unraid 7 with kernel 6.18, `binfmt_misc` registrations are per container.
|
On some hosts, for example Unraid 7 with kernel 6.18, `binfmt_misc` registrations are per container.
|
||||||
`tonistiigi/binfmt --install arm64` then reports success, but Debian answers `exec format error`.
|
`tonistiigi/binfmt --install arm64` then reports success, but Debian answers `exec format error`.
|
||||||
|
|||||||
Reference in new issue
Block a user