#!/usr/bin/env bash # Compila o Domino Chain do fredygames.com: o jogo de puzzle de dominos de Andreas Roever, Volker # Diels-Grabsch e colaboradores (codigo, graficos dos temas de Harald Radke e musicas de Roberto Lorenz sob a # GPL-3.0-or-later, como o AUTHORS e o debian/copyright do Debian main registram) em WebAssembly, com o # Emscripten 6.0.10 e as portas SDL2 2.32.10, SDL2_mixer 2.8.0 (libogg, libvorbis), SDL2_ttf 2.20.2 # (FreeType, HarfBuzz), libpng e zlib dele, mais o Lua 5.2.4. Este script e o patch 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-domino-chain.sh # # Fonte: o tarball da tag 1.1 do GitLab do projeto (o mesmo arquivo que o Debian usa como # pushover_1.1.orig.tar.gz), conferido pelo SHA-256 e guardado em artifacts/cache/domino-chain/. O site # hospeda esse tarball sem src/levels/original/ e src/recordings/finish/original/ (as fases do jogo # comercial de 1992 convertidas para o formato do jogo, com os nomes dos autores dela: o site nao as # usa) e sem src/sounds/ (veja abaixo): domino-chain-1.1-pruned.tar.gz. O script aceita os dois tarballs e # tira essas pastas de qualquer forma. # # O que o site serve e montado aqui, como o Makefile do jogo faria (data/domino-chain/{images,sounds, # themes,levels}), com quatro diferencas: # - as imagens dos dominos (images/dominoes.png) sao renderizadas pelo POV-Ray a partir de src/dominoes # (.pov, GPL); o POV-Ray nao esta nas nossas ferramentas, entao o arquivo vem pronto do zip de # lancamento 1.1 para Windows do proprio projeto (conferido pelo SHA-256), assim como a fonte # data/fonts/FreeSans.ttf (GNU FreeFont, GPL-3.0-or-later com a excecao de fontes). Os dois arquivos # saem desse zip e ficam soltos em artifacts/build/domino-chain-1.1/, de onde o bundle os hospeda; # o zip, que traz tambem as fases do jogo de 1992, nao e hospedado; # - so os conjuntos de fases A&V e Tutorials (levels/av e levels/tutorial) entram: o conjunto "original" # e feito de fases do jogo comercial de 1992 (as grades de blocos delas, com os autores); # - os 17 efeitos sonoros de src/sounds/ nao tem autoria nem licenca registradas, e o historico do projeto # nao diz de onde vieram (o primeiro commit do jogo le os arquivos do original). Sao trocados pelos do # make-sounds.py, sintetizados aqui, com os mesmos nomes, codificados em Ogg Vorbis (qualidade 0.3) pelo # wav2ogg (Builds/pygame-music/wav2ogg.c, compilado aqui com a libvorbis 1.3.7 de artifacts/tools). # - as 11 musicas dos temas (Roberto Lorenz) sao recodificadas em Ogg Vorbis qualidade 0.1 para # reduzir o download (de 31 MB para cerca de 16 MB), com o oggdec.c (Builds/terratactician) e o wav2ogg; # domino-chain-fredygames.patch (so com __EMSCRIPTEN__, exceto a troca do Boost): # - boost::filesystem vira std::filesystem (so duas funcoes); # - fribidi.h: o jogo usa o FriBidi para textos da direita para a esquerda; esta versao em ingles nao # precisa dele, e o fribidi.h novo faz o mesmo so para a esquerda para a direita; # - o laco principal devolve a vez ao navegador a cada quadro (o build usa Asyncify); # - o jogo so redesenha os blocos que mudaram, contando que a tela guarde o quadro anterior; o canvas # do navegador nao guarda, entao cada quadro copia a imagem toda. # Sem a localizacao (gettext devolve o proprio texto em ingles), sem a documentacao, sem os icones. O jogo # precisa de excecoes de C++ (-fexceptions). Os dados vao num domino-chain.data que o proprio Emscripten # carrega (--preload-file data), com ./data como pasta de trabalho (o jogo a acha como "portable datadir"). # O perfil, as fases resolvidas e as gravacoes ficam em /home/web_user/.local/share/domino-chain (IndexedDB). # # Saida: artifacts/build/domino-chain-1.1/domino-chain.{js,wasm,data}, dominoes.png e FreeSans.ttf, que o # bundle.yaml do jogo confere pelo SHA-256. set -euo pipefail VERSION=1.1 SRC_SHA256=a785121edabd2c54a11073541120e1ec8205d18b792341586a0fea2f7d615251 PRUNED_SHA256=0160121ec50d1cf3ba960937ccb2165cb5414ec16daf80b0c6aae5b31079cfd0 LUA_SHA256=b9e2e4aad6789b3b63a056d442f7b39f0ecfca3ae0f1fc0ae4e9614401b69f4b WIN_SHA256=cc95469b9bb3f1ace29afcce73bf82d2c5090db16c16d0d00b53f3613f6bff0a 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/domino-chain-$VERSION" cache="$root/artifacts/cache/domino-chain" tools="$root/artifacts/tools" tarball="domino-chain.gitlab.io-$VERSION.tar.gz" pruned="domino-chain-$VERSION-pruned.tar.gz" s="domino-chain.gitlab.io-$VERSION" 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 [ -d "$tools/vorbis-1.3.7/include" ] || { echo "Falta a libvorbis 1.3.7 em $tools/vorbis-1.3.7 (veja Builds/pygame-music/README)." >&2; exit 1; } # Arquivo auxiliar: em domino-chain/ ou pygame-music/ (repositorio) ou ao lado do script (pasta de fontes do site). aux() { if [ -f "$here/domino-chain/$1" ]; then echo "$here/domino-chain/$1"; elif [ -f "$here/pygame-music/$1" ]; then echo "$here/pygame-music/$1"; elif [ -f "$here/terratactician/$1" ]; then echo "$here/terratactician/$1"; else echo "$here/$1"; fi } # fetch : usa o arquivo ao lado do script, ou baixa para o cache. fetch() { local file="$here/$(basename "$2")" if [ ! -f "$file" ]; then file="$2" if [ ! -f "$file" ]; then mkdir -p "$(dirname "$file")" curl -fsSL -o "$file.part" "$1" mv "$file.part" "$file" fi fi echo "$3 $file" | shasum -a 256 -c - >&2 echo "$file" } if [ -f "$here/$pruned" ]; then src_tar="$here/$pruned" echo "$PRUNED_SHA256 $src_tar" | shasum -a 256 -c - >&2 else src_tar="$(fetch "https://gitlab.com/domino-chain/domino-chain.gitlab.io/-/archive/$VERSION/$tarball" "$cache/$tarball" "$SRC_SHA256")" fi lua_tar="$(fetch "https://www.lua.org/ftp/lua-5.2.4.tar.gz" "$cache/lua-5.2.4.tar.gz" "$LUA_SHA256")" win_zip="$(fetch "https://gitlab.com/domino-chain/domino-chain.gitlab.io/uploads/18740047d36c5f760fde34896a2ce1c4/Domino-Chain_${VERSION}_for_Windows.zip" "$cache/Domino-Chain_${VERSION}_for_Windows.zip" "$WIN_SHA256")" rm -rf "$out" mkdir -p "$out" tar xzf "$src_tar" -C "$out" rm -rf "$out/$s/src/levels/original" "$out/$s/src/recordings/finish/original" "$out/$s/src/sounds" tar xzf "$lua_tar" -C "$out" patch -d "$out/$s" -p1 --quiet --no-backup-if-mismatch < "$(aux domino-chain-fredygames.patch)" # Arquivos prontos do zip de Windows (nada mais dele entra) unzip -q -j "$win_zip" "Domino-Chain_${VERSION}_for_Windows/data/domino-chain/images/dominoes.png" \ "Domino-Chain_${VERSION}_for_Windows/data/fonts/FreeSans.ttf" -d "$out" # Efeitos sonoros: sintetizados, em Ogg Vorbis cc -O2 "$(aux wav2ogg.c)" -I"$tools/vorbis-1.3.7/include" -L"$tools/vorbis-1.3.7/lib" -lvorbisenc -lvorbis -logg -lm -o "$out/wav2ogg" python3 -I "$(aux make-sounds.py)" "$out/wav" d="$out/data/domino-chain" mkdir -p "$d/images" "$d/sounds" "$d/themes" "$d/levels" "$out/data/fonts" for w in $(LC_ALL=C ls "$out"/wav/*.wav); do "$out/wav2ogg" "$w" "$d/sounds/$(basename "$w" .wav).ogg" 0.3; done cp "$out/$s"/src/images/*.png "$d/images/" cp "$out/dominoes.png" "$d/images/dominoes.png" cp "$out/$s"/src/themes/* "$d/themes/" # Musicas dos temas (11 .ogg, 31 MB): decodificadas e recodificadas em Ogg Vorbis qualidade 0.1 (cerca de metade # do tamanho), com o oggdec (vorbisfile da libvorbis 1.3.7) e o wav2ogg, ambos compilados aqui. cc -O2 "$(aux oggdec.c)" "$tools/vorbis-src/libvorbis-1.3.7/lib/vorbisfile.c" -I"$tools/vorbis-1.3.7/include" \ -I"$tools/vorbis-src/libvorbis-1.3.7/include" -L"$tools/vorbis-1.3.7/lib" -lvorbis -logg -lm -o "$out/oggdec" for m in $(LC_ALL=C ls "$d"/themes/*.ogg); do "$out/oggdec" "$m" "$out/in.wav" "$out/wav2ogg" "$out/in.wav" "$m" 0.1 done rm -f "$out/in.wav" "$out/oggdec" "$out/wav2ogg" for set in av tutorial; do (LC_ALL=C cat "$out/$s"/src/levels/$set/*.level | gzip -9n > "$d/levels/$set.gz") done cp "$out/FreeSans.ttf" "$out/data/fonts/FreeSans.ttf" rm -rf "$out/wav" # Compila de dentro da pasta de saida, com caminhos relativos. ( cd "$out" lua="tmp-lua-5.2.4/src" mv lua-5.2.4 tmp-lua-5.2.4 ports=(-sUSE_SDL=2 -sUSE_SDL_MIXER=2 -sSDL2_MIXER_FORMATS='["ogg"]' -sUSE_SDL_TTF=2 -sUSE_LIBPNG=1 -sUSE_ZLIB=1) mkdir obj for f in $(LC_ALL=C ls $lua/*.c | grep -v "/lua.c\|/luac.c"); do emcc -O2 -w -ffile-prefix-map="$out/=" -DLUA_USE_POSIX -c "$f" -o "obj/lua_$(basename "$f").o" done src="$s/src/domino-chain" for f in $(LC_ALL=C ls $src/*.cpp); do em++ -std=c++17 -fexceptions -O2 -w -ffile-prefix-map="$out/=" -DVERSION="\"$VERSION\"" -DDATADIR='"/data"' \ -I"$lua" "${ports[@]}" -c "$f" -o "obj/$(basename "$f").o" done for f in $(LC_ALL=C ls $src/linebreak/*.c); do emcc -O2 -w -ffile-prefix-map="$out/=" -c "$f" -o "obj/lb_$(basename "$f").o" done for f in $(LC_ALL=C ls $src/sha1/*.cpp); do em++ -std=c++17 -O2 -w -ffile-prefix-map="$out/=" -c "$f" -o "obj/sha_$(basename "$f").o" done em++ -fexceptions -O2 $(LC_ALL=C ls obj/*.o) "${ports[@]}" -lidbfs.js -sASYNCIFY -sSTACK_SIZE=1MB \ -sALLOW_MEMORY_GROWTH -sINITIAL_MEMORY=128MB -sENVIRONMENT=web -sEXIT_RUNTIME=1 \ -sEXPORTED_RUNTIME_METHODS=FS,addRunDependency,removeRunDependency \ --preload-file data -o domino-chain.js rm -rf obj tmp-lua-5.2.4 ) shasum -a 256 "$out/domino-chain.js" "$out/domino-chain.wasm" "$out/domino-chain.data" "$out/dominoes.png" "$out/FreeSans.ttf"