joeylib2/tools/joeymod/joeymod

100 lines
3.7 KiB
Bash
Executable file

#!/usr/bin/env bash
# joeymod: convert a Protracker .MOD into the runtime form a target
# platform expects.
#
# Usage:
# joeymod input.mod output.mod -- passthrough copy + magic validation
# (DOS / ST runtimes detect song end
# inside libxmp-lite, so the file is
# used as-is)
# joeymod input.mod output.amod -- passthrough + E8FF stop-marker
# pattern injected at song end. The
# Amiga audio HAL relies on E8FF to
# honor PlayMod(loop=false) since
# PTPlayer has no native song-end
# signal. Other replayers ignore
# E8FF (or treat it as a filter
# toggle), so .amod is harmless if
# fed to the wrong port.
# joeymod input.mod output.ntp -- runs the PHP ntpconverter staged
# at toolchains/iigs/ntp/ntpconverter.php
# (NinjaTrackerPlus' .NTP runtime
# format on the IIgs)
#
# The output extension picks the conversion. Build rules per platform
# call this with whichever pair their HAL needs.
set -euo pipefail
if [[ $# -ne 2 ]]; then
echo "usage: joeymod input.mod output.{mod,amod,ntp}" >&2
exit 2
fi
in=$1
out=$2
if [[ ! -f $in ]]; then
echo "joeymod: input not found: $in" >&2
exit 2
fi
# All Protracker-derived .MOD variants store a 4-byte signature at
# offset 1080. Reject anything that does not match a known one --
# better to fail at build time than ship a corrupted audio asset.
magic=$(dd if="$in" bs=1 count=4 skip=1080 status=none)
case "$magic" in
M.K.|M!K!|FLT4|FLT8|6CHN|8CHN|CD81|OKTA|OCTA) ;;
*)
printf 'joeymod: %s does not look like a .MOD (magic %q at offset 1080)\n' "$in" "$magic" >&2
exit 2
;;
esac
ext="${out##*.}"
ext="${ext,,}"
case "$ext" in
mod)
cp "$in" "$out"
;;
amod)
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
modloopend="$repo/build/tools/modloopend"
if [[ ! -x $modloopend ]]; then
echo "joeymod: $modloopend missing; run 'make tools' first" >&2
exit 2
fi
"$modloopend" "$in" "$out"
;;
ntp)
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
ntp_dir="$repo/toolchains/iigs/ntp"
if [[ ! -f $ntp_dir/ntpconverter.php ]]; then
echo "joeymod: $ntp_dir/ntpconverter.php missing; run toolchains/install.sh" >&2
exit 2
fi
if ! command -v php >/dev/null 2>&1; then
echo "joeymod: php CLI not found; install php-cli" >&2
exit 2
fi
# ntpconverter.php writes <basename>.ntp next to its input. Stage
# in a scratch dir so we own the output path and don't pollute
# the caller's source tree.
tmp=$(mktemp -d -t joeymod.XXXXXX)
trap 'rm -rf "$tmp"' EXIT
cp "$in" "$tmp/song.MOD"
( cd "$ntp_dir" && php ntpconverter.php "$tmp/song.MOD" >/dev/null )
if [[ ! -f $tmp/song.ntp ]]; then
echo "joeymod: ntpconverter.php did not produce an .ntp from $in" >&2
exit 2
fi
cp "$tmp/song.ntp" "$out"
;;
*)
echo "joeymod: unknown output extension '.$ext' (expected .mod, .amod, or .ntp)" >&2
exit 2
;;
esac
printf 'joeymod: %s -> %s (%d bytes)\n' "$in" "$out" "$(stat -c %s "$out")"