joeylib2/scripts/lib/tileBankGate.sh
2026-10-13 14:01:46 -05:00

129 lines
4.9 KiB
Bash

# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
# See LICENSE.md for license information.
# SPDX-License-Identifier: MIT
#
# Shared by the tile-bank gates, scripts/verify-<port>-tilebank.sh. Each runs
# examples/tilebank on its port with the DATA/tilebank make/<port>.mk staged
# (tests/host/tileBankStage.py: the port's own .tbk bake of
# tests/host/tileBank.png, every other target's bake, the expected pixels),
# gets the program's TILEBANK log line off the machine, and judges it here
# against the host gate: scripts/check-tilebank.sh is run for its surface
# hash, so the expected value has exactly one source.
# Source after joeyEnv.sh.
TILEBANK_GATE="$(basename "$0" .sh)"
# tileBankAwaitLine DIR SECONDS PID -- wait for the program's log (joeylog.txt
# in any case, as DOS and GEMDOS name it) in DIR to hold a TILEBANK line, for
# up to SECONDS or until PID exits; print the log's path if it does.
tileBankAwaitLine() {
local dir="$1"
local seconds="$2"
local pid="$3"
local log
local waited
for ((waited = 0; waited < seconds; waited++)); do
log="$(find "$dir" -maxdepth 1 -iname joeylog.txt -print -quit)"
if [ -n "$log" ] && grep -q '^TILEBANK: ' "$log"; then
printf '%s\n' "$log"
return 0
fi
joeyAlive "$pid" || return 1
sleep 1
done
return 1
}
# tileBankData BINDIR -- print the DATA/tilebank to stage: the one
# make/<port>.mk staged beside the program, or TILEBANK_DATA_DIR when set (a
# negative control stages a deliberately broken bake that way).
tileBankData() {
printf '%s\n' "${TILEBANK_DATA_DIR:-$1/DATA/tilebank}"
}
# tileBankJudge LOG -- judge examples/tilebank's TILEBANK line in LOG: the
# program's own verdict (both loads pixel-exact, the palette, every staged
# foreign bank refused both ways), both surface hashes equal to the host's,
# and every other target assetbake knows refused. Prints the line and one
# PASS or FAIL line; returns 0 on PASS.
tileBankJudge() {
local line
local verdict
local streamHash
local pasteHash
local refused
local wantRefused="$TILEBANK_OTHERS/$TILEBANK_OTHERS"
local fails=()
local why
line="$(tr -d '\r' < "$1" | grep -E '^TILEBANK: ' | tail -1)"
if [ -z "$line" ]; then
echo "$TILEBANK_GATE: FAIL - no TILEBANK line in the program's log" >&2
return 1
fi
echo "$line"
verdict="$(sed -n 's/^TILEBANK: \([A-Z]*\).*/\1/p' <<< "$line")"
streamHash="$(sed -n 's/.* streamHash=\([0-9A-F]*\).*/\1/p' <<< "$line")"
pasteHash="$(sed -n 's/.* pasteHash=\([0-9A-F]*\).*/\1/p' <<< "$line")"
refused="$(sed -n 's/.* refused=\([0-9]*\/[0-9]*\).*/\1/p' <<< "$line")"
[ "$verdict" = PASS ] || fails+=("the program's own checks failed")
[ "$streamHash" = "$TILEBANK_HASH" ] || fails+=("streamHash ${streamHash:-missing}, host $TILEBANK_HASH")
[ "$pasteHash" = "$TILEBANK_HASH" ] || fails+=("pasteHash ${pasteHash:-missing}, host $TILEBANK_HASH")
[ "$refused" = "$wantRefused" ] || fails+=("refused ${refused:-missing}, want $wantRefused")
if [ "${#fails[@]}" -gt 0 ]; then
why="$(printf '%s; ' "${fails[@]}")"
echo "$TILEBANK_GATE: FAIL - ${why%; }" >&2
return 1
fi
echo "$TILEBANK_GATE: PASS (own bake pixel-exact both ways, hash $TILEBANK_HASH = host; $wantRefused other targets refused)"
}
# tileBankNeedBuild PROGRAM DATADIR BUILD-HINT -- exit 2 unless the port's
# TILEBANK program and its DATA/tilebank are there.
tileBankNeedBuild() {
local what
for what in "$1" "$2/own.tbk" "$2/expect.bin"; do
if [ ! -e "$what" ]; then
echo "$TILEBANK_GATE: $what is missing; run: $3" >&2
exit 2
fi
done
}
# tileBankReference -- run the host gate, scripts/check-tilebank.sh, which must
# pass (its pixel checks are what make its hash worth matching), and set
# TILEBANK_HASH the surface hash of its to-surface load of its own bake
# TILEBANK_OTHERS how many targets besides any one port assetbake knows
# Exits 2 without a host C compiler, 1 if the host gate fails.
tileBankReference() {
local out
if ! command -v "${CC:-cc}" > /dev/null; then
echo "$TILEBANK_GATE: no host C compiler (${CC:-cc}) for the reference run of scripts/check-tilebank.sh" >&2
exit 2
fi
if ! out="$("$JOEY_REPO/scripts/check-tilebank.sh" 2>&1)"; then
echo "$out" | tail -15 >&2
echo "$TILEBANK_GATE: FAIL - the host reference, scripts/check-tilebank.sh, failed" >&2
exit 1
fi
TILEBANK_HASH="$(sed -n 's/.*to-surface hash \([0-9A-F]\{8\}\).*/\1/p' <<< "$out" | head -1)"
if [ -z "$TILEBANK_HASH" ]; then
echo "$TILEBANK_GATE: FAIL - scripts/check-tilebank.sh printed no to-surface hash" >&2
exit 1
fi
TILEBANK_OTHERS="$(python3 - "$JOEY_REPO/tools/assetbake" <<'PY'
import sys
sys.path.insert(0, sys.argv[1])
from assetbake import TARGET_NAMES
print(len(TARGET_NAMES) - 1)
PY
)"
}