igir-report.ps1: read-only igir report over the EmuDeck tree on valhalla, matching ROMs by checksum against libretro's No-Intro + Redump DAT sets (sparse-cloned + cached). Scoped (-Platforms) or whole-library (-All); CSV per run under /storage1/igir/reports. Uses node:lts (alpine breaks igir on musl) and metadat/no-intro (not the curated dat/ folder). igir-strip-snes-headers.sh: reversible backup-then-strip of 512-byte SNES copier headers (size%1024==512) that igir can't auto-detect, renaming to .sfc so headered ROMs match headerless No-Intro.
80 lines
2.9 KiB
Bash
80 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
|
# scripts/igir-strip-snes-headers.sh (runs ON valhalla)
|
|
#
|
|
# SNES copier ROMs carry a 512-byte header (file size % 1024 == 512). igir
|
|
# detects SNES headers by content *signature*, which these copier headers lack,
|
|
# so it can't strip them and they never match headerless No-Intro DATs — even
|
|
# though their headerless checksum IS in No-Intro. This script blind-strips that
|
|
# 512-byte header (the universally-correct fix for SNES) and renames to .sfc.
|
|
#
|
|
# It is a MUTATION of the live EmuDeck tree (RomM + EmuDeck read it). Every
|
|
# touched file is tar'd to a backup first, so the change is fully reversible.
|
|
#
|
|
# Usage (default folder = snes):
|
|
# ssh ginnoir@valhalla 'bash -s' < scripts/igir-strip-snes-headers.sh
|
|
# ssh ginnoir@valhalla 'bash -s -- sfc' < scripts/igir-strip-snes-headers.sh
|
|
# ssh ginnoir@valhalla 'bash -s -- snes 1' < scripts/igir-strip-snes-headers.sh # 2nd arg=1 => dry run
|
|
#
|
|
# Restore from a backup:
|
|
# tar xzf /storage1/igir/backup/<folder>-headered-<stamp>.tar.gz \
|
|
# -C /storage1/Emulation/roms/<folder>
|
|
set -uo pipefail
|
|
|
|
FOLDER="${1:-snes}"
|
|
DRYRUN="${2:-0}"
|
|
ROOT="/storage1/Emulation/roms/$FOLDER"
|
|
BK="/storage1/igir/backup"
|
|
STAMP="$(date +%Y-%m-%d)"
|
|
|
|
[ -d "$ROOT" ] || { echo "No such folder: $ROOT"; exit 1; }
|
|
mkdir -p "$BK"
|
|
cd "$ROOT" || exit 1
|
|
shopt -s nullglob nocaseglob
|
|
|
|
# Collect headered SNES ROMs (size % 1024 == 512).
|
|
list="$(mktemp)"; : > "$list"
|
|
for f in *.smc *.sfc *.fig *.swc; do
|
|
[ -f "$f" ] || continue
|
|
s=$(stat -c %s "$f")
|
|
[ $((s % 1024)) -eq 512 ] && printf '%s\0' "$f" >> "$list"
|
|
done
|
|
n=$(grep -zc . "$list" || true)
|
|
echo "Headered files in '$FOLDER': $n"
|
|
if [ "$n" -eq 0 ]; then echo "Nothing to strip."; rm -f "$list"; exit 0; fi
|
|
|
|
if [ "$DRYRUN" = "1" ]; then
|
|
echo "(dry run) would back up to $BK/$FOLDER-headered-$STAMP.tar.gz and strip $n files."
|
|
rm -f "$list"; exit 0
|
|
fi
|
|
|
|
# Back up originals before mutating.
|
|
bkfile="$BK/$FOLDER-headered-$STAMP.tar.gz"
|
|
tar --null -czf "$bkfile" -T "$list"
|
|
echo "Backup: $bkfile ($(stat -c %s "$bkfile") bytes, $(tar tzf "$bkfile" | wc -l) files)"
|
|
|
|
# Strip: drop first 512 bytes, verify new size, write as .sfc, remove old.
|
|
stripped=0; errors=0
|
|
while IFS= read -r -d '' f; do
|
|
s=$(stat -c %s "$f")
|
|
base="${f%.*}"; target="$base.sfc"; tmp="$f.hl.tmp"
|
|
tail -c +513 "$f" > "$tmp"
|
|
ns=$(stat -c %s "$tmp")
|
|
if [ "$ns" -ne $((s - 512)) ]; then
|
|
echo "SIZE MISMATCH, skipped: $f ($s -> $ns)"; rm -f "$tmp"; errors=$((errors+1)); continue
|
|
fi
|
|
if [ "$target" != "$f" ] && [ -e "$target" ]; then target="$base (headerless).sfc"; fi
|
|
mv -f "$tmp" "$target"
|
|
[ "$target" != "$f" ] && rm -f "$f"
|
|
stripped=$((stripped+1))
|
|
done < "$list"
|
|
rm -f "$list"
|
|
|
|
# Verify none remain.
|
|
left=0
|
|
for f in *.smc *.sfc *.fig *.swc; do
|
|
[ -f "$f" ] || continue
|
|
s=$(stat -c %s "$f")
|
|
[ $((s % 1024)) -eq 512 ] && left=$((left+1))
|
|
done
|
|
echo "RESULT stripped=$stripped errors=$errors remaining_headered=$left"
|