#!/usr/bin/env bash # Compila o Dave Gnukem do fredygames.com (David Joffe; codigo e quase todos os dados sob MIT ou GPL, a # escolha e de quem usa; aqui, MIT) em WebAssembly, com o Emscripten 6.0.10 e as portas SDL2 2.32.10 e # SDL2_mixer 2.8.0 dele. Este script, o patch e o gerador do som de saida (dave-gnukem/) fazem parte do # codigo-fonte publicado junto do jogo. # # source /emsdk_env.sh # emsdk install 6.0.10 && emsdk activate 6.0.10 # src/FredGames.Bundler/Builds/build-dave-gnukem.sh # # Fonte: os tarballs dos commits fbda206 (davidjoffe/dave_gnukem) e b50a69c (davidjoffe/gnukem_data), # conferidos pelo SHA-256 e guardados em artifacts/cache/dave-gnukem/. # # dave-gnukem/gnukem-fredygames.patch: # - teclas iniciais: pular = Z e atirar = X (o padrao do jogo, Ctrl e Alt, e tomado por atalhos do # navegador e do sistema); as teclas continuam redefiniveis no menu; # - o som de saida e o exit.wav (ver abaixo), no lugar do exit.ogg; # - djiPoll espera 1 ms (SDL_Delay), para os lacos que consultam o teclado sem esperar (como o que # aguarda soltar o Esc ao abrir o menu) devolverem o controle ao navegador (ASYNCIFY). # Depois do patch, o script troca, nos fontes do jogo, o nome da macro __EMSCRIPTEN__ (desvios de um port # antigo para Emscripten + SDL 1) por outro que nunca existe, para valer o caminho normal do codigo. # Fica de fora toda a pasta music/ e o sons/exit.ogg: sao de Eric Matyas (soundimage.org), cujos termos de # uso nao estao no repositorio do jogo. O som de saida vem de dave-gnukem/make-exit-sound.py (CC0). Fora # tambem o icon/ e o README.md dos dados (o texto de licencas dele vai no LICENSE.txt do jogo). # Os dados vao num davegnukem.data que o proprio Emscripten carrega (--preload-file) em /data; as # configuracoes e recordes ficam em /home/web_user/.gnukem, que a pagina monta no IndexedDB. # # Saida: artifacts/build/dave-gnukem-fbda206/davegnukem.{js,wasm,data}, que o bundle.yaml do jogo confere # pelo SHA-256. set -euo pipefail CODE_COMMIT=fbda206d0aac575146b01179330484ccf1569aab CODE_SHA256=9866c20f49f8f8324eff0c579999625cd2d9d2ec2724deed620466231bf81895 DATA_COMMIT=b50a69cbe864f6f8e30c82d719f7e46c57d9ad38 DATA_SHA256=19fcae84f7da00daf967a60cc9193400d329566f8aaa3b48743508a134a4ee8e EMSCRIPTEN=6.0.10 here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" root="$(git -C "$here" rev-parse --show-toplevel 2>/dev/null || pwd)" out="$root/artifacts/build/dave-gnukem-${CODE_COMMIT:0:7}" cache="$root/artifacts/cache/dave-gnukem" if ! emcc --version 2>/dev/null | head -1 | grep -q " $EMSCRIPTEN "; then echo "Precisa do Emscripten $EMSCRIPTEN no PATH (source /emsdk_env.sh)." >&2 exit 1 fi fetch() { # arquivo url sha256 if [ ! -f "$cache/$1" ]; then mkdir -p "$cache" curl -fsSL -o "$cache/$1.part" "$2" mv "$cache/$1.part" "$cache/$1" fi echo "$3 $cache/$1" | shasum -a 256 -c - >&2 } fetch dave_gnukem.tar.gz "https://github.com/davidjoffe/dave_gnukem/archive/$CODE_COMMIT.tar.gz" "$CODE_SHA256" fetch gnukem_data.tar.gz "https://github.com/davidjoffe/gnukem_data/archive/$DATA_COMMIT.tar.gz" "$DATA_SHA256" rm -rf "$out" mkdir -p "$out/work/obj" tar xzf "$cache/dave_gnukem.tar.gz" -C "$out/work" tar xzf "$cache/gnukem_data.tar.gz" -C "$out/work" G="$out/work/dave_gnukem-$CODE_COMMIT" D="$out/work/gnukem_data-$DATA_COMMIT" patch -d "$G" -p1 --binary --no-backup-if-mismatch < "$here/dave-gnukem/gnukem-fredygames.patch" >&2 # O jogo tem desvios para um port antigo para Emscripten + SDL 1 (#ifdef __EMSCRIPTEN__: SDL_Delay desligado, # laco de menu por emscripten_set_main_loop, cabecalhos SDL/SDL.h). Esta build usa SDL2 e ASYNCIFY, entao # o caminho normal do codigo e o certo: o nome da macro e trocado nos fontes do jogo por um que nunca existe. grep -rl "__EMSCRIPTEN__" "$G/src" --include='*.cpp' --include='*.h' | xargs perl -pi -e 's/__EMSCRIPTEN__/DJ_SDL1_EMSCRIPTEN_WORKAROUNDS/g' rm -rf "$D/music" "$D/sounds/exit.ogg" "$D/icon" "$D/README.md" python3 -I "$here/dave-gnukem/make-exit-sound.py" "$D/sounds/exit.wav" PORTS=(-sUSE_SDL=2 -sUSE_SDL_MIXER=2 -sSDL2_MIXER_FORMATS='["wav"]') FLAGS=(-O2 -w -std=c++14 -include cstdlib -ffile-prefix-map="$out/work/=" "${PORTS[@]}" -I"$G/src" -DDATA_DIR='"/data/"' -DVERSION='"v1.0.3 - 29 Nov 2022"') objs=() jobs=0 add() { # arquivo local f="$1" rel o rel="${f#"$out/work/"}" o="$out/work/obj/${rel//\//_}.o" objs+=("$o") em++ "${FLAGS[@]}" -c "$f" -o "$o" & jobs=$((jobs + 1)) if [ "$jobs" -ge 8 ]; then wait; jobs=0; fi } # A lista do Makefile do jogo, sem os arquivos do Windows (win32/). for f in block bullet console credits datadir djfile djfonts djimageload djimage djlang djlog djsprite \ djstring djtypes djutf8 ed_common ed_DrawBoxContents ed_lvled ed_macros ed ed_spred \ effect_viewportshadow gameending game graph hero hiscores instructions inventory keys level \ loadedlevel localization/djgettext mainmenu main menu mission mixins m_misc sdl/djgraph \ sdl/djinput sdl/djsound sdl/djtime settings sys_error sys_log thing_monsters thing; do add "$G/src/$f.cpp" done wait for o in "${objs[@]}"; do [ -f "$o" ] || { echo "Falhou: $o" >&2; exit 1; }; done # Liga de dentro da pasta de saida, com caminhos relativos. mkdir -p "$out/data" cp -R "$D/." "$out/data/" ( cd "$out" em++ -O2 ${LINK_EXTRA:-} "${objs[@]}" "${PORTS[@]}" -lidbfs.js -sASYNCIFY -sALLOW_MEMORY_GROWTH=1 \ -sENVIRONMENT=web -sEXIT_RUNTIME=1 \ -sEXPORTED_RUNTIME_METHODS=FS,ENV,addRunDependency,removeRunDependency \ --preload-file data@/data \ -o davegnukem.js ) rm -rf "$out/data" "$out/work" shasum -a 256 "$out/davegnukem.js" "$out/davegnukem.wasm" "$out/davegnukem.data"