#!/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/-headered-.tar.gz \ # -C /storage1/Emulation/roms/ 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"