feat(roms): add igir report + SNES header-strip ops scripts
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.
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# scripts/igir-report.ps1
|
||||
#
|
||||
# Run the igir ROM collection manager in REPORT mode (read-only) against the
|
||||
# EmuDeck tree at /storage1/Emulation/roms on valhalla, matching ROMs by
|
||||
# checksum against the full No-Intro + Redump DAT sets. Produces a CSV per run
|
||||
# under /storage1/igir/reports listing FOUND / MISSING / UNUSED per system.
|
||||
#
|
||||
# Nothing is moved, renamed, or deleted — the ROM tree is mounted read-only.
|
||||
#
|
||||
# ./scripts/igir-report.ps1 -Platforms gba,snes,n64,psx # scoped run (fast)
|
||||
# ./scripts/igir-report.ps1 -All # whole library (SLOW: hashes everything)
|
||||
# ./scripts/igir-report.ps1 -Platforms snes -UpdateDats # refresh the cached DATs first
|
||||
#
|
||||
# Gotchas baked in (all learned the hard way — see memory igir-roms):
|
||||
# * Uses the Debian `node:lts` image, NOT node:lts-alpine (igir silently
|
||||
# dies on musl).
|
||||
# * DATs come from libretro-database `metadat/no-intro` + `metadat/redump`
|
||||
# (full sets with checksums), NOT the tiny curated top-level `dat/` folder.
|
||||
# * SNES `.smc` copier headers (size%1024==512) are NOT auto-detected by igir
|
||||
# and won't match headerless No-Intro until physically stripped. The `snes`
|
||||
# folder was stripped 2026-06-06; if you add more headered SNES ROMs, strip
|
||||
# them first (see scripts/igir-strip-snes-headers.sh) or they'll show UNUSED.
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string[]]$Platforms,
|
||||
[switch]$All,
|
||||
[switch]$UpdateDats,
|
||||
[string]$Hostname = 'valhalla'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$PSNativeCommandUseErrorActionPreference = $true
|
||||
$server = "ginnoir@$Hostname"
|
||||
|
||||
if (-not $All -and (-not $Platforms -or $Platforms.Count -eq 0)) {
|
||||
Write-Error "Specify -Platforms <name,name,...> (e.g. -Platforms gba,snes) or -All for the whole library."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build the igir -i input args. -All scans the entire roms tree (heavy);
|
||||
# otherwise one -i per named platform folder.
|
||||
if ($All) {
|
||||
$inputArgs = '-i /input'
|
||||
} else {
|
||||
$inputArgs = ($Platforms | ForEach-Object { "-i /input/$_" }) -join ' '
|
||||
}
|
||||
$doPull = if ($UpdateDats) { '1' } else { '0' }
|
||||
|
||||
# Remote logic runs on valhalla. Single-quoted here-string so PowerShell leaves
|
||||
# $vars for bash; INPUT_ARGS / DOPULL are injected below.
|
||||
$remote = @'
|
||||
set -uo pipefail
|
||||
DATS=/storage1/igir/dats/libretro-database
|
||||
REPORTS=/storage1/igir/reports
|
||||
mkdir -p "$REPORTS" /storage1/igir/dats
|
||||
|
||||
# Sparse, blobless clone of just the No-Intro + Redump DAT dirs (cached & reused).
|
||||
if [ ! -d "$DATS/.git" ]; then
|
||||
echo ">> Fetching libretro-database DATs (one-time sparse clone)..."
|
||||
docker run --rm -v /storage1/igir:/w -w /w node:lts sh -c '
|
||||
git clone --filter=blob:none --sparse --depth 1 \
|
||||
https://github.com/libretro/libretro-database dats/libretro-database &&
|
||||
cd dats/libretro-database &&
|
||||
git sparse-checkout set metadat/no-intro metadat/redump'
|
||||
elif [ "__DOPULL__" = "1" ]; then
|
||||
echo ">> Updating cached DATs..."
|
||||
docker run --rm -v /storage1/igir:/w -w /w/dats/libretro-database node:lts git pull -q
|
||||
fi
|
||||
|
||||
NI=$(find "$DATS/metadat/no-intro" -name '*.dat' | wc -l)
|
||||
RD=$(find "$DATS/metadat/redump" -name '*.dat' | wc -l)
|
||||
echo ">> DATs available: $NI No-Intro, $RD Redump"
|
||||
|
||||
STAMP=$(date +%Y-%m-%dT%H-%M-%S)
|
||||
OUT="igir-report-$STAMP.csv"
|
||||
echo ">> Running igir report -> $REPORTS/$OUT"
|
||||
docker run --rm \
|
||||
-v /storage1/Emulation/roms:/input:ro \
|
||||
-v "$DATS":/dats:ro \
|
||||
-v "$REPORTS":/output \
|
||||
node:lts npx -y igir@latest report \
|
||||
-d /dats/metadat/no-intro -d /dats/metadat/redump \
|
||||
__INPUT_ARGS__ \
|
||||
--report-output "/output/$OUT" 2>&1 | grep -vE 'npm notice|npm warn' || true
|
||||
echo ">> Done. CSV: /storage1/igir/reports/$OUT"
|
||||
'@
|
||||
|
||||
$remote = $remote.Replace('__INPUT_ARGS__', $inputArgs).Replace('__DOPULL__', $doPull)
|
||||
# Strip CR so the remote bash never sees stray \r (this file may be CRLF on disk).
|
||||
$remote = $remote.Replace("`r", '')
|
||||
|
||||
Write-Host "igir report on $server :: $(if ($All) {'ALL platforms'} else {$Platforms -join ', '})"
|
||||
ssh $server $remote
|
||||
Reference in New Issue
Block a user