#!/usr/bin/env bash # Compila o Triplane Classic do fredygames.com: o jogo de biplanos de Dodekaedron Software Creations Oy # (codigo, documentacao, imagens e sons sob a GPL-3.0-or-later, desde 2009; README e data/LICENSE do # pacote) em WebAssembly, com o Emscripten 6.0.10 e as portas SDL2 2.32.10 e SDL2_mixer 2.8.0 (com a # libmodplug 11022021, que toca a musica em MOD) dele. 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-triplane-classic.sh # # Fonte: o tarball upstream 1.0.8 como o Debian o publica (triplane_1.0.8.orig.tar.gz, deb.debian.org), # conferido pelo SHA-256 e guardado em artifacts/cache/triplane-classic/ (o site hospeda o mesmo arquivo). # Na pasta de fontes do site, o script acha o tarball e o patch ao lado dele. # # O jogo e escrito para o SDL 1.2, que nao tem porta no Emscripten. O patch acrescenta o # src/io/sdl1compat.{h,cpp}, so com o pedaco da API do SDL 1.2 que o jogo usa, sobre o SDL2 (tela de # 8 bits com paleta, copiada para uma textura a cada quadro; teclas com os codigos do SDL 1.2, que o # jogo guarda na configuracao; sem joystick). O cabecalho e incluido em todos os arquivos (-include). # O resto, com __EMSCRIPTEN__: # - timing.cpp e sdl_compat.cpp devolvem a vez ao navegador nas esperas (a build usa Asyncify); # - sdl_compat.cpp mantem na memoria os dados do MOD enquanto ele toca (o SDL_mixer 2 pode le-los); # - fredygames_save(), que a pagina chama quando a aba some ou fecha: o jogo so grava os pilotos e as # opcoes ao terminar (os pilotos tambem depois de cada missao). # fokker.dks (todos os graficos, sons e musicas do jogo) e montado pelo dksbuild do proprio jogo, que # aqui tambem e compilado com o Emscripten e roda no Node do emsdk: o formato usa inteiros de 32 bits, e # o wasm32 tem long de 32 bits como o DOS original. O arquivo vai na raiz de /data, que e onde o jogo o # procura (TRIPLANE_DATA). Pilotos e opcoes ficam em /home/web_user/.triplane (IndexedDB). # # Saida: artifacts/build/triplane-classic-1.0.8/triplane.{js,wasm,data}, que o bundle.yaml do jogo # confere pelo SHA-256. set -euo pipefail VERSION=1.0.8 SRC_SHA256=81e9e980c66dbf848e9e44602ed4b57d66ff93caab8e86a651ae71920a7587a6 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/triplane-classic-$VERSION" cache="$root/artifacts/cache/triplane-classic" tarball="triplane_$VERSION.orig.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 node="$(command -v node)" # o do emsdk # Arquivo auxiliar: em triplane-classic/ (repositorio) ou ao lado do script (pasta de fontes do site). aux() { if [ -f "$here/triplane-classic/$1" ]; then echo "$here/triplane-classic/$1"; else echo "$here/$1"; fi } if [ -f "$here/$tarball" ]; then src_tar="$here/$tarball" else src_tar="$cache/$tarball" if [ ! -f "$src_tar" ]; then mkdir -p "$cache" curl -fsSL -o "$src_tar.part" "https://deb.debian.org/debian/pool/main/t/triplane/$tarball" mv "$src_tar.part" "$src_tar" fi fi echo "$SRC_SHA256 $src_tar" | shasum -a 256 -c - >&2 rm -rf "$out" mkdir -p "$out" tar xzf "$src_tar" -C "$out" s="triplane-$VERSION" patch -d "$out/$s" -p1 --quiet --no-backup-if-mismatch < "$(aux triplane-classic-fredygames.patch)" # Compila de dentro da pasta de saida, com caminhos relativos: o carregador do triplane.data guarda o # nome que o arquivo tem aqui. ( cd "$out/$s" # fokker.dks, pelo dksbuild do jogo em++ -O2 -w -o "$out/dksbuild.js" src/tools/dksbuild/dksbuild.cc -sNODERAWFS -sENVIRONMENT=node "$node" "$out/dksbuild.js" data/fokker.lst > /dev/null rm "$out/dksbuild.js" "$out/dksbuild.wasm" ports=(-sUSE_SDL=2 -sUSE_SDL_MIXER=2 -sSDL2_MIXER_FORMATS='["mod"]') mkdir "$out/obj" for f in gfx/bitmap gfx/font gfx/gfx util/wutil util/random io/sdl_compat io/video io/mouse io/dksfile \ io/timing triplane world/tripai world/tripmis gfx/fades menus/tripmenu world/terrain \ world/fobjects world/tmexept gfx/extra settings world/plane io/joystick io/sound \ world/tripaudio io/sdl1compat; do extra="" if [ "$f" = io/sdl1compat ]; then extra="-DSDL1COMPAT_IMPL"; fi em++ -O2 -ffile-prefix-map="$out/=" -w -Isrc -include src/io/sdl1compat.h $extra "${ports[@]}" \ -DHAVE_SDL_MIXER '-DTRIPLANE_DATA="/data"' "-DTRIPLANE_VERSION=\"$VERSION\"" \ -c "src/$f.cpp" -o "$out/obj/$(echo "$f" | tr / _).o" done em++ -O2 $(LC_ALL=C ls "$out"/obj/*.o) "${ports[@]}" -lidbfs.js \ -sASYNCIFY -sALLOW_MEMORY_GROWTH -sINITIAL_MEMORY=64MB -sENVIRONMENT=web -sEXIT_RUNTIME=1 \ -sEXPORTED_FUNCTIONS=_main,_fredygames_save \ -sEXPORTED_RUNTIME_METHODS=FS,addRunDependency,removeRunDependency \ --preload-file fokker.dks@/data/fokker.dks \ -o "$out/triplane.js" rm fokker.dks rm -rf "$out/obj" ) shasum -a 256 "$out/triplane.js" "$out/triplane.wasm" "$out/triplane.data"