#!/usr/bin/env bash # Compila o Zaz do fredygames.com: o jogo de bolas coloridas de Remigiusz Dybka (codigo, graficos, fases e # sons sob a GPL-3.0-or-later; musica de Leonard Ritter sob a CC BY-SA 3.0; fontes FreeSans e # FreeMonoBold GPL e font1.ttf de Phranzysko OFL, conforme o data/copyright.txt) em WebAssembly, com o # Emscripten 6.0.10 e as portas SDL2 2.32.10, SDL2_image 2.6.0 (libpng 1.6.58, libjpeg 9f, zlib 1.3.2), # libogg 1.3.5, libvorbis 1.3.7 e FreeType 2.14.3 dele, mais o FTGL 2.1.3-rc5 (MIT) compilado aqui. Este # script, o patch e a camada de compatibilidade (zaz/compat) 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-zaz.sh # # Fonte: o tarball da versao 1.0.1 (zaz-1.0.1.tar.gz, publicado pelo autor no SourceForge) e o # ftgl-2.1.3-rc5.tar.gz (SourceForge), conferidos pelo SHA-256 e guardados em artifacts/cache/zaz/. O # site hospeda o tarball do jogo sem o win32.zip (bibliotecas do Windows ja compiladas, que o build nao # usa; o Debian tambem o tira); o script aceita os dois. Na pasta de fontes do site, o script acha tudo # ao lado dele. # # O jogo e escrito para o SDL 1.2 e o OpenGL 1.x. A camada de compatibilidade, escrita para este build: # - compat/SDL/SDL.h, SDL_image.h e zazsdl12.h/.c: o pedaco da API do SDL 1.2 que o jogo usa (janela # com contexto OpenGL, troca de quadros, mouse, nomes antigos), sobre o SDL2; # - zazgl.h/.c: o desenho passa pela emulacao de OpenGL legado do Emscripten (glBegin/glEnd sobre # WebGL); zazgl.h, incluido em todos os arquivos do jogo e do FTGL, cobre o que falta nela: as formas # double de glVertex3d e glTexCoord2d, GL_CLAMP, texturas BGR e formatos internos numericos, as # pilhas de atributos que o FTGL usa e as texturas GL_ALPHA dos glifos (que a emulacao desenha pretas; # viram GL_LUMINANCE_ALPHA brancas, desenhadas com GL_MODULATE). # zaz-fredygames.patch (so ativo com __EMSCRIPTEN__, salvo a primeira linha): # - mixer.cpp: o construtor deixa de repetir o argumento padrao na definicao (o clang recusa); # - ogvexport.h: sem a exportacao de video (precisa da libtheora e grava um .ogv que a pagina nao teria # como entregar); a classe fica vazia, e gameloop.cpp tira a opcao "Export video" dos menus; # - scene.cpp: o caractere digitado vem da camada (o SDL2 nao tem keysym.unicode); # - main.cpp: tela fixa de 1024x768, que a pagina escala, e fredygames_save(), que a pagina chama quando # a aba some ou fecha (o jogo so grava as opcoes ao sair); # - mainmenu.cpp: sem as opcoes de resolucao e de tela cheia (a pagina tem o proprio botao). # Os dados de data/ vao num zaz.data que o proprio Emscripten carrega (--preload-file) em /usr/share/zaz, # onde o jogo procura uma instalacao; perfis, opcoes e recordes ficam em /home/web_user/.zaz. # # Saida: artifacts/build/zaz-1.0.1/zaz.{js,wasm,data}, que o bundle.yaml do jogo confere pelo SHA-256. set -euo pipefail VERSION=1.0.1 SRC_SHA256=b422c92f15dde0432e1819001e9eb6167895b380aad44e55abff17e02daf6be4 PRUNED_SHA256=3c6c7c2050d6bce14ff531ea05a3216397693a2ff153c4b4c94b6732b24acaf3 FTGL_SHA256=5458d62122454869572d39f8aa85745fc05d5518001bcefa63bd6cbb8d26565b 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/zaz-$VERSION" cache="$root/artifacts/cache/zaz" tarball="zaz-$VERSION.tar.gz" pruned="zaz-$VERSION-pruned.tar.gz" ftgl="ftgl-2.1.3-rc5.tar.gz" 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 # Arquivo auxiliar: em zaz/, zaz/compat/ ou zaz/compat/SDL/ (repositorio) ou ao lado do script (pasta de # fontes do site, onde tudo fica numa pasta so). aux() { local f for f in "$here/zaz/$1" "$here/zaz/compat/$1" "$here/zaz/compat/SDL/$1" "$here/$1"; do if [ -f "$f" ]; then echo "$f"; return; fi done echo "Nao achei $1." >&2 exit 1 } # Arquivo baixado: ao lado do script ou no cache, conferido pelo SHA-256. fetch() { local name="$1" url="$2" sha="$3" file if [ -f "$here/$name" ]; then file="$here/$name" else file="$cache/$name" if [ ! -f "$file" ]; then mkdir -p "$cache" curl -fsSL -o "$file.part" "$url" mv "$file.part" "$file" fi fi echo "$sha $file" | shasum -a 256 -c - >&2 echo "$file" } if [ -f "$here/$pruned" ]; then game_tar="$here/$pruned" echo "$PRUNED_SHA256 $game_tar" | shasum -a 256 -c - >&2 else game_tar="$(fetch "$tarball" "https://downloads.sourceforge.net/project/zaz/$tarball" "$SRC_SHA256")" fi ftgl_tar="$(fetch "$ftgl" \ "https://downloads.sourceforge.net/project/ftgl/FTGL%20Source/2.1.3~rc5/$ftgl" "$FTGL_SHA256")" rm -rf "$out" mkdir -p "$out/work/compat/SDL" "$out/work/obj" "$out/work/gen" "$out/work/ftglgen" tar xzf "$game_tar" -C "$out/work" tar xzf "$ftgl_tar" -C "$out/work" Z="$out/work/zaz-$VERSION" F="$out/work/ftgl-2.1.3~rc5" C="$out/work/compat" patch -d "$Z" -p1 --no-backup-if-mismatch < "$(aux zaz-fredygames.patch)" >&2 for f in zazsdl12.h zazsdl12.c zazgl.h zazgl.c; do cp "$(aux "$f")" "$C/$f"; done for f in SDL.h SDL_image.h; do cp "$(aux "$f")" "$C/SDL/$f"; done # config.h: as definicoes que o configure geraria (sem traducoes: ENABLE_NLS fica de fora). cat > "$out/work/gen/config.h" <<'EOF' #define HAVE_STDINT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_UNISTD_H 1 #define HAVE_SYS_STAT_H 1 #define HAVE_SYS_TYPES_H 1 #define PACKAGE "zaz" #define PACKAGE_NAME "zaz" #define PACKAGE_STRING "zaz 1.0.1" #define PACKAGE_VERSION "1.0.1" #define VERSION "1.0.1" EOF : > "$out/work/ftglgen/config.h" PORTS=(-sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS='["png","jpg"]' -sUSE_OGG=1 -sUSE_VORBIS=1 -sUSE_FREETYPE=1) FLAGS=(-O2 -w -fexceptions -ffile-prefix-map="$out/work/=" "${PORTS[@]}" -I"$C" -I"$F/src" -DPACKAGE_DATA_DIR='"/usr/share"' -DENABLE_SPLASH=false) # Arquivos: a parte do FTGL que as fontes de textura usam, os do Makefile.am do jogo (sem o # ogvexport.cpp) e a camada. objs=() add() { # arquivo, flags extras... local f="$1" rel o shift rel="${f#"$out/work/"}" o="$out/work/obj/${rel//\//_}.o" objs+=("$o") case "$f" in *.c) emcc "${FLAGS[@]}" "$@" -c "$f" -o "$o" & ;; *) em++ "${FLAGS[@]}" "$@" -c "$f" -o "$o" & ;; esac jobs=$((jobs + 1)) if [ "$jobs" -ge 8 ]; then wait; jobs=0; fi } jobs=0 for f in FTFont/FTFont.cpp FTFont/FTTextureFont.cpp FTGlyph/FTGlyph.cpp FTGlyph/FTTextureGlyph.cpp \ FTFace.cpp FTSize.cpp FTLibrary.cpp FTGlyphContainer.cpp FTCharmap.cpp FTPoint.cpp FTBuffer.cpp; do add "$F/src/$f" -I"$out/work/ftglgen" -I"$F/src/FTGL" -include "$C/zazgl.h" done for f in $(sed -n '/^zaz_SOURCES = /,/^$/p' "$Z/src/Makefile.am" | grep -oE '[a-z_0-9]+\.cpp' | grep -v ogvexport); do add "$Z/src/$f" -I"$out/work/gen" -include "$out/work/gen/config.h" -include "$C/zazgl.h" done add "$C/zazsdl12.c" add "$C/zazgl.c" 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: o carregador do zaz.data guarda o nome que a # pasta tem aqui. mkdir -p "$out/data" cp -R "$Z/data/." "$out/data/" rm -f "$out"/data/Makefile* ( cd "$out" em++ -O2 -fexceptions "${objs[@]}" "${PORTS[@]}" -sLEGACY_GL_EMULATION=1 -lGL -lidbfs.js \ -sASYNCIFY -sALLOW_MEMORY_GROWTH=1 -sENVIRONMENT=web -sEXIT_RUNTIME=1 \ -sEXPORTED_RUNTIME_METHODS=FS,ENV,addRunDependency,removeRunDependency \ --preload-file data@/usr/share/zaz \ -o zaz.js ) rm -rf "$out/data" "$out/work" shasum -a 256 "$out/zaz.js" "$out/zaz.wasm" "$out/zaz.data"