153 lines
6.7 KiB
Bash
Executable file
153 lines
6.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
# See LICENSE.md for license information.
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# verify-atarist-palette.sh - The ST family's palette, read off the shifter.
|
|
#
|
|
# JoeyLib colours are 12-bit $0RGB. A plain ST's shifter has 3 bits per
|
|
# channel, so it keeps each channel's top three bits; an STe's has 4, with
|
|
# the channel's LOW bit in bit 3 of the register nibble. The ST build (make
|
|
# atarist) must write the 3-bit truncation -- on every machine, an STe
|
|
# included, since it never uses STe hardware -- and the STe build (make
|
|
# ste) the exact 4-bit colour.
|
|
#
|
|
# Subject: the PATTERN example -- eight bands, each its own palette, each
|
|
# palette a gradient whose entry i has i in some of its channels. So every
|
|
# register sees every channel value 0..15 across the bands, odd ones
|
|
# included, and the Timer B raster ISR reloads all sixteen registers at
|
|
# every band. Hatari's video_color trace logs each palette register write
|
|
# with its pc; the gate collects the application's (TOS lives at $Exxxxx),
|
|
# and for each register the set of values written must be EXACTLY the set
|
|
# the machine's encoding of the eight gradients gives. A shifter fed the
|
|
# wrong encoding fails on the odd values; a missing band or a wrong
|
|
# palette fails on the set.
|
|
#
|
|
# Usage: scripts/verify-atarist-palette.sh [st|megast|ste|megaste ...]
|
|
# machines to run, default "st ste megaste": a plain ST and a
|
|
# Mega ST run the ST build, an STe and a Mega STe the STe build
|
|
# Requires: ./install.sh install emulator:atarist (Hatari, EmuTOS),
|
|
# PATTERN.PRG in build/atarist/bin and build/ste/bin (make
|
|
# atarist, make ste)
|
|
set -uo pipefail
|
|
|
|
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
source "$repo/scripts/lib/joeyEnv.sh"
|
|
joeyNeed HATARI hatari
|
|
joeyNeed EMUTOS_IMG emutos
|
|
|
|
machines=${*:-st ste megaste}
|
|
wall=120 # hard cap on Hatari, whatever happens to this script
|
|
runVbls=1200 # EmuTOS boot + PATTERN up and banding: ~600 frames
|
|
|
|
work=$(mktemp -d -t joeylib-st-palette.XXXXXX)
|
|
trap 'rm -rf "$work"' EXIT
|
|
|
|
fails=0
|
|
for machine in $machines; do
|
|
case $machine in
|
|
st|megast) build=atarist ;;
|
|
ste|megaste) build=ste ;;
|
|
*) echo "verify-atarist-palette: unknown machine '$machine' (st, megast, ste or megaste)" >&2; exit 2 ;;
|
|
esac
|
|
prog=$repo/build/$build/bin/PATTERN.PRG
|
|
[ -f "$prog" ] || { echo "verify-atarist-palette: missing $prog (run 'make $build')" >&2; exit 2; }
|
|
rm -rf "$work/c"
|
|
mkdir -p "$work/c"
|
|
cp "$prog" "$work/c/"
|
|
# The trace is filtered as it is produced: only palette register writes
|
|
# from the application, not TOS's ($Exxxxx) or Hatari's other colour
|
|
# bookkeeping. --run-vbls ends the run; timeout is the backstop.
|
|
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy timeout -s KILL "$wall" "$HATARI" \
|
|
--machine "$machine" \
|
|
--tos "$EMUTOS_IMG" \
|
|
--harddrive "$work/c" \
|
|
--gemdos-drive C \
|
|
--drive-a off --drive-b off \
|
|
--sound off \
|
|
--fast-forward on \
|
|
--run-vbls "$runVbls" \
|
|
--trace video_color \
|
|
--auto 'C:\PATTERN.PRG' 2>&1 \
|
|
| grep -E '^write col addr=ff82[45]' | grep -v ' pc=e' > "$work/$machine.log"
|
|
|
|
awk -v machine="$machine" -v build="$build" '
|
|
# One 4-bit channel as that build writes the shifter nibble.
|
|
function channel(v) {
|
|
return build == "atarist" ? rshift(v, 1) : or(rshift(v, 1), lshift(and(v, 1), 3))
|
|
}
|
|
# A set of colour words as Python prints a sorted list of their hex.
|
|
function hexList(set, count, names, i, n, out) {
|
|
n = 0
|
|
for (i = 0; i < count; i++) {
|
|
names[++n] = sprintf("0x%x", set[i])
|
|
}
|
|
asort(names)
|
|
out = ""
|
|
for (i = 1; i <= n; i++) {
|
|
out = out (i > 1 ? ", " : "") "\x27" names[i] "\x27"
|
|
}
|
|
return "[" out "]"
|
|
}
|
|
BEGIN {
|
|
# PATTERN'"'"'s eight palettes: which of red, green, and blue carry
|
|
# the gradient.
|
|
split("111 100 110 010 011 001 101 111", gradients, " ")
|
|
}
|
|
# write col addr=ff825e col=70 video_cyc_w=55892 ... pc=1f00e
|
|
match($0, /^write col addr=ff82([45][0-9a-f]) col=([0-9a-f]+) /, m) {
|
|
register = int((strtonum("0x" m[1]) - 64) / 2)
|
|
value = strtonum("0x" m[2])
|
|
if (!((register, value) in seen)) {
|
|
seen[register, value] = 1
|
|
got[register, seenCount[register]++] = value
|
|
}
|
|
writes++
|
|
}
|
|
END {
|
|
bits = build == "atarist" ? "3-bit" : "4-bit"
|
|
if (writes == 0) {
|
|
printf "verify-atarist-palette: %s build on %s FAIL - PATTERN never wrote the palette\n", build, machine > "/dev/stderr"
|
|
exit 1
|
|
}
|
|
badCount = 0
|
|
for (i = 0; i < 16; i++) {
|
|
delete want
|
|
delete wantList
|
|
wantCount = 0
|
|
v = i ? channel(i) : 0
|
|
for (g = 1; g <= 8; g++) {
|
|
word = (substr(gradients[g], 1, 1) == "1" ? lshift(v, 8) : 0) + (substr(gradients[g], 2, 1) == "1" ? lshift(v, 4) : 0) + (substr(gradients[g], 3, 1) == "1" ? v : 0)
|
|
if (!(word in want)) {
|
|
want[word] = 1
|
|
wantList[wantCount++] = word
|
|
}
|
|
}
|
|
same = wantCount == seenCount[i]
|
|
for (word in want) {
|
|
same = same && ((i, word + 0) in seen)
|
|
}
|
|
if (!same) {
|
|
delete gotList
|
|
for (k = 0; k < seenCount[i]; k++) {
|
|
gotList[k] = got[i, k]
|
|
}
|
|
bad[++badCount] = sprintf("register %d: wrote %s, want %s", i, hexList(gotList, seenCount[i]), hexList(wantList, wantCount))
|
|
}
|
|
}
|
|
if (badCount > 0) {
|
|
printf "verify-atarist-palette: %s build on %s FAIL - not the %s encoding of PATTERN'"'"'s palettes:\n", build, machine, bits > "/dev/stderr"
|
|
for (b = 1; b <= badCount && b <= 4; b++) {
|
|
printf "verify-atarist-palette: %s\n", bad[b] > "/dev/stderr"
|
|
}
|
|
exit 1
|
|
}
|
|
printf "verify-atarist-palette: %s build on %s OK - %d palette writes, all 16 registers exactly the %s encoding of the 8 band palettes\n", build, machine, writes, bits
|
|
}' "$work/$machine.log" || fails=$((fails + 1))
|
|
done
|
|
|
|
if [ "$fails" -gt 0 ]; then
|
|
echo "verify-atarist-palette: FAIL" >&2
|
|
exit 1
|
|
fi
|
|
echo "verify-atarist-palette: PASS"
|