diff --git a/scripts/annotate-engines.py b/scripts/annotate-engines.py new file mode 100644 index 0000000..cbaef78 --- /dev/null +++ b/scripts/annotate-engines.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +"""Annotate ROM-hack notes with the engine/base framework they're built on. + +Adds an `engine:` frontmatter key + an `· engine **X**` token to the note's +`> [!info]` callout line. Idempotent: re-running skips notes already annotated, +so it's safe to run after future enrichment passes. + +WHY a frozen map: engine attribution is research, not scrape metadata. This file +doubles as the provenance record — each entry is tagged confirmed vs likely with +the evidence behind it (see comments). Confirmed = a source explicitly names the +engine; likely = strong era + feature-fingerprint inference, flagged "(likely)" +in the value so it stays honest and queryable. + +Engine frameworks: + - CFRU (Complete FireRed Upgrade) + DPE (Dynamic Pokémon Expansion) — Skeli789 + & ghoulslash. Binary engine injected into a FireRed ROM. The modern FireRed + base for full-dex / Gen-9-mechanics hacks. + - pokefirered (decomp) — pret's FireRed disassembly. The *other* modern FireRed + base; distinct from CFRU (decomp vs binary). + - pokeemerald-expansion — RHH (Rom Hack Hideout), built on pret's pokeemerald + decomp. The Emerald analogue of CFRU. + - pokeemerald (decomp) — pret's plain Emerald decomp / Pokabbie's rogue fork. + - hg-engine — BluRosie. HeartGold engine overhaul (the HGSS analogue). + +Run: python scripts/annotate-engines.py [""] +""" +import os, re, sys, glob + +DEFAULT_VAULT = r"C:\Users\MattC\Documents\Obsidian Vault" +CATALOG = "Pokémon ROM Hacks" + +# stem -> engine value. "(likely)" suffix = inferred, not source-confirmed. +ENGINE_MAP = { + # --- FireRed → CFRU + DPE (confirmed) ------------------------------------- + "Radical Red": "CFRU + DPE", # docs/community: CFRU+DPE, Skeli789 + "Unbound": "CFRU", # "powered by CFRU alongside custom code" + "Fire Red 898": "CFRU + DPE", # uses CFRU+DPE+Leon's Rombase + "Aesthetic Red": "CFRU + DPE", # PokeHarbor: CFRU+DPE engine base + # --- FireRed → CFRU (likely: modern full-dex + CFRU feature fingerprint) --- + "Roaring Red": "CFRU + DPE (likely)", # 2025, modern mechanics, 386 dex + "Astral Red": "CFRU + DPE (likely)", # 2024; QoL list = CFRU defaults + "Fire Red Extended": "CFRU (likely)", # being reworked onto CFRU + # --- FireRed → pokefirered decomp (likely; NOT CFRU) ---------------------- + "FireRed Reignited": "pokefirered (decomp, likely)", + "FireRed Reignited LeafGreen Regrown": "pokefirered (decomp, likely)", + # --- Emerald → pokeemerald-expansion (RHH) -------------------------------- + "Inclement Emerald": "pokeemerald-expansion", # decomp difficulty hack + "Emerald Seaglass": "pokeemerald-expansion", # confirmed + "Modern Emerald": "pokeemerald-expansion", # confirmed + "Energized Emerald": "pokeemerald-expansion", # confirmed + "Inverse Emerald": "pokeemerald-expansion", # confirmed (pret + rh-hideout) + "R.O.W.E.": "pokeemerald-expansion", # open-world decomp, Gen 9 + "Blazing Emerald": "pokeemerald-expansion (likely)", + "Ephemerald": "pokeemerald-expansion (likely)", + # --- Emerald → pokeemerald decomp (Pokabbie rogue fork) ------------------- + "Emerald Rogue": "pokeemerald (decomp)", # github.com/Pokabbie/pokeemerald-rogue + "Emerald Rogue 2.0": "pokeemerald (decomp)", + # --- Recharged series (Jaizu) → decomp; expansion-feature fingerprint ----- + # Vanilla+ QoL hacks with optional Nuzlocke/level-cap toggles; following mons, + # mints/bottle caps, Fairy type, HM revamp == pokeemerald-expansion features. + "Recharged Emerald": "pokeemerald-expansion (likely)", + "Recharged Emerald Rebalanced": "pokeemerald-expansion (likely)", # rebalanced/difficulty variant + "Recharged Pink": "pokeemerald-expansion (likely)", + "Recharged Yellow (previously known as Pok├⌐mon Yellow Cross)": "pokeemerald-expansion (likely)", + # Emerald Cross (Jaizu) — vanilla+ QoL/bugfix, no expansion → lighter decomp build + "Emerald Cross": "pokeemerald (decomp, likely)", + # --- HeartGold → hg-engine ------------------------------------------------ + "HeartGold Generation": "hg-engine", # body already says hg-engine +} + +# Notes whose scrape left base/version broken — fix while we're in there. +FIXUPS = { + "HeartGold Generation": {"base": "HeartGold", "version": "2.0"}, +} + + +def annotate(path): + text = open(path, encoding="utf-8").read() + stem = os.path.splitext(os.path.basename(path))[0] + engine = ENGINE_MAP[stem] + fix = FIXUPS.get(stem, {}) + lines = text.split("\n") + + # locate frontmatter bounds + if lines[0].strip() != "---": + return f" SKIP {stem}: no frontmatter" + fm_end = next(i for i in range(1, len(lines)) if lines[i].strip() == "---") + + changed = [] + + # --- fixups (base/version) in frontmatter + callout ----------------------- + for key, val in fix.items(): + for i in range(1, fm_end): + m = re.match(rf'^{key}:\s*(.*)$', lines[i]) + if m and m.group(1).strip(' "') != val: + lines[i] = f'{key}: {val}' + changed.append(f"{key}->{val}") + break + + # --- engine: in frontmatter (after base:, idempotent) --------------------- + if any(re.match(r'^engine:\s', l) for l in lines[1:fm_end]): + pass # already present + else: + base_i = next((i for i in range(1, fm_end) + if re.match(r'^base:\s', lines[i])), fm_end - 1) + lines.insert(base_i + 1, f'engine: "{engine}"') + fm_end += 1 + changed.append("frontmatter engine") + + # --- callout token (append to the line after `> [!info]`) ----------------- + info_i = next((i for i, l in enumerate(lines) + if l.strip().startswith("> [!info]")), None) + if info_i is not None and info_i + 1 < len(lines): + meta = lines[info_i + 1] + if meta.lstrip().startswith(">") and "· engine **" not in meta: + # apply base/version fixups to the callout line too + for key, val in fix.items(): + meta = re.sub(rf'{key} \*\*[^*]*\*\*', f'{key} **{val}**', meta) + lines[info_i + 1] = meta.rstrip() + f" · engine **{engine}**" + changed.append("callout token") + + if not changed: + return f" ok {stem}: already annotated" + open(path, "w", encoding="utf-8").write("\n".join(lines)) + return f" EDIT {stem}: {', '.join(changed)}" + + +def main(): + vault = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_VAULT + hacks = os.path.join(vault, CATALOG, "Hacks") + if not os.path.isdir(hacks): + sys.exit(f"Hacks dir not found: {hacks}") + by_stem = {os.path.splitext(os.path.basename(p))[0]: p + for p in glob.glob(os.path.join(hacks, "*.md"))} + missing = [s for s in ENGINE_MAP if s not in by_stem] + print(f"Annotating {len(ENGINE_MAP)} notes ({len(missing)} missing):") + for stem in ENGINE_MAP: + if stem in by_stem: + print(annotate(by_stem[stem])) + else: + print(f" MISS {stem}: no note found") + + +if __name__ == "__main__": + main() diff --git a/scripts/build-vault-mocs.py b/scripts/build-vault-mocs.py index 38d51a2..d2a9356 100644 --- a/scripts/build-vault-mocs.py +++ b/scripts/build-vault-mocs.py @@ -75,6 +75,7 @@ def load_records(hacks_dir): "base": fm.get("base") or DASH, "version": fm.get("version") or DASH, "status": fm.get("status") or DASH, + "engine": fm.get("engine") or DASH, "type": typ, }) return recs @@ -159,17 +160,17 @@ def platform_static_table(recs): def base_static_table(recs, with_base): if with_base: - head = "| Hack | Base | Version | Dev | Type |\n|---|---|---|---|---|" + head = "| Hack | Base | Version | Dev | Engine | Type |\n|---|---|---|---|---|---|" rows = [ f"| [[{r['stem']}]] | {cell(r['base'])} | {cell(r['version'])} | " - f"{cell(r['status'])} | {types_cell(r['type'])} |" + f"{cell(r['status'])} | {cell(r['engine'])} | {types_cell(r['type'])} |" for r in sorted(recs, key=key) ] else: - head = "| Hack | Version | Dev | Type |\n|---|---|---|---|" + head = "| Hack | Version | Dev | Engine | Type |\n|---|---|---|---|---|" rows = [ f"| [[{r['stem']}]] | {cell(r['version'])} | {cell(r['status'])} | " - f"{types_cell(r['type'])} |" + f"{cell(r['engine'])} | {types_cell(r['type'])} |" for r in sorted(recs, key=key) ] return head + "\n" + "\n".join(rows) diff --git a/scripts/build-wiki-data.py b/scripts/build-wiki-data.py index ee5c317..2d9d303 100644 --- a/scripts/build-wiki-data.py +++ b/scripts/build-wiki-data.py @@ -21,7 +21,7 @@ OUT = os.path.join(OUT_DIR, "catalog.json") SCALARS = ["title", "platform", "base", "version", "status", "generation", "developer", "release_date", "banner", "homepage", "source", - "library_path", "play_status", "scrape_dir"] + "library_path", "play_status", "scrape_dir", "engine"] def section(body, heading): @@ -79,6 +79,7 @@ def main(): return dict(sorted(c.items(), key=lambda kv: (-kv[1], kv[0]))) type_counts = Counter(t for h in hacks for t in h["type"]) + engine_counts = Counter(h["engine"] for h in hacks if h.get("engine")) out = { "generated": date.today().isoformat(), "count": len(hacks), @@ -86,6 +87,7 @@ def main(): "platform": facet("platform"), "base": facet("base"), "status": facet("status"), + "engine": dict(sorted(engine_counts.items(), key=lambda kv: (-kv[1], kv[0]))), "type": dict(sorted(type_counts.items(), key=lambda kv: (-kv[1], kv[0]))), "play_status": facet("play_status"), }, diff --git a/scripts/pc-import-staging.py b/scripts/pc-import-staging.py new file mode 100644 index 0000000..e906571 --- /dev/null +++ b/scripts/pc-import-staging.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +"""Repack staged PC downloads from /tmp/pc-import into roms/windows/.""" +import os +import subprocess +import tempfile +import zipfile +import shutil + +DEST = "/storage1/Emulation/roms/windows" +STAGE = "/tmp/pc-import" + + +def repack_rar_to_zip(rar_path, dest_zip): + tmp = tempfile.mkdtemp(prefix="pcrepack_") + try: + r = subprocess.run(["bsdtar", "-xf", rar_path, "-C", tmp], capture_output=True, text=True) + if r.returncode != 0: + return False, "bsdtar: " + (r.stderr or r.stdout)[:200] + tmp_zip = dest_zip + ".part" + with zipfile.ZipFile(tmp_zip, "w", zipfile.ZIP_DEFLATED) as z: + for root, _, files in os.walk(tmp): + for fn in files: + fp = os.path.join(root, fn) + z.write(fp, os.path.relpath(fp, tmp)) + os.replace(tmp_zip, dest_zip) + has_exe = any(fn.lower() == "game.exe" for fn in os.listdir(tmp)) + return True, f"{os.path.getsize(dest_zip):,} bytes, Game.exe={has_exe}" + finally: + shutil.rmtree(tmp, ignore_errors=True) + + +def merge_zip_overlay(base_zip, overlay_zip, dest_zip): + tmp = tempfile.mkdtemp(prefix="pcmerge_") + try: + with zipfile.ZipFile(base_zip) as z: + z.extractall(tmp) + with zipfile.ZipFile(overlay_zip) as z: + z.extractall(tmp) + tmp_zip = dest_zip + ".part" + with zipfile.ZipFile(tmp_zip, "w", zipfile.ZIP_DEFLATED) as z: + for root, _, files in os.walk(tmp): + for fn in files: + fp = os.path.join(root, fn) + z.write(fp, os.path.relpath(fp, tmp)) + os.replace(tmp_zip, dest_zip) + has_exe = os.path.exists(os.path.join(tmp, "Game.exe")) + return True, f"{os.path.getsize(dest_zip):,} bytes, Game.exe={has_exe}" + finally: + shutil.rmtree(tmp, ignore_errors=True) + + +def apply_deserted(): + base_rar = update_rar = None + for fn in os.listdir(STAGE): + if "Deserted" not in fn: + continue + if "1.4" in fn: + update_rar = os.path.join(STAGE, fn) + else: + base_rar = os.path.join(STAGE, fn) + if not base_rar: + return False, "base rar missing" + tmp = tempfile.mkdtemp(prefix="pcdeserted_") + try: + r = subprocess.run(["bsdtar", "-xf", base_rar, "-C", tmp], capture_output=True, text=True) + if r.returncode != 0: + return False, "base extract: " + (r.stderr or "")[:120] + if update_rar: + r = subprocess.run(["bsdtar", "-xf", update_rar, "-C", tmp], capture_output=True, text=True) + if r.returncode != 0: + return False, "update extract: " + (r.stderr or "")[:120] + dest_zip = os.path.join(DEST, "Pokemon - Deserted (Hack).zip") + tmp_zip = dest_zip + ".part" + with zipfile.ZipFile(tmp_zip, "w", zipfile.ZIP_DEFLATED) as z: + for root, _, files in os.walk(tmp): + for fn in files: + fp = os.path.join(root, fn) + z.write(fp, os.path.relpath(fp, tmp)) + os.replace(tmp_zip, dest_zip) + has_exe = os.path.exists(os.path.join(tmp, "Game.exe")) + return True, f"{os.path.getsize(dest_zip):,} bytes, Game.exe={has_exe}, update={bool(update_rar)}" + finally: + shutil.rmtree(tmp, ignore_errors=True) + + +def main(): + os.makedirs(DEST, exist_ok=True) + for label, fn in [ + ("bushido", lambda: repack_rar_to_zip( + f"{STAGE}/bushido.rar", f"{DEST}/Pokemon - bushido (Hack).zip")), + ("rejuvenation", lambda: merge_zip_overlay( + f"{STAGE}/rejuvenation.zip", f"{STAGE}/rejuvenation-patch.zip", + f"{DEST}/Pokemon - Rejuvenation (Hack).zip")), + ("deserted", apply_deserted), + ]: + ok, msg = fn() + print(f"{label}: {ok} {msg}") + + +if __name__ == "__main__": + main() diff --git a/wiki/catalog.json b/wiki/catalog.json index 42115af..a240ea4 100644 --- a/wiki/catalog.json +++ b/wiki/catalog.json @@ -1,25 +1,25 @@ { - "generated": "2026-06-08", - "count": 368, + "generated": "2026-06-23", + "count": 372, "facets": { "platform": { - "GBA": 188, + "GBA": 191, "NDS": 47, "Unknown": 45, - "PC": 40, + "PC": 41, "GBC": 22, "GB": 14, "3DS": 6, "Patch": 6 }, "base": { - "Unknown": 185, - "Emerald": 54, + "Unknown": 184, + "Emerald": 58, "FireRed": 50, "Crystal": 19, "Ruby": 8, + "HeartGold": 6, "Platinum": 6, - "HeartGold": 5, "SoulSilver": 4, "White": 4, "Gold": 3, @@ -49,25 +49,38 @@ "the north atlantic island nation of Iceland": 1 }, "status": { - "Complete": 168, + "Complete": 171, "Unknown": 161, - "Ongoing": 28, + "Ongoing": 29, "Beta": 10, "Complete (beta)": 1 }, + "engine": { + "pokeemerald-expansion": 6, + "pokeemerald-expansion (likely)": 6, + "CFRU + DPE": 3, + "CFRU + DPE (likely)": 2, + "pokeemerald (decomp)": 2, + "pokefirered (decomp, likely)": 2, + "CFRU": 1, + "CFRU (likely)": 1, + "hg-engine": 1, + "pokeemerald (decomp, likely)": 1 + }, "type": { "Expansion": 143, - "New Experience": 129, + "New Experience": 130, "Difficulty": 105, - "QoL": 50, - "Vanilla+": 21, + "QoL": 54, + "Vanilla+": 25, "Cosmetic": 11, "Demake": 8, "Roguelite": 5 }, "play_status": { - "Unplayed": 367, - "Playing": 1 + "Unplayed": 368, + "Completed": 3, + "Dropped": 1 } }, "image_base": "https://romhacks-files.ginnoir.com", @@ -344,6 +357,7 @@ "source": "https://duckduckgo.com/?q=Pok%C3%A9mon%20Aesthetic%20Red%20rom%20hack", "library_path": "roms/gba/Hacks/Pokemon - Aesthetic Red (Hack).gba", "play_status": "Unplayed", + "engine": "CFRU + DPE", "type": [ "Cosmetic", "Vanilla+" @@ -851,6 +865,7 @@ "library_path": "/storage1/Emulation/roms/gba/Pokemon Astral Red v1.2.gba", "play_status": "Unplayed", "scrape_dir": "Pokemon_Astral_Red", + "engine": "CFRU + DPE (likely)", "type": [ "Expansion" ], @@ -1428,8 +1443,8 @@ "stem": "Black Pearl Emerald", "title": "Pokémon Black Pearl Emerald", "platform": "GBA", - "base": null, - "version": "1.01 - 08/2024", + "base": "Emerald", + "version": "1.0.1", "status": "Complete", "generation": null, "developer": "CDO", @@ -1446,6 +1461,7 @@ "tags": [ "hack", "platform/gba", + "base/emerald", "status/complete", "type/difficulty", "type/expansion", @@ -1674,6 +1690,7 @@ "library_path": "—", "play_status": "Unplayed", "scrape_dir": "Pokemon_Blazing_Emerald", + "engine": "pokeemerald-expansion (likely)", "type": [ "Expansion", "New Experience" @@ -3737,13 +3754,13 @@ "title": "Pokémon Deserted", "platform": "PC", "base": null, - "version": null, + "version": "1.4", "status": null, "generation": null, "release_date": "2022", "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemon_Deserted/TCjUt.qR4e-small-Pokemon-Deserted-A-Short--102745be5cc33d62.jpg", "source": "https://www.pokeporto.com/pokemon-deserted/", - "library_path": "—", + "library_path": "/storage1/Emulation/roms/windows/Pokemon - Deserted (Hack).zip", "play_status": "Unplayed", "scrape_dir": "Pokemon_Deserted", "type": [ @@ -4169,6 +4186,53 @@ } ] }, + { + "stem": "Emerald Cross", + "title": "Pokémon Emerald Cross", + "platform": "GBA", + "base": "Emerald", + "version": "2.0.5", + "status": "Complete", + "generation": "Gen III", + "developer": "Jaizu", + "release_date": "2024", + "homepage": "https://www.pokecommunity.com/threads/v-0-9-2-pok%C3%A9mon-emerald-cross.466499/", + "source": "https://www.pokeharbor.com/2022/06/pokemon-emerald-cross/", + "library_path": "roms/gba/Pokemon - Emerald Cross (Hack).gba", + "play_status": "Unplayed", + "engine": "pokeemerald (decomp, likely)", + "type": [ + "Vanilla+", + "QoL" + ], + "tags": [ + "hack", + "platform/gba", + "base/emerald", + "status/complete", + "type/vanilla+", + "type/qol" + ], + "summary": "Pokémon Emerald Cross is Jaizu's \"definitive vanilla Emerald\" — a quality-of-life and bug-fix overhaul that deliberately stays faithful to the original. No expansion, no altered encounters, no modern online features; instead it irons out Emerald's long-standing bugs (broken RNG, Battle Frontier glitches, map errors) and layers on conveniences. Roughly 35h main / 60h completionist.", + "notability": "The purest \"Emerald, but smoothed out\" — vanilla Hoenn with modern comforts and zero rebalancing. Same author as the Recharged series; the lighter, more conservative sibling. See [[Nuzlocke-Friendly (Vanilla+)]] for the related QoL picks.", + "story": "", + "features": [ + "Following Pokémon; auto-run (R in the overworld)", + "Infinite / reusable TMs, bag sorting, expanded options, improved summary screen", + "Extensive vanilla bug-fixes (RNG, Battle Frontier, map errors)", + "No fakemon / expansion and no altered wild encounters — vanilla dex & difficulty" + ], + "links": [ + { + "label": "Info", + "url": "https://www.pokeharbor.com/2022/06/pokemon-emerald-cross/" + }, + { + "label": "Thread", + "url": "https://www.pokecommunity.com/threads/v-0-9-2-pok%C3%A9mon-emerald-cross.466499/" + } + ] + }, { "stem": "Emerald Extended Cut", "title": "Pokémon Emerald Extended Cut", @@ -4406,6 +4470,7 @@ "library_path": "—", "play_status": "Unplayed", "scrape_dir": "Pokemon_Emerald_Rogue_2.0", + "engine": "pokeemerald (decomp)", "type": [ "Difficulty", "Expansion" @@ -4444,6 +4509,7 @@ "source": "https://github.com/Pokabbie/pokeemerald-rogue", "library_path": "roms/gba/Hacks/Pokemon - Emerald Rogue (Hack).gba", "play_status": "Unplayed", + "engine": "pokeemerald (decomp)", "type": [ "Roguelite", "Difficulty" @@ -4493,6 +4559,7 @@ "library_path": "roms/gba/Hacks/Pokemon - Emerald Seaglass (Hack).gba", "play_status": "Unplayed", "scrape_dir": "Pokemon_Emerald_Seaglass", + "engine": "pokeemerald-expansion", "type": [ "Vanilla+", "QoL", @@ -4627,6 +4694,7 @@ "library_path": "/storage1/Emulation/roms/gba/Energized v1.0.21.gba", "play_status": "Unplayed", "scrape_dir": "Pok_mon_Energized_Emerald", + "engine": "pokeemerald-expansion", "type": [ "New Experience", "QoL" @@ -4664,6 +4732,7 @@ "library_path": "/storage1/Emulation/roms/gba/Ephemerald v1.2.zip", "play_status": "Unplayed", "scrape_dir": "Pokemon_Ephemerald", + "engine": "pokeemerald-expansion (likely)", "type": [ "New Experience" ], @@ -4955,6 +5024,7 @@ "library_path": "/storage1/Emulation/roms/gba/Pokemon Fire Red 898 Randomizer v1.2.3.gba", "play_status": "Unplayed", "scrape_dir": "Pokemon_Fire_Red_898", + "engine": "CFRU + DPE", "type": [ "Expansion" ], @@ -4997,6 +5067,7 @@ "library_path": "roms/gba/Hacks/Pokemon - Fire Red Extended (Hack).gba", "play_status": "Unplayed", "scrape_dir": "Pokemon_FireRed_Extended", + "engine": "CFRU (likely)", "type": [ "Vanilla+", "Expansion" @@ -5066,7 +5137,7 @@ "generation": "Multi-gen", "source": "https://duckduckgo.com/?q=Pok%C3%A9mon%20Fire%20of%20Sky%20rom%20hack", "library_path": "roms/gba/Hacks/Pokemon - Fire of Sky (Hack).gba", - "play_status": "Playing", + "play_status": "Completed", "type": [ "New Experience" ], @@ -5077,6 +5148,7 @@ "status/complete", "type/newexperience" ], + "rating": 3, "summary": "A story-focused new-adventure hack.", "notability": "", "story": "", @@ -5245,6 +5317,7 @@ "library_path": "—", "play_status": "Unplayed", "scrape_dir": "Pokemon_FireRed_Reignited_LeafGreen_Regrown", + "engine": "pokefirered (decomp, likely)", "type": [ "Expansion", "QoL" @@ -5304,6 +5377,7 @@ "source": "https://duckduckgo.com/?q=Pok%C3%A9mon%20FireRed%20Reignited%20rom%20hack", "library_path": "roms/gba/Hacks/Pokemon - FireRed Reignited (Hack).gba", "play_status": "Unplayed", + "engine": "pokefirered (decomp, likely)", "type": [ "Vanilla+", "QoL" @@ -5790,7 +5864,7 @@ "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemon_Gaia/IMG_9759-a786223593d3ccea.webp", "source": "https://www.pokecommunity.com/threads/pokemon-gaia.336982/", "library_path": "roms/gba/Hacks/Pokemon - Gaia (Hack).gba", - "play_status": "Unplayed", + "play_status": "Completed", "scrape_dir": "Pokemon_Gaia", "type": [ "New Experience" @@ -6376,8 +6450,8 @@ "stem": "HeartGold Generation", "title": "Pokémon HeartGold Generation", "platform": "NDS", - "base": null, - "version": "s of the hack for those who pr", + "base": "HeartGold", + "version": "2.0", "status": "Ongoing", "generation": "Gen IV", "release_date": "2025", @@ -6386,6 +6460,7 @@ "library_path": "/storage1/Emulation/roms/nds/Pokemon Heart Gold Generations Full Version 05AUG2025.nds", "play_status": "Unplayed", "scrape_dir": "Pokemon_HeartGold_Generation", + "engine": "hg-engine", "type": [ "Expansion", "QoL" @@ -6889,6 +6964,7 @@ "library_path": "roms/gba/Hacks/Pokemon - Inclement Emerald (Hack).gba", "play_status": "Unplayed", "scrape_dir": "Pokemon_Inclement_Emerald", + "engine": "pokeemerald-expansion", "type": [ "Difficulty", "Expansion" @@ -7040,7 +7116,7 @@ "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemon_Infinite_Fusion/FB_IMG_1709754195267-745fda0d8b7fee05.jpg", "homepage": "https://infinitefusion.fandom.com/", "source": "https://www.pokeharbor.com/2023/03/pokemon-infinite-fusion/", - "library_path": "—", + "library_path": "roms/pc/Pokemon - Infinite Fusion (sprite-seeded).zip", "play_status": "Unplayed", "scrape_dir": "Pokemon_Infinite_Fusion", "type": [ @@ -7194,6 +7270,7 @@ "library_path": "—", "play_status": "Unplayed", "scrape_dir": "Pokemon_Inverse_Emerald", + "engine": "pokeemerald-expansion", "type": [ "Expansion", "QoL" @@ -8551,6 +8628,7 @@ "library_path": "roms/gba/Hacks/Pokemon - Modern Emerald (Hack).gba", "play_status": "Unplayed", "scrape_dir": "Pok_mon_Modern_Emerald", + "engine": "pokeemerald-expansion", "type": [ "Vanilla+", "QoL", @@ -9098,6 +9176,36 @@ } ] }, + { + "stem": "Myth 2", + "title": "Pokémon Myth 2", + "platform": "PC", + "base": null, + "version": "0.9.8", + "status": "Ongoing", + "generation": null, + "developer": "falcary", + "release_date": "2024", + "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemon_Myth/0eff5b6f02d4c0adadf739dfcdeed4cf-ff58ac1a98160369.png", + "source": "https://www.mediafire.com/file/pfb200uk53diizh/Pokemon-Myth.zip/file", + "library_path": "/storage1/Emulation/roms/windows/Pokemon - Myth 2 (Hack).zip", + "play_status": "Unplayed", + "scrape_dir": "Pokemon_Myth", + "type": [ + "New Experience" + ], + "tags": [ + "hack", + "platform/pc", + "status/ongoing", + "type/newexperience" + ], + "summary": "Sequel to [[Myth]] — falcary's long-form RPG Maker XP fangame in the Mythan region. v0.9.8 is the build ginnoir placed in the RomM `windows` library (2026-06-22).", + "notability": "", + "story": "", + "features": [], + "links": [] + }, { "stem": "Myth", "title": "Pokémon Myth", @@ -10911,6 +11019,7 @@ "library_path": "roms/gba/Hacks/Pokemon - R.O.W.E. (Hack).gba", "play_status": "Unplayed", "scrape_dir": "Pokemon_ROWE", + "engine": "pokeemerald-expansion", "type": [ "New Experience", "QoL", @@ -11070,8 +11179,9 @@ "homepage": "https://radicalred.miraheze.org/wiki/Main_Page", "source": "https://www.hackdex.app/hack/radical-red", "library_path": "roms/gba/Hacks/Pokemon - Radical Red (Hack).gba", - "play_status": "Unplayed", + "play_status": "Dropped", "scrape_dir": "Pok_mon_Radical_Red", + "engine": "CFRU + DPE", "type": [ "Difficulty", "Expansion" @@ -11358,7 +11468,7 @@ "title": "Pokémon Reborn", "platform": "PC", "base": null, - "version": "Episode 19", + "version": "19.5.0", "status": "Complete", "generation": "Gen 1–7", "developer": "Amethyst & the Reborn Team", @@ -11366,7 +11476,7 @@ "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemon_Reborn/16-1-5dc2bc1637770907.png", "homepage": "https://www.rebornevo.com/", "source": "https://www.rebornevo.com/pr/index.html/", - "library_path": "—", + "library_path": "/storage1/Emulation/roms/windows/Pokemon - Reborn (Hack).zip", "play_status": "Unplayed", "scrape_dir": "Pokemon_Reborn", "type": [ @@ -11399,12 +11509,113 @@ } ] }, + { + "stem": "Recharged Emerald Rebalanced", + "title": "Pokémon Recharged Emerald (Rebalanced)", + "platform": "GBA", + "base": "Emerald", + "version": "2.2.8", + "status": "Complete", + "generation": "Gen III", + "developer": "Jaizu", + "release_date": "2025", + "homepage": "https://ko-fi.com/s/bcfd8cef1c", + "source": "https://pokehostel.com/pokemon-recharged-emerald/", + "library_path": "roms/gba/Pokemon - Recharged Emerald Rebalanced (Hack).gba", + "play_status": "Unplayed", + "engine": "pokeemerald-expansion (likely)", + "type": [ + "Difficulty", + "QoL" + ], + "tags": [ + "hack", + "platform/gba", + "base/emerald", + "status/complete", + "type/difficulty", + "type/qol" + ], + "summary": "The **Rebalanced** edition of [[Recharged Emerald]] — the same Jaizu QoL suite and optional Nuzlocke / level-cap toggles, but with rebalanced trainer teams, movesets and level curve for a tougher, more curated baseline than the regular build. Pick this if you want Recharged Emerald's conveniences with extra bite; take the [[Recharged Emerald|regular build]] for vanilla difficulty.", + "notability": "The \"harder\" half of the Recharged Emerald pair — a single toggle-light rebalance rather than full kaizo, so it scratches the difficulty itch without leaving the Recharged comfort features behind.", + "story": "", + "features": [ + "Rebalanced trainers / level curve vs. the regular Recharged Emerald", + "Optional **Nuzlocke mode** (permadeath until the E4) + **level cap** mode", + "Following Pokémon, auto-run, instant text, day/night cycle", + "HM moves usable without teaching them; key-item wheel; 999-stack bag", + "Nature Mints, Bottle Caps, Masuda-method breeding", + "Gen III roster with modern mechanics" + ], + "links": [ + { + "label": "Info", + "url": "https://pokehostel.com/pokemon-recharged-emerald/" + }, + { + "label": "", + "url": "https://ko-fi.com/s/bcfd8cef1c" + } + ] + }, + { + "stem": "Recharged Emerald", + "title": "Pokémon Recharged Emerald", + "platform": "GBA", + "base": "Emerald", + "version": "2.2.8", + "status": "Complete", + "generation": "Gen III", + "developer": "Jaizu", + "release_date": "2025", + "homepage": "https://ko-fi.com/s/bcfd8cef1c", + "source": "https://pokehostel.com/pokemon-recharged-emerald/", + "library_path": "roms/gba/Pokemon - Recharged Emerald (Hack).gba", + "play_status": "Unplayed", + "engine": "pokeemerald-expansion (likely)", + "type": [ + "Vanilla+", + "QoL" + ], + "tags": [ + "hack", + "platform/gba", + "base/emerald", + "status/complete", + "type/vanilla+", + "type/qol", + "nuzlocke" + ], + "summary": "Pokémon Recharged Emerald is Jaizu's QoL-focused, vanilla-difficulty take on Hoenn — the Emerald entry in the same \"Recharged\" series as [[Recharged Pink]] and Recharged Yellow. It keeps the Gen III roster and the original difficulty by default, then layers on a deep quality-of-life suite and **optional** Challenge, level-cap and Nuzlocke toggles you turn on only if you want them.", + "notability": "Exactly the \"vanilla+ with a Nuzlocke switch\" niche — modern conveniences plus an in-game Nuzlocke mode (fainted mons stay fainted until you beat the Champion, then it reverts for postgame) without forcing a harder game. See [[Nuzlocke-Friendly (Vanilla+)]].", + "story": "", + "features": [ + "Optional **Nuzlocke mode** (permadeath until the E4) + **level cap** mode with bonus-EXP scaling", + "Optional **Challenge mode** — Gym Leaders / E4 get optimized IVs/EVs/movesets (off by default)", + "Following Pokémon in the overworld", + "Run by default (auto-run), instant text, day/night cycle with matching battle backgrounds", + "HM moves usable without teaching them; forgettable at any time", + "Key-item wheel (register 4 items); bag up to 999 per slot", + "Modern team-building: Nature Mints, Bottle Caps, Masuda-method breeding", + "Retains the Gen III dex with updated mechanics from later gens" + ], + "links": [ + { + "label": "Info", + "url": "https://pokehostel.com/pokemon-recharged-emerald/" + }, + { + "label": "", + "url": "https://ko-fi.com/s/bcfd8cef1c" + } + ] + }, { "stem": "Recharged Pink", "title": "Pokémon Recharged Pink", "platform": "GBA", "base": "Emerald", - "version": "removes connection features an", + "version": "1.9.2", "status": null, "generation": "Gen III", "developer": "Jaizu", @@ -11413,12 +11624,19 @@ "library_path": "/storage1/Emulation/roms/gba/Pokemon Recharged Pink v1.9.2.gba", "play_status": "Unplayed", "scrape_dir": "Pokemon_Recharged_Pink", - "type": [], + "engine": "pokeemerald-expansion (likely)", + "type": [ + "Vanilla+", + "QoL" + ], "tags": [ "hack", "platform/gba", "base/emerald", - "source/discord" + "type/vanilla+", + "type/qol", + "source/discord", + "nuzlocke" ], "summary": "Pokémon Recharged Pink is a variation of Pokemon Recharged Yellow, tailored for players who don't require compatibility with Generation 3 games. This version removes connection features and includes a cheat menu accessible through the Player's computer. For a detailed list of changes, see below.", "notability": "", @@ -11452,7 +11670,7 @@ "title": "Pokémon Recharged Yellow (previously known as Pokémon Yellow Cross)", "platform": "GBA", "base": "Emerald", - "version": null, + "version": "1.8.0", "status": null, "generation": "Gen III", "developer": "Jaizu", @@ -11462,17 +11680,19 @@ "library_path": "/storage1/Emulation/roms/gba/rchrgd yllw v1.8.0.zip", "play_status": "Unplayed", "scrape_dir": "Pok_mon_Recharged_Yellow_previously_known_as_Pok_mon_Yellow_Cross", + "engine": "pokeemerald-expansion (likely)", "type": [ - "Difficulty", + "Vanilla+", "QoL" ], "tags": [ "hack", "platform/gba", "base/emerald", - "type/difficulty", + "type/vanilla+", "type/qol", - "source/discord" + "source/discord", + "nuzlocke" ], "summary": "**Pokémon Recharged Yellow (previously known as Pokemon Yellow Cross)** is a GBA ROM Hack by Jaizu based on Pokemon Emerald. It was last updated on April 26, 2025.", "notability": "", @@ -11585,7 +11805,7 @@ "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemon_Rejuvenation/Screenshot_20240628_152348_Discord-6a5d3f6cae7802de.jpg", "homepage": "https://rejuvenation.wiki.gg/", "source": "https://www.pokeharbor.com/2024/01/pokemon-rejuvenation/", - "library_path": "—", + "library_path": "/storage1/Emulation/roms/windows/Pokemon - Rejuvenation (Hack).zip", "play_status": "Unplayed", "scrape_dir": "Pokemon_Rejuvenation", "type": [ @@ -11890,6 +12110,7 @@ "library_path": "/storage1/labdata/romhacks/library/Pokemon_Roaring_Red/", "play_status": "Unplayed", "scrape_dir": "Pokemon_Roaring_Red", + "engine": "CFRU + DPE (likely)", "type": [ "Expansion" ], @@ -15389,8 +15610,9 @@ "homepage": "https://www.pokecommunity.com/threads/pok%C3%A9mon-unbound-completed.382178/", "source": "https://www.mediafire.com/file/rq72yc9dyj9r9a5/Pokemon_Unbound_2.1.1.gba/file", "library_path": "/storage1/Emulation/roms/gba/Pokemon Unbound 2.1.1.gba", - "play_status": "Unplayed", + "play_status": "Completed", "scrape_dir": "Pokemon_Unbound", + "engine": "CFRU", "type": [ "New Experience", "Difficulty" @@ -15404,6 +15626,7 @@ "type/difficulty", "source/discord" ], + "rating": 5, "summary": "Pokémon Unbound is widely regarded as one of the most polished FireRed hacks ever made. Developed by Skeli, it's set in the original Borrius region with a complex, war-torn plot, a Gen-8-level custom battle engine, four selectable difficulty modes (Easy to Insane), a mission system, Max Raids, and an enormous pile of quality-of-life features. Generations 1–7 are available, with some Gen 8 in the post-game.", "notability": "A benchmark for modern GBA hacking — routinely tops 'best ROM hack' lists for its production values, difficulty options and post-game depth.", "story": "", @@ -16783,12 +17006,12 @@ "title": "Pokémon bushido", "platform": "PC", "base": null, - "version": null, + "version": "1.1.12", "status": null, "generation": null, "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemon_bushido/NLihHbc-924807f554fe09e6.gif", "source": "https://www.pokecommunity.com/threads/pokemon-bushido.447182/", - "library_path": "—", + "library_path": "/storage1/Emulation/roms/windows/Pokemon - bushido (Hack).zip", "play_status": "Unplayed", "scrape_dir": "Pokemon_bushido", "type": [