mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 20:50:21 +02:00
ec9dc29646
Silver: derived import manifest (tools/make_silver_manifest.py re-resolves the Gold manifest's symbols from pokesilver.sym), silver GameVersion row, generation-keyed extractor routing, required-files override, edition save stamping (a Silver playthrough no longer writes into the Gold save), checkver-driven edition data, SILVER/KAMON/OSCAR/MAX presets, GOLD rival default, edition credits banner, Lugia title screen (OAM layouts, bob, trail, palettes as title.lua data keys with Gold defaults so old caches need no re-import), packaging for every build target, docs, and tests. Launcher: the installed-mods list is one continuous scroll (rows culled to the viewport) instead of a pager with an inner scroll viewport; the pad cursor's edge-scroll no longer runs it to the bottom. The game dropdown shows just the initial and caret. Find-tab behavior unchanged. Title tempo: a sprite-anim frame shows duration+1 ticks (engine/sprite_anims/core.asm GetSpriteAnimFrame), which locks both editions' 64-tick wing beat to the 64-tick sine bob; the title screens no longer run fast and out of phase.
95 lines
3.6 KiB
Python
95 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Derive the Pokemon Silver import manifest from the shipped Gold manifest.
|
|
|
|
Gold and Silver are assembled from one pokegold source tree; every constant
|
|
block, charmap entry, map id, and symbol NAME is identical between the two
|
|
builds, and the edition differences (wild encounter tables, the alternate
|
|
front pics in gfx/pics_silver.asm, the title screen art, preset player
|
|
names, a handful of map texts) are all ROM data that the importer decodes
|
|
from the Silver cart at import time. So rather than re-parsing pokegold
|
|
from scratch like tools/make_gold_manifest.py does, this takes the shipped
|
|
Gold manifest verbatim and overrides only what genuinely differs:
|
|
|
|
* romSha1 -- Silver's ROM hash (pret/pokegold's byte-exact build).
|
|
* symbols -- every symbol re-resolved from pokesilver.sym, because the
|
|
edition-selected data blocks have different sizes and shift
|
|
their neighbours (e.g. the compressed front pics).
|
|
|
|
Usage: python3 tools/make_silver_manifest.py
|
|
Default paths: Gold manifest beside this script; symbols at
|
|
/Users/bryanbassett/Documents/development/pokegold-symbols/pokesilver.sym
|
|
(a pokegold checkout's own `make silver` build emits an identical one).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import copy
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from rom_data import CANONICAL_SILVER_SHA1, SymbolTable # noqa: E402
|
|
|
|
DEV = "/Users/bryanbassett/Documents/development"
|
|
DEFAULT_GOLD = os.path.join(os.path.dirname(__file__), "rom_manifest_gold.json")
|
|
DEFAULT_OUT = os.path.join(
|
|
os.path.dirname(__file__), "rom_manifest_silver.json")
|
|
DEFAULT_SYMBOLS = os.path.join(DEV, "pokegold-symbols/pokesilver.sym")
|
|
|
|
|
|
def derive(gold, symbols_path):
|
|
"""Return the Silver manifest derived from the Gold manifest dict."""
|
|
silver = copy.deepcopy(gold)
|
|
silver["romSha1"] = CANONICAL_SILVER_SHA1
|
|
|
|
silver_symbols = SymbolTable(symbols_path)
|
|
resolved, missing = {}, []
|
|
for name in gold["symbols"]:
|
|
symbol = silver_symbols.by_name.get(name)
|
|
if symbol is None:
|
|
missing.append(name)
|
|
continue
|
|
resolved[name] = [symbol.bank, symbol.address]
|
|
if missing:
|
|
raise SystemExit(
|
|
"pokesilver.sym is missing symbols the manifest needs: "
|
|
+ ", ".join(sorted(missing)[:10])
|
|
+ (" ..." if len(missing) > 10 else ""))
|
|
silver["symbols"] = resolved
|
|
|
|
# Sanity: the edition pic banks must actually have moved something. If
|
|
# every address matches Gold's, the --symbols file is almost certainly
|
|
# pokegold.sym, and the import would decode Gold data out of a Silver ROM.
|
|
if all(resolved[n] == gold["symbols"][n] for n in resolved):
|
|
raise SystemExit(
|
|
f"{symbols_path} resolves every symbol to Gold's address; "
|
|
"is it really pokesilver.sym?")
|
|
|
|
return silver
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--gold", default=DEFAULT_GOLD,
|
|
help="shipped Gold manifest to derive from")
|
|
parser.add_argument("--symbols", default=DEFAULT_SYMBOLS,
|
|
help="pokesilver.sym symbol file")
|
|
parser.add_argument("--out", default=DEFAULT_OUT)
|
|
args = parser.parse_args()
|
|
|
|
with open(args.gold, encoding="utf-8") as f:
|
|
gold = json.load(f)
|
|
|
|
silver = derive(gold, os.path.abspath(args.symbols))
|
|
with open(args.out, "w", encoding="utf-8", newline="\n") as f:
|
|
json.dump(silver, f, ensure_ascii=False, indent=2, sort_keys=True)
|
|
f.write("\n")
|
|
print(f"wrote {args.out}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|