#!/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 # # check-modplayer.sh - Host gate for src/core/modPlayer.c, the module player # every port that mixes .MOD in software plays through (DOS, the ST, the # X68000, and the hosted ports). Builds tests/host/modPlayerHost.c, which # includes the player, with the host cc and the address and undefined- # behaviour sanitizers, and runs it: the Protracker behaviours the player # keeps, where a song ends, the 8-bit and 16-bit outputs, and mangled # modules played without reading outside the player's copy. When the # Amiga's PTPlayer is installed, its period and vibrato tables are handed # over too, and the player's must match them. # # Usage: scripts/check-modplayer.sh # Exit: 0 PASS, 1 FAIL set -uo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" label=check-modplayer cc=${CC:-cc} work=$(mktemp -d -t joeylib-modplayer.XXXXXX) trap 'rm -rf "$work"' EXIT cd "$repo" if ! "$cc" -O1 -g -fsanitize=address,undefined -fno-sanitize-recover=all -DJOEYLIB_PLATFORM_BLANK \ -Iinclude -Iinclude/joey -Isrc/core -Wall -Wextra -Werror \ tests/host/modPlayerHost.c -lm -o "$work/modPlayerHost"; then echo "$label: FAIL - the harness did not build" exit 1 fi # PTPlayer's mt_PeriodTable, then its three vibrato tables, as numbers. tables=() asm="${AMIGA_PTPLAYER:-}/ptplayer.asm" if [ -f "$asm" ]; then awk -v out="$work/tables.txt" ' index($0, "mt_PeriodTable:") && !periodsDone { inPeriods = 1 } inPeriods && $0 == "" { inPeriods = 0 periodsDone = 1 } index($0, "mt_VibratoSineTable:") && !wavesDone { inWaves = 1 } index($0, "mt_VibratoRectTable:") { afterRect = 1 } inWaves && afterRect && index($0, "endc") { inWaves = 0 wavesDone = 1 } (inPeriods || inWaves) && match($0, /^[ \t]*dc\.[bw][ \t]+/) { list = substr($0, RLENGTH + 1) sub(/;.*/, "", list) n = split(list, values, ",") for (i = 1; i <= n; i++) { if (inPeriods) { periods = periods (periods == "" ? "" : " ") (values[i] + 0) } else { waves = waves (waves == "" ? "" : " ") (values[i] + 0) } } } END { printf "periods %s\nvibrato %s\n", periods, waves > out }' "$asm" tables=("$work/tables.txt") fi output=$("$work/modPlayerHost" "${tables[@]}" 2>&1) status=$? echo "$output" | grep -v '^MODPLAYER' counts=$(sed -n 's/^MODPLAYER //p' <<< "$output") if [ "$status" -ne 0 ]; then echo "$label: FAIL - ${counts:-harness error} checks pass" exit 1 fi echo "$label: PASS ($counts checks: Protracker's behaviours, song ends, both outputs, and mangled modules, under the sanitizers)"