# Pokémon ROM Hacks — tooling Acquisition + patching pipeline for the Pokémon ROM-hack collection in the valhalla homelab library. Spun off from the `homelabstack` repo on 2026-06-06. > **The catalog (the notes) lives in the self-hosted Obsidian vault**, not in this > repo — under `Pokémon ROM Hacks/`: one note per hack, plus `Index`, `Types`, > `Play Queue`, `Bases/`, `Platforms/`, a `Wanted` acquisition list, and a > `_Claude.md` ops reference. Access it via the Obsidian MCP (`mcp__obsidian__*`) > or the `vault` skill. New hacks are added there **manually** (see the vault's > `_Claude.md` checklist). This repo is just the tooling. The ROMs live on valhalla under `/storage1/Emulation/roms//Hacks/`, served by the RomM stack (`roms.ginnoir.com`) — deployed from `homelabstack` (`stacks/roms/`). ## Layout | Path | What | |---|---| | `scripts/romhack-import.py` | Import a drop folder of mixed ROMs/patches/docs into the valhalla library (validate, clean-name, apply patches, archive). Runs on valhalla. | | `scripts/romhack-fetch.py` | Acquire + patch + place worthwhile hacks from direct (non-gated) sources. Manifest-driven. Runs on valhalla. | | `scripts/romhack-apply.py` | Apply a single IPS/BPS/UPS patch to a base ROM with checksum verification. | | `scripts/build-vault-mocs.py` | Regenerate the vault's static MOC tables + header counts (Index/Platforms/Bases) from the notes. Read-only on `Hacks/*.md`. Re-run after any note change. | | `scripts/scrape_match.py` | Match the Discord-scrape `metadata.json` entries to vault notes → `.scrape/_match_report.json` (curated-overlap / discord-match / unmatched). | | `scripts/enrich_vault.py` | Synthesize the scrape into notes: `backfill` (frontmatter for imports), `merge` (scrape into curated), `create` (new notes), `rebuild` (normalize import bodies). `--apply` writes; default dry-runs to `.scrape/_preview/`. | | `scripts/enrich_web.py` | Apply hand/web-researched facts from `.scrape/web_facts*.json` onto notes (summary, features, dev, version, notability), idempotently. | | `scripts/build-wiki-data.py` | Export all notes → `wiki/catalog.json`, the data source for the wiki site (see `wiki/SPEC.md`). | | `scripts/build-romhack-vault.py` | **Archived.** Original 75-hack bootstrap generator — do **not** re-run against the live vault. Kept only for its structured `HACKS` dataset. | | `wiki/` | `catalog.json` (exported 368-hack dataset) + `SPEC.md` (build spec for the future static wiki site). | | `drop/` | **gitignored** staging area (~1.3 GB) of ROM/patch binaries pending import. | | `.scrape/` | **gitignored** per-machine scratch: Discord-scrape `metadata.json` pulled from valhalla + match report + `web_facts*.json` + note backups. | ## Enrichment pipeline The vault catalog (368 notes) was enriched from the Discord scrape on valhalla (`/storage1/labdata/romhacks/metadata/*/metadata.json`) plus web research. To re-run or extend: ```bash # 1. pull the scrape metadata locally (one-time / refresh) ssh valhalla "cd /storage1/labdata/romhacks/metadata && tar cf - */metadata.json" | tar xf - -C .scrape # 2. match scrape -> notes python scripts/scrape_match.py --report .scrape/_match_report.json # 3. synthesize (drop --apply first to preview into .scrape/_preview/) python scripts/enrich_vault.py backfill --apply python scripts/enrich_vault.py rebuild --apply python scripts/enrich_vault.py merge --apply python scripts/enrich_vault.py create --apply # 4. web-enrich more hacks: add a .scrape/web_factsN.json batch, then python scripts/enrich_web.py --apply # 5. refresh static surfaces + the site data python scripts/build-vault-mocs.py python scripts/build-wiki-data.py ``` Art for every scraped hack is web-served at `https://romhacks-files.ginnoir.com/_meta//` (copied into the Caddy-served `library/_meta/` tree on valhalla). ## Acquisition policy Pre-3DS handhelds (gb/gbc/gba/nds) + pre-Wii consoles. Direct, non-anti-bot sources only for auto-fetch; gated hacks are tracked in the vault's `Pokémon ROM Hacks/Wanted.md` for manual hand-off. No offensive/"shitpost" content (e.g. Clover excluded).