mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-30 07:37:38 +00:00
doomgeneric compiled to wasm32-wasi plus the Freedoom Phase 1 IWAD, packed into one self-contained index.html that publishes as a NIP-5D napplet and runs inside Amethyst's existing sandbox and CSP unchanged. - build.sh: pinned wasi-sdk, Freedoom and doomgeneric; reproducible artifact hash. IWAD=/TITLE= swap in another IWAD. - The page supplies a WASI in-memory file system, the frame buffer, keyboard, touch and gamepad input, Web Audio sound effects, a small MIDI synth for the music, and keeps saves in window.napplet.storage. - doomgeneric.patch makes the screen melt non-blocking and clears the frame buffer before the first melt. - doom.test.mjs plays it in headless Chromium inside the production shell.html, shim.js and CSP: boot, music, gameplay, save and reload through storage, denied and undeclared storage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NQ76C3uhMzzWRfB6NNxYzf
116 lines
5.1 KiB
Bash
Executable File
116 lines
5.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Builds the Freedoom napplet: doomgeneric compiled to wasm32-wasi with wasi-sdk, plus the
|
|
# Freedoom Phase 1 IWAD, packed into one self-contained index.html.
|
|
#
|
|
# tools/napplet-doom/build.sh # -> tools/napplet-doom/build/index.html
|
|
# IWAD=~/doom1.wad TITLE=Doom tools/napplet-doom/build.sh # another IWAD you may redistribute
|
|
#
|
|
# Every input is pinned (a git commit or a sha256), so the same inputs give the same artifact
|
|
# hash, and anyone can rebuild a published napplet and compare its `x` tag.
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
WORK="${WORK:-$HERE/build}"
|
|
OUT="${OUT:-$WORK/index.html}"
|
|
|
|
DOOMGENERIC_REPO=https://github.com/ozkl/doomgeneric
|
|
DOOMGENERIC_COMMIT=e257a09527062bfb986b6e5e0780839b6cbd5b71
|
|
|
|
FREEDOOM_VERSION=0.13.0
|
|
FREEDOOM_SHA256=3f9b264f3e3ce503b4fb7f6bdcb1f419d93c7b546f4df3e874dd878db9688f59
|
|
|
|
WASI_SDK_VERSION=25
|
|
case "$(uname -s)-$(uname -m)" in
|
|
Linux-x86_64) WASI_SDK_HOST=x86_64-linux WASI_SDK_SHA256=52640dde13599bf127a95499e61d6d640256119456d1af8897ab6725bcf3d89c ;;
|
|
Linux-aarch64 | Linux-arm64) WASI_SDK_HOST=arm64-linux WASI_SDK_SHA256=47fccad8b2498f2239e05e1115c3ffc652bf37e7de2f88fb64b2d663c976ce2d ;;
|
|
Darwin-x86_64) WASI_SDK_HOST=x86_64-macos WASI_SDK_SHA256=55e3ff3fee1a15678a16eeccba0129276c9f6be481bc9c283e7f9f65bf055c11 ;;
|
|
Darwin-arm64) WASI_SDK_HOST=arm64-macos WASI_SDK_SHA256=e1e529ea226b1db0b430327809deae9246b580fa3cae32d31c82dfe770233587 ;;
|
|
*) echo "No pinned wasi-sdk for $(uname -s)-$(uname -m)" >&2; exit 1 ;;
|
|
esac
|
|
|
|
sha256() {
|
|
if command -v sha256sum > /dev/null; then sha256sum "$1" | cut -d' ' -f1; else shasum -a 256 "$1" | cut -d' ' -f1; fi
|
|
}
|
|
|
|
# fetch URL FILE SHA256: download once, then always verify.
|
|
fetch() {
|
|
if [ ! -f "$2" ]; then
|
|
echo "Downloading $1"
|
|
curl -fsSL -o "$2.part" "$1"
|
|
mv "$2.part" "$2"
|
|
fi
|
|
local actual
|
|
actual="$(sha256 "$2")"
|
|
if [ "$actual" != "$3" ]; then
|
|
echo "sha256 mismatch for $2: expected $3, got $actual" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
mkdir -p "$WORK"
|
|
cd "$WORK"
|
|
|
|
# ---- Toolchain -------------------------------------------------------------------------------
|
|
SDK_DIR="wasi-sdk-$WASI_SDK_VERSION.0-$WASI_SDK_HOST"
|
|
fetch "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/$SDK_DIR.tar.gz" \
|
|
"$SDK_DIR.tar.gz" "$WASI_SDK_SHA256"
|
|
[ -d "$SDK_DIR" ] || tar xzf "$SDK_DIR.tar.gz"
|
|
CC="$WORK/$SDK_DIR/bin/clang"
|
|
SYSROOT="$WORK/$SDK_DIR/share/wasi-sysroot"
|
|
|
|
# ---- IWAD ------------------------------------------------------------------------------------
|
|
# Freedoom by default. IWAD=path swaps in another one; whether you may publish it is up to you.
|
|
if [ -n "${IWAD:-}" ]; then
|
|
WAD="$IWAD"
|
|
TITLE="${TITLE:-Doom}"
|
|
else
|
|
fetch "https://github.com/freedoom/freedoom/releases/download/v$FREEDOOM_VERSION/freedoom-$FREEDOOM_VERSION.zip" \
|
|
"freedoom-$FREEDOOM_VERSION.zip" "$FREEDOOM_SHA256"
|
|
unzip -q -o "freedoom-$FREEDOOM_VERSION.zip" "freedoom-$FREEDOOM_VERSION/freedoom1.wad" "freedoom-$FREEDOOM_VERSION/COPYING.txt"
|
|
WAD="$WORK/freedoom-$FREEDOOM_VERSION/freedoom1.wad"
|
|
TITLE="${TITLE:-Freedoom}"
|
|
fi
|
|
|
|
# ---- Engine ----------------------------------------------------------------------------------
|
|
if [ ! -d doomgeneric/.git ]; then
|
|
git init -q doomgeneric
|
|
git -C doomgeneric remote add origin "$DOOMGENERIC_REPO"
|
|
fi
|
|
git -C doomgeneric fetch -q --depth 1 origin "$DOOMGENERIC_COMMIT"
|
|
git -C doomgeneric checkout -q --force FETCH_HEAD
|
|
git -C doomgeneric clean -q -fdx
|
|
git -C doomgeneric apply "$HERE/src/doomgeneric.patch"
|
|
|
|
SRC="$WORK/doomgeneric/doomgeneric"
|
|
# The engine sources of doomgeneric's Emscripten build, minus its SDL front end and SDL sound.
|
|
ENGINE="dummy am_map doomdef doomstat dstrings d_event d_items d_iwad d_loop d_main d_mode d_net
|
|
f_finale f_wipe g_game hu_lib hu_stuff info i_cdmus i_endoom i_joystick i_scale i_sound i_system
|
|
i_timer memio m_argv m_bbox m_cheat m_config m_controls m_fixed m_menu m_misc m_random p_ceilng
|
|
p_doors p_enemy p_floor p_inter p_lights p_map p_maputl p_mobj p_plats p_pspr p_saveg p_setup
|
|
p_sight p_spec p_switch p_telept p_tick p_user r_bsp r_data r_draw r_main r_plane r_segs r_sky
|
|
r_things sha1 sounds statdump st_lib st_stuff s_sound tables v_video wi_stuff w_checksum w_file
|
|
w_main w_wad z_zone w_file_stdc i_input i_video doomgeneric mus2mid"
|
|
|
|
# i_sound.c includes SDL_mixer.h under FEATURE_SOUND without using it.
|
|
mkdir -p stub obj
|
|
: > stub/SDL_mixer.h
|
|
|
|
CFLAGS=(--target=wasm32-wasip1 "--sysroot=$SYSROOT" -O2 -w
|
|
-DFEATURE_SOUND -DDOOMGENERIC_RESX=320 -DDOOMGENERIC_RESY=200
|
|
-D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_PROCESS_CLOCKS
|
|
-I"$WORK/stub" -I"$SRC")
|
|
|
|
rm -f obj/*.o
|
|
echo "Compiling doomgeneric ($DOOMGENERIC_COMMIT)"
|
|
for name in $ENGINE; do
|
|
"$CC" "${CFLAGS[@]}" -c "$SRC/$name.c" -o "obj/$name.o"
|
|
done
|
|
"$CC" "${CFLAGS[@]}" -Wall -c "$HERE/src/doomgeneric_napplet.c" -o obj/doomgeneric_napplet.o
|
|
|
|
# A reactor: the page calls _initialize, then dg_start and dg_tick, instead of a blocking main().
|
|
"$CC" --target=wasm32-wasip1 "--sysroot=$SYSROOT" -O2 -mexec-model=reactor \
|
|
-lwasi-emulated-signal -lwasi-emulated-process-clocks \
|
|
obj/*.o -o doom.wasm
|
|
|
|
python3 "$HERE/assemble.py" "$HERE/src/index.template.html" doom.wasm "$WAD" "$OUT" "$TITLE"
|