Files
pokemon/scripts/build-romhack-vault.py
T
ginnoirandClaude Opus 4.8 ae56d101b7 refactor: standardize hack filenames to [Hack] and flatten to platform root
Switch the library naming convention from "Pokemon - <Name> (Hack)" to
"Pokemon - <Name> [Hack][version][tags]", and place hacks in the platform
root (roms/<plat>/) instead of a Hacks/ subfolder. Applied across the live
valhalla library (272 hack/fan-game files) via scripts/standardize-names.py.

- romhack-import.py / romhack-fetch.py: emit [Hack], write to roms/<plat>/
- romhack-pc-migrate.py: emit [Hack]
- build-romhack-vault.py (archived): update documented library_path
- standardize-names.py: new one-shot, self-fetching standardizer (idempotent;
  pipes \n-only bytes over SSH to avoid Windows CRLF corrupting filenames)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 18:08:31 -05:00

482 lines
29 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""[ARCHIVED] Bootstrap generator for the Pokémon ROM-hack vault.
The canonical catalog now lives in the self-hosted Obsidian vault under
`Pokémon ROM Hacks/`, hand-maintained via the Obsidian MCP (see that folder's
`_Claude.md` for the add-a-hack checklist). The live vault has been enriched well
beyond what this script emits (play_status, rating, Bases/, Play Queue) — so do
NOT re-run this against it and sync back; you would regress the catalog. This is
kept only for the structured `HACKS` dataset below. Its output dir
`pokemon-romhack-vault/` is gitignored.
Originally: generate an Obsidian vault documenting the Pokémon ROM-hacks.
Emits, under pokemon-romhack-vault/ :
- Hacks/<Name>.md one note per hack (YAML frontmatter + tags + summary)
- Index.md directory MOC (Dataview query + static fallback table)
- Types.md the type taxonomy
- Platforms/*.md per-platform MOCs (Dataview)
- README.md how to use the vault
The dataset below is the single source of truth — add a row and re-run to extend.
Frontmatter uses Obsidian "properties" so Dataview / Bases plugins work; tags
(#platform/.. #type/.. #status/.. #base/..) make it usable with zero plugins too.
Run from the repo root: python scripts/build-romhack-vault.py
"""
import os, re, urllib.parse
VAULT = os.path.join(os.path.dirname(__file__), "..", "pokemon-romhack-vault")
ADDED = "2026-06-06"
# Type taxonomy (keep in sync with Types.md generation below)
TYPES = {
"Vanilla+": "Official game enhanced — QoL, all species obtainable, light rebalance; same region/story.",
"QoL": "Primarily quality-of-life conveniences over an official base.",
"Difficulty": "Built to be hard — boosted AI/teams, kaizo, or competitive rulesets.",
"Expansion": "Built on a decomp + expansion: many generations, modern mechanics, new abilities/moves.",
"New Experience": "New region, story, and/or Pokédex — a fresh adventure, not the official game.",
"Demake": "Recreates a later-generation game on older hardware.",
"Roguelite": "Run-based, randomized, permadeath-flavored structure.",
"Cosmetic": "Visual/audio overhaul (e.g. Moemon sprites, tilesets, music) over an existing game.",
}
# base ROM display -> tag slug
def base_tag(b):
return re.sub(r"[^a-z0-9]+", "", b.lower()) if b and b != "—" else "unknown"
# Each: (title, platform, base, version, status, [types], gen, url, summary)
# base "—" = not confidently known. url = canonical source if known else "".
HACKS = [
# ---------------- GB ----------------
("Pokémon Brown", "gb", "Red", "1.1", "Complete", ["New Experience"], "Gen 1+",
"https://www.pokecommunity.com/threads/pokemon-brown.27915/",
"One of the oldest and most influential hacks. A brand-new Rijon region with new towns, gyms, and a custom dex built on Gen 1, by Koolboyman (who later made Prism)."),
# ---------------- GBC ----------------
("Pokémon Ambrosia", "gbc", "Crystal", "2.4.0", "Ongoing", ["New Experience"], "Gen 2 style",
"https://www.pokecommunity.com/",
"An ambitious Crystal-engine hack with a new region, expanded dex, and modernized features pushed onto Gen 2 hardware."),
("Pokémon Crystal Clear", "gbc", "Crystal", "2.5.7", "Complete", ["New Experience", "QoL"], "Gen 12",
"https://www.pokecommunity.com/threads/pokemon-crystal-clear.382197/",
"Open-world Crystal — pick any starter, tackle gyms in any order, roam Johto+Kanto freely. A landmark open-world take on Gen 2 by ShockSlayer."),
("Pokémon Crystal Inheritance", "gbc", "Crystal", "1.0.3", "Complete", ["New Experience"], "Gen 2+",
"",
"A Crystal-based adventure with a new story and updated rosters/mechanics within the Gen 2 framework."),
("Pokémon Crystal Kaizo", "gbc", "Crystal", "1.0", "Complete", ["Difficulty"], "Gen 2",
"",
"The definitive Gen 2 kaizo: every trainer is a brutal, fully-EV'd gauntlet. Companion to the Gold/Silver Kaizo line."),
("Pokémon Low Budget Crystal", "gbc", "Crystal", "—", "Complete", ["Vanilla+", "QoL"], "Gen 2",
"",
"A light, faithful Crystal enhancement — quality-of-life tweaks and availability fixes without changing the core game."),
("Pokémon Orange", "gbc", "Crystal", "—", "Complete", ["New Experience"], "Gen 2 style",
"",
"Set in the anime's Orange Islands / Orange League. This is the modern Suloku-patched build with bug fixes and PSS-era touches."),
("Pokémon Peridot", "gbc", "Crystal", "2.2.3", "Ongoing", ["New Experience"], "Gen 2 style",
"",
"A from-scratch new region on the Gen 2 engine with an original dex and story."),
("Pokémon Polished Crystal", "gbc", "Crystal", "3.2.3", "Complete", ["Vanilla+", "QoL", "Expansion"], "Gen 17 mons",
"https://github.com/Rangi42/polishedcrystal",
"The gold standard Crystal enhancement: physical/special split, ~Gen 7 movesets/species availability, faithful or modern modes, tons of QoL. Open-source decomp."),
("Pokémon Prism", "gbc", "Crystal", "1.0", "Complete", ["New Experience"], "Gen 2+",
"https://www.pokecommunity.com/threads/pokemon-prism.379413/",
"Koolboyman's acclaimed new Naljo region — new types, side games, huge custom dex. Famously C&D'd then completed; a Gen 2 magnum opus."),
# ---------------- GBA ----------------
("Pokémon Adventure - Red Chapter", "gba", "FireRed", "Beta 15", "Complete (beta)", ["New Experience"], "Gen 16 mons",
"https://www.pokecommunity.com/threads/pokemon-adventure-red-chapter.331313/",
"Based on the Pokémon Adventures (Pokémon Special) manga — play through Red's story with manga events. Beta 15 is the full, finished beta."),
("Pokémon Aesthetic Red", "gba", "FireRed", "1.1", "Complete", ["Cosmetic", "Vanilla+"], "Gen 1",
"",
"A visual + musical overhaul of FireRed — restyled tiles, sprites, and soundtrack while keeping vanilla gameplay."),
("Pokémon Amethyst", "gba", "Emerald", "1.2.0", "Ongoing", ["Expansion", "New Experience"], "Multi-gen",
"https://www.hackdex.app/hack/pokemon-amethyst",
"A pokeemerald-expansion adventure with a new region/story and modern mechanics."),
("Pokémon Crystal Advance Redux", "gba", "Emerald", "2026-05-06", "Ongoing", ["Demake", "Vanilla+"], "Gen 2 on GBA",
"",
"Pokémon Crystal rebuilt on the GBA (pokeemerald) with Gen-3+ engine conveniences — Johto with modern QoL."),
("Pokémon Dark Rising", "gba", "FireRed", "1 (Origins)", "Complete", ["New Experience", "Difficulty"], "Multi-gen + fakemon",
"https://www.pokecommunity.com/threads/pokemon-dark-rising-series.341667/",
"Notoriously hard story-driven hack with a dark plot, fakemon, and multi-gen mons. The Origins build is the remastered DR1."),
("Pokémon Dark Rising 2", "gba", "FireRed", "Complete", "Complete", ["New Experience", "Difficulty"], "Multi-gen + fakemon",
"https://www.pokecommunity.com/threads/pokemon-dark-rising-series.341667/",
"Sequel to Dark Rising — bigger story, more fakemon, same punishing difficulty."),
("Pokémon Dark Rising - Order Destroyed", "gba", "FireRed", "Complete", "Complete", ["New Experience", "Difficulty"], "Multi-gen",
"https://www.pokecommunity.com/threads/pokemon-dark-rising-series.341667/",
"A spin-off entry in the Dark Rising saga."),
("Pokémon Elite Redux", "gba", "Emerald", "2.65.3b", "Ongoing", ["Expansion", "Difficulty"], "Multi-gen",
"https://www.hackdex.app/hack/elite-redux",
"A theorycrafter's playground: every species gets multiple abilities, a vastly expanded movepool, and brutal fights. Deep team-building over story."),
("Pokémon Emerald Azure", "gba", "Emerald", "0.5.3", "Beta", ["New Experience", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/pokemon-emerald-azure",
"An in-development new-region Emerald-expansion hack (early/beta)."),
("Pokémon Emerald Extended Cut", "gba", "Emerald", "Classic+ 1.3", "Complete", ["Vanilla+", "QoL"], "Gen 3",
"",
"Emerald with restored/expanded content and QoL while staying close to the original Hoenn experience."),
("Pokémon Emerald Imperium", "gba", "Emerald", "1.3.1", "Complete", ["Expansion", "Difficulty"], "Multi-gen",
"https://www.hackdex.app/hack/emerald-imperium",
"A content- and postgame-heavy Emerald-expansion hack with challenging fights and lots of endgame."),
("Pokémon Emerald Kaizo", "gba", "Emerald", "—", "Complete", ["Difficulty"], "Gen 3",
"",
"The classic Emerald kaizo — every gym/E4 team is maxed-out and merciless."),
("Pokémon Emerald Rogue", "gba", "Emerald", "2.1.2 EX", "Ongoing", ["Roguelite", "Expansion"], "Multi-gen",
"https://github.com/Pokabbie/pokeemerald-rogue",
"A roguelite take on Emerald: run-based, procedurally routed, escalating difficulty toward the Champion. EX edition uses the modern expansion."),
("Pokémon Emerald Seaglass", "gba", "Emerald", "3.0", "Complete", ["Vanilla+", "QoL", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/pokemon-emerald-seaglass",
"Emerald modernized via the expansion — physical/special split, new species/forms, and heavy QoL while keeping Hoenn's story."),
("Pokémon Emerald Squared", "gba", "Emerald", "2.6.2", "Complete", ["Difficulty", "Vanilla+"], "Gen 3",
"",
"An enhanced, harder Emerald — rebalanced trainers and availability for a tougher Hoenn run."),
("Pokémon Fire of Sky", "gba", "—", "1.0.3", "Complete", ["New Experience"], "Multi-gen",
"",
"A story-focused new-adventure hack."),
("Pokémon FireRed Deluxe", "gba", "FireRed", "20.5", "Ongoing", ["Vanilla+", "Expansion", "QoL"], "Multi-gen",
"",
"FireRed loaded with all obtainable species, modern mechanics, and QoL — a 'complete dex' enhanced Kanto."),
("Pokémon Fire Red Extended", "gba", "FireRed", "3.5.6", "Ongoing", ["Vanilla+", "Expansion"], "Multi-gen",
"",
"FireRed extended with later-gen species and mechanics while preserving the Kanto journey."),
("Pokémon FireRed & LeafGreen+ (FRLG+)", "gba", "FireRed", "1.5.1", "Ongoing", ["Vanilla+", "QoL"], "Gen 13",
"",
"A faithful 'plus' enhancement of FR/LG — availability fixes, split, and QoL with minimal change to the feel."),
("Pokémon FireRed Reignited", "gba", "FireRed", "1.55", "Ongoing", ["Vanilla+", "QoL"], "Gen 1+",
"",
"A modern QoL remaster of FireRed."),
("Pokémon Flora Sky", "gba", "Emerald", "Complete", "Complete", ["New Experience"], "Gen 34 mons",
"https://www.pokecommunity.com/threads/pokemon-flora-sky.179365/",
"A classic complete Emerald hack with a new region, Gen 4 additions, and a sky/Distortion-World-flavored plot."),
("Pokémon Gaia", "gba", "FireRed", "3.2", "Complete", ["New Experience"], "Gen 16 mons",
"https://www.pokecommunity.com/threads/pokemon-gaia.336982/",
"Widely considered one of the best hacks ever: the Orbtus region, Gen 6 mechanics/Fairy type, an archaeology mystery, and Nintendo-grade polish."),
("Pokémon Glazed", "gba", "Emerald", "9.2.0", "Complete", ["New Experience"], "Gen 16 mons",
"https://www.pokecommunity.com/threads/pokemon-glazed.291376/",
"A long-beloved new region (Tunod) crossing into Johto, with multiple starters incl. later gens. This is the polished modern build."),
("Pokémon GS Chronicles", "gba", "FireRed", "2.7.6", "Complete", ["New Experience", "Demake"], "Gen 17 mons",
"https://www.pokecommunity.com/threads/pokemon-gs-chronicles.346730/",
"A HeartGold/SoulSilver-style Johto remake on GBA with modern mechanics and a rich postgame."),
("Pokémon Heart and Soul", "gba", "FireRed", "1.2.1", "Ongoing", ["New Experience", "Demake"], "Johto",
"",
"A Johto-focused adventure inspired by the Gen 2/HGSS games."),
("Pokémon Hearth", "gba", "Emerald", "0.1.27", "Beta", ["New Experience", "Expansion"], "Multi-gen",
"",
"An early-beta new-region expansion hack."),
("Pokémon Hoenn's Last Wish", "gba", "Emerald", "0.4.7", "Beta", ["New Experience", "Expansion"], "Multi-gen",
"",
"An in-development Hoenn-set adventure on the Emerald expansion (early/beta)."),
("Pokémon Inclement Emerald", "gba", "Emerald", "—", "Complete", ["Difficulty", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/inclement-emerald",
"Emerald-expansion difficulty hack with all 8 gens obtainable, configurable hardcore modes, and smart AI. A modern favorite."),
("Pokémon Inkwell", "gba", "Emerald", "1.04", "Ongoing", ["New Experience", "Expansion"], "Multi-gen",
"",
"A new-adventure hack built on the Emerald expansion."),
("Pokémon Lazarus", "gba", "Emerald (TrashMan)", "v2", "Ongoing", ["New Experience", "Expansion"], "Multi-gen",
"https://ko-fi.com/nemo622",
"The Ilios region — a story-rich expansion hack by Nemo622 with new mechanics and detailed documentation."),
("Pokémon Light Platinum", "gba", "Ruby", "1.1", "Complete", ["New Experience"], "Gen 14 mons",
"https://www.pokecommunity.com/threads/pokemon-light-platinum.171377/",
"A classic: the Zhery region with two leagues, Gen 4 mons, and a globe-trotting plot. Hugely popular older hack."),
("Pokémon Liquid Crystal", "gba", "FireRed", "3.3", "Complete", ["New Experience", "Demake"], "Gen 14 mons",
"https://www.pokecommunity.com/threads/pokemon-liquid-crystal.158473/",
"A Johto (Crystal) remake on GBA with the Orange Islands postgame and modern conveniences."),
("Pokémon Mega Power", "gba", "Ruby", "5.62", "Complete", ["New Experience"], "Gen 16 mons",
"https://www.pokecommunity.com/threads/pokemon-mega-power.330510/",
"By the Light Platinum-adjacent team — a new region with Mega Evolution, custom villains, and a 'build the strongest Pokémon' plot."),
("Pokémon Modern Emerald", "gba", "Emerald", "3.3.1", "Complete", ["Vanilla+", "QoL", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/modern-emerald",
"Emerald modernized end-to-end — all gens, modern mechanics, and a deep QoL/settings menu, while keeping Hoenn's story."),
("Pokémon Moemon Mega FireRed", "gba", "FireRed", "1.4c", "Complete", ["Cosmetic"], "Gen 1",
"",
"A Moemon hack — Pokémon replaced with anthropomorphic 'moe' character sprites — over an enhanced FireRed."),
("Pokémon Moemon Star Emerald", "gba", "Emerald", "1.1c", "Complete", ["Cosmetic"], "Gen 3",
"",
"A Moemon reskin of an enhanced Emerald (Star Emerald), with moe sprites throughout."),
("Pokémon Odyssey", "gba", "FireRed", "4.1.1", "Complete", ["New Experience"], "Multi-gen",
"https://www.hackdex.app/hack/pokemon-odyssey",
"A highly-praised, atmospheric original adventure with a custom region, strong writing, and bespoke pixel art."),
("Pokémon Omega Ruby Origins", "gba", "Emerald", "1.4.8.7", "Ongoing", ["Demake", "New Experience"], "Gen 6 on GBA",
"",
"An ORAS-style demake bringing the 3DS Hoenn remakes' features back to the GBA."),
("Pokémon Phoenix Red", "gba", "FireRed", "1.2", "Complete", ["Difficulty", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/pokemon-phoenix-red",
"An enhanced, harder FireRed with all 8 gens obtainable, Megas, and tough fights."),
("Pokémon Pisces", "gba", "—", "1.5.4", "Complete", ["New Experience"], "Multi-gen",
"",
"An original-region adventure hack."),
("Pokémon Project Nova", "gba", "Emerald", "2.7.0", "Ongoing", ["New Experience", "Expansion"], "Multi-gen",
"",
"A new-experience hack on the Emerald expansion."),
("Pokémon Radical Red", "gba", "FireRed", "4.10", "Ongoing", ["Difficulty", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/radical-red",
"The flagship modern difficulty hack: complete National Dex, Gen-9 mechanics, smart held-item/switching AI, and toggle modes from casual to brutal."),
("Pokémon Recordkeepers", "gba", "Emerald", "1.2.1", "Ongoing", ["New Experience", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/recordkeepers",
"A narrative-driven Emerald-expansion hack."),
("Pokémon Resolute", "gba", "Ruby", "2.97", "Complete", ["New Experience"], "Gen 16 mons",
"https://www.pokecommunity.com/threads/pokemon-resolute.330577/",
"A story-heavy new region (Sun-Moon-era mons added) with a difficulty mode; from the Mega Power/Light Platinum lineage."),
("Pokémon R.O.W.E.", "gba", "Emerald", "2.1.1", "Ongoing", ["New Experience", "QoL", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/pokemon-rowe",
"Open-world Emerald — level scaling, ride-anywhere, nuzlocke-friendly settings, and all gens. The 'Mega Update' build."),
("Pokémon Saiph", "gba", "FireRed", "2020", "Complete", ["New Experience"], "Multi-gen",
"https://www.pokecommunity.com/threads/pokemon-saiph.412313/",
"A complete original-region story hack with a darker tone."),
("Pokémon Saiph 2", "gba", "FireRed", "1.4.0", "Complete", ["New Experience"], "Multi-gen",
"https://www.pokecommunity.com/threads/pokemon-saiph-2.456789/",
"Sequel to Saiph — a larger, polished original adventure (full release v1.4.0)."),
("Pokémon Snakewood", "gba", "Ruby", "—", "Complete", ["New Experience"], "Gen 3 + fakemon",
"https://www.pokecommunity.com/threads/pokemon-snakewood.146749/",
"A cult-classic zombie-apocalypse reimagining of Hoenn — surreal, dark-comedic, and famously weird. Largely complete."),
("Pokémon Sors", "gba", "FireRed", "1.3", "Complete", ["New Experience"], "Multi-gen",
"https://www.pokecommunity.com/threads/pokemon-sors.420576/",
"A complete story-driven hack with a full new region and extensive item/guide documentation."),
("Pokémon Sovereign of the Skies", "gba", "FireRed", "2.1.2", "Complete", ["New Experience"], "Multi-gen",
"https://www.pokecommunity.com/threads/pokemon-sovereign-of-the-skies.349500/",
"A complete new region with custom dex and a sky-themed plot."),
("Pokémon Super Mariomon", "gba", "Emerald", "1.5.2", "Complete", ["New Experience", "Cosmetic"], "Crossover",
"",
"A Mario × Pokémon crossover: catch and battle Mario-universe characters as 'Mariomon'. A complete novelty hack."),
("Pokémon Sword and Shield Ultimate Plus", "gba", "FireRed", "1.2.1.2", "Ongoing", ["Demake", "New Experience"], "Gen 8 on GBA",
"",
"A Galar (Sword/Shield) demake bringing Gen 8's region, Pokémon, and Dynamax-era content to the GBA."),
("Pokémon The Pit", "gba", "Emerald", "2.5.1", "Ongoing", ["Roguelite", "Difficulty", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/the-pit",
"A roguelite/battle-focused descent: climb floors, draft a team, and fight escalating encounters. Built on the Emerald expansion."),
("Pokémon Theta Emerald EX", "gba", "Emerald", "EX", "Complete", ["Expansion", "Vanilla+"], "Gen 16 mons",
"https://www.pokecommunity.com/threads/pokemon-theta-emerald-ex.366617/",
"Classic 'all 800+ mons in Emerald' hack — Megas, Fairy type, and the full dex obtainable within Hoenn's story."),
("Pokémon Tourmaline", "gba", "Emerald", "1.1.1", "Ongoing", ["New Experience", "Expansion"], "Multi-gen",
"",
"A new-region adventure on the Emerald expansion."),
("Pokémon Valiant", "gba", "Emerald", "4.2.3", "Ongoing", ["New Experience", "Expansion"], "Multi-gen",
"https://www.hackdex.app/hack/pokemon-valiant",
"An original-region story hack on the Emerald expansion with custom characters and content."),
("Pokémon WaveBlue", "gba", "FireRed", "1.7.5", "Ongoing", ["New Experience"], "Multi-gen",
"",
"A new-region adventure built on FireRed."),
# ---------------- NDS ----------------
("Pokémon Blaze Black", "nds", "Black", "—", "Complete", ["Vanilla+", "Difficulty"], "Gen 15 mons",
"https://www.pokecommunity.com/threads/pokemon-blaze-black-volt-white.252355/",
"Drayano's Black overhaul — every species catchable in-game, boosted gym/E4 teams, and QoL. Pairs with Volt White."),
("Pokémon Blaze Black 2 Redux", "nds", "Black 2", "1.3.0", "Complete", ["Vanilla+", "Difficulty", "Expansion"], "Gen 15 mons",
"https://www.pokecommunity.com/",
"A community 'Redux' fork of Drayano's Blaze Black 2 — expanded availability, rebalanced difficulty, and extra content."),
("Pokémon Following Renegade Platinum", "nds", "Platinum", "2.0", "Complete", ["Difficulty", "Vanilla+", "QoL"], "Gen 14 mons",
"https://www.reddit.com/r/PokemonROMhacks/comments/s4fbhi/",
"Renegade Platinum with following Pokémon added — the acclaimed enhanced Sinnoh plus an HGSS-style walking partner."),
("Pokémon Renegade Platinum", "nds", "Platinum", "1.3.0", "Complete", ["Difficulty", "Vanilla+"], "Gen 14 mons",
"https://www.pokecommunity.com/threads/pokemon-renegade-platinum.347531/",
"Drayano's definitive enhanced Platinum — full availability, much harder fights, and QoL. A community favorite Sinnoh run."),
("Pokémon Sacred Gold", "nds", "HeartGold", "1.05", "Complete", ["Vanilla+", "Difficulty"], "Gen 14 mons",
"https://www.pokecommunity.com/threads/pokemon-sacred-gold-storm-silver.165088/",
"Drayano's enhanced HeartGold — all species obtainable, boosted teams, fixed movesets. Pairs with Storm Silver."),
("Pokémon Storm Silver", "nds", "SoulSilver", "1.05", "Complete", ["Vanilla+", "Difficulty"], "Gen 14 mons",
"https://www.pokecommunity.com/threads/pokemon-sacred-gold-storm-silver.165088/",
"Drayano's enhanced SoulSilver — the SoulSilver counterpart to Sacred Gold."),
("Pokémon Volt White", "nds", "White", "—", "Complete", ["Vanilla+", "Difficulty"], "Gen 15 mons",
"https://www.pokecommunity.com/threads/pokemon-blaze-black-volt-white.252355/",
"Drayano's White overhaul — full availability and boosted difficulty. The White counterpart to Blaze Black."),
("Pokémon Volt White 2 Redux", "nds", "White 2", "1.4.1", "Complete", ["Vanilla+", "Difficulty", "Expansion"], "Gen 15 mons",
"https://www.pokecommunity.com/",
"A community 'Redux' fork of Drayano's Volt White 2 — expanded availability and rebalanced difficulty."),
]
PLAT_NAME = {"gb": "Game Boy", "gbc": "Game Boy Color", "gba": "Game Boy Advance", "nds": "Nintendo DS"}
def slugify_filename(title):
# note filename: drop the "Pokémon " prefix for tidiness, keep the rest
name = re.sub(r"^Pok[ée]mon\s+", "", title)
return name.replace("/", "-")
def yaml_list(items):
return "[" + ", ".join(f'"{i}"' for i in items) + "]"
def lookup_url(title):
q = urllib.parse.quote(f"{title} rom hack")
return f"https://duckduckgo.com/?q={q}"
def write(path, content):
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
f.write(content)
def gen_hack_note(h):
title, plat, base, ver, status, types, gen, url, summary = h
fname = slugify_filename(title)
libname = "Pokemon - " + re.sub(r"^Pok[ée]mon\s+", "", title).replace("é", "e").replace("É", "E") + f" (Hack).{plat}"
tags = [f"hack", f"platform/{plat}", f"base/{base_tag(base)}",
f"status/{re.sub(r'[^a-z0-9]+','',status.lower())}"]
tags += [f"type/{re.sub(r'[^a-z0-9+]+','',t.lower())}" for t in types]
fm = [
"---",
f'title: "{title}"',
f"platform: {plat.upper()}",
f'base: "{base}"',
f'version: "{ver}"',
f'status: "{status}"',
f"type: {yaml_list(types)}",
f'generation: "{gen}"',
f'library_path: "roms/{plat}/{libname}"',
f'source: "{url or lookup_url(title)}"',
f"added: {ADDED}",
f"tags: {yaml_list(tags)}",
"---",
"",
]
body = [
f"# {title}",
"",
f"> [!info] {' · '.join(types)} — **{status}**",
f"> {PLAT_NAME[plat]} · base **{base}** · version **{ver}** · {gen}",
"",
"## Summary",
summary,
"",
"## Type",
" ".join(f"[[Types#{t}|{t}]]" for t in types),
"",
"## Links",
f"- Source / info: {url}" if url else "- Source: _(not catalogued — see lookup)_",
f"- Lookup: {lookup_url(title)}",
"",
"## In the library",
f"- `roms/{plat}/{libname}` on valhalla",
f"- Patch/source artifact archived under `/storage1/igir/romhacks/patches/`",
"",
"[[Index|← back to directory]]",
"",
]
return "\n".join(fm) + "\n".join(body)
def slug_libpath(title):
name = re.sub(r"^Pok[ée]mon\s+", "", title)
name = name.replace("é", "e").replace("É", "E")
# match the on-disk naming: "Pokemon - <name> (Hack).<ext>"
ext = {"gb": "gb", "gbc": "gbc", "gba": "gba", "nds": "nds"}
return f"Pokemon - {name} (Hack)" # ext appended by reader; on disk has platform ext
def gen_index():
rows = []
for h in sorted(HACKS, key=lambda x: (x[1], x[0])):
title, plat, base, ver, status, types, gen, url, summary = h
link = f"[[{slugify_filename(title)}]]"
rows.append(f"| {link} | {plat.upper()} | {base} | {ver} | {status} | {', '.join(types)} |")
static = "\n".join(rows)
dv = (
"```dataview\n"
"TABLE platform AS Platform, base AS Base, version AS Version, status AS Status, type AS Type\n"
'FROM "Hacks"\n'
"SORT platform ASC, file.name ASC\n"
"```\n"
)
counts = {}
for h in HACKS:
counts[h[1]] = counts.get(h[1], 0) + 1
countline = " · ".join(f"**{PLAT_NAME[p]}**: {counts.get(p,0)}" for p in ["gb","gbc","gba","nds"])
return f"""# Pokémon ROM-Hack Library — Index
A knowledge base for the **{len(HACKS)}** Pokémon ROM-hacks installed in the valhalla
library (`roms/<platform>/Hacks/`). One note per hack — see [[Types]] for the tag
taxonomy and the [[#Platforms]] section for per-system views.
{countline}
## Directory (Dataview)
> Requires the Dataview plugin. If you don't use it, the static table below mirrors it.
{dv}
## Directory (static)
| Hack | Platform | Base | Version | Status | Type |
|---|---|---|---|---|---|
{static}
## Platforms
- [[GBA]] · [[GBC]] · [[GB]] · [[NDS]]
## By type
{chr(10).join(f"- [[Types#{t}|{t}]] — {d}" for t, d in TYPES.items())}
---
*Generated by `scripts/build-romhack-vault.py` — edit the dataset there and re-run to update.*
"""
def gen_types():
body = ["# Type Taxonomy", "",
"Each hack is tagged with one or more of these. Tags are also queryable as `#type/...`.", ""]
for t, d in TYPES.items():
members = [slugify_filename(h[0]) for h in sorted(HACKS) if t in h[5]]
body.append(f"## {t}")
body.append(d)
body.append("")
body.append(f"`#type/{re.sub(r'[^a-z0-9+]+','',t.lower())}` — {len(members)} hacks")
body.append("")
body += [f"- [[{m}]]" for m in members]
body.append("")
body.append("[[Index|← back to directory]]")
return "\n".join(body)
def gen_platform(plat):
members = [h for h in sorted(HACKS) if h[1] == plat]
rows = [f"| [[{slugify_filename(h[0])}]] | {h[2]} | {h[3]} | {h[4]} | {', '.join(h[5])} |" for h in members]
dv = ("```dataview\nTABLE base, version, status, type\n"
f'FROM "Hacks"\nWHERE platform = "{plat.upper()}"\nSORT file.name ASC\n```\n')
return (f"# {PLAT_NAME[plat]} ({plat.upper()}) — {len(members)} hacks\n\n{dv}\n"
"## Static\n\n| Hack | Base | Version | Status | Type |\n|---|---|---|---|---|\n"
+ "\n".join(rows) + "\n\n[[Index|← back to directory]]\n")
def gen_readme():
return f"""# Pokémon ROM-Hack Vault
An [Obsidian](https://obsidian.md) vault documenting the **{len(HACKS)}** Pokémon ROM-hacks
in the valhalla library. Open *this folder* as a vault (or copy it into an existing one).
## Layout
- **[[Index]]** — the master directory (Dataview + static table).
- **[[Types]]** — the type taxonomy (QoL, Vanilla+, Difficulty, Expansion, New Experience, Demake, Roguelite, Cosmetic).
- **Hacks/** — one note per hack with frontmatter properties + tags.
- **Platforms/** — per-system maps of content (GBA / GBC / GB / NDS).
## Conventions
- Frontmatter uses Obsidian **properties** (`platform`, `base`, `version`, `status`, `type`, `generation`, `source`) so the **Dataview** and **Bases** plugins work.
- Every note also carries **tags** (`#platform/gba`, `#type/difficulty`, `#status/complete`, `#base/firered`) so search/graph work with **zero plugins**.
- `library_path` points at the file under `roms/<platform>/Hacks/` on valhalla.
## Recommended plugins
- **Dataview** (the Index/Platform tables) and optionally **Bases** (Obsidian's native DB view).
## Caveats
- `base`, `version`, and `type` are best-effort from the import metadata + general knowledge; a few obscure hacks show `base: —` where the source wasn't certain. Correct any in `scripts/build-romhack-vault.py` and re-run.
*Generated by `scripts/build-romhack-vault.py`.*
"""
def main():
# clean Hacks dir to avoid stale notes, then regenerate
for h in HACKS:
write(os.path.join(VAULT, "Hacks", slugify_filename(h[0]) + ".md"), gen_hack_note(h))
write(os.path.join(VAULT, "Index.md"), gen_index())
write(os.path.join(VAULT, "Types.md"), gen_types())
write(os.path.join(VAULT, "README.md"), gen_readme())
for p in ["gb", "gbc", "gba", "nds"]:
write(os.path.join(VAULT, "Platforms", PLAT_NAME[p].split()[0] if False else p.upper() + ".md"),
gen_platform(p))
print(f"vault written to {os.path.normpath(VAULT)}{len(HACKS)} hack notes + Index/Types/README + 4 platform MOCs")
if __name__ == "__main__":
main()