fix(yellow): address version:yellow issues and title pupil bake

Seed Mt Moon Super Nerd dialogue (#1743), play item-use heal jingles
(#1635), use white fades for fly/teleport warps (#1644), add a
Yellow-only Advanced palette overlay (#1639), parse Yellow Super Rod
data including Safari Dragonair (#1074), and apply title rOBP0 when
baking Pikachu eye OAM so pupils stay black with white glints.
This commit is contained in:
1jamie
2026-08-25 11:29:59 -05:00
parent bbe0f0d9ae
commit 69c7ee89b5
24 changed files with 1154 additions and 299 deletions
+42 -1
View File
@@ -77,6 +77,26 @@ GB_SHADES = (
)
def _apply_title_obp0(image):
"""Title rOBP0=%11100000 ($E0): OBJ shades 1 and 2 → white, 3 → black.
Eye OAM is baked into the MEWMON-colored BG PNG; without this remap the
shade-1 glints become body yellow under the title palette
(pokeyellow engine/movie/title.asm after PlacePikachu).
"""
pixels = image.load()
w, h = image.size
mid, dark = GB_SHADES[1][0], GB_SHADES[2][0]
for y in range(h):
for x in range(w):
r, g, b, a = pixels[x, y]
if a == 0:
continue
if abs(r - mid) <= 2 or abs(r - dark) <= 2:
pixels[x, y] = GB_SHADES[0]
return image
def _symbol(symbols, name):
try:
return symbols[name]
@@ -1880,12 +1900,33 @@ def extract_field(rom, symbols, manifest, out_dir, assets_dir):
(3, 24, 24, True), (2, 32, 24, True),
(0, 56, 16, False), (1, 64, 16, False),
(2, 56, 24, False), (3, 64, 24, False)):
eye = ob_clear[ob_index]
eye = ob_clear[ob_index].copy()
_apply_title_obp0(eye)
if flip:
eye = eye.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
pikachu.paste(eye, (px, py), eye)
_save_png(pikachu, os.path.join(assets_dir, "title/pikachu.png"))
# Blink overlays (half/closed) — same OBP remap as open eyes.
eye_layout = (
(1, 24, 16, True), (0, 32, 16, True),
(3, 24, 24, True), (2, 32, 24, True),
(0, 56, 16, False), (1, 64, 16, False),
(2, 56, 24, False), (3, 64, 24, False),
)
# Re-compose blank-face pika for overlays (open eyes already baked).
blank_face = matte_color0(compose(13, 9, pika_cells))
for suffix, base in (("eyes_half", 4), ("eyes_closed", 8)):
overlay = Image.new("RGBA", (48, 16), (255, 255, 255, 0))
overlay.paste(blank_face.crop((24, 16, 72, 32)), (0, 0))
for ob_index, px, py, flip in eye_layout:
eye = ob_clear[base + ob_index].copy()
_apply_title_obp0(eye)
if flip:
eye = eye.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
overlay.paste(eye, (px - 24, py - 16), eye)
_save_png(overlay, os.path.join(assets_dir, f"title/{suffix}.png"))
falling_star = raw_2bpp(
"FallingStar", 8, 8, "intro/falling_star.png",
transparent=True)
+37
View File
@@ -86,6 +86,43 @@ def parse_super_rod(pokered):
return out
def parse_super_rod_yellow(pokeyellow):
"""pokeyellow data/wild/super_rod.asm: inline species,level rows.
Yellow stores four (species, level) pairs per map on one `db` line
(`db MAP, SPECIES, LEVEL, SPECIES, LEVEL, ...`), unlike Red's
`dbw MAP, .Group` + `db level, species` groups. Slot order is kept
so Super Rod weighted rolls and DexNav lists stay faithful (#1074).
"""
out = {}
path = os.path.join(pokeyellow, "data/wild/super_rod.asm")
for lineno, line in read_asm(path):
s = line.strip()
if not s.startswith("db ") or s == "db -1" or s.startswith("db -1 ;"):
continue
# db MAP, SPECIES, LEVEL, SPECIES, LEVEL, SPECIES, LEVEL, SPECIES, LEVEL
parts = [p.strip() for p in s[3:].split(",")]
if len(parts) < 3 or not re.match(r"^[A-Z][A-Z0-9_]*$", parts[0]):
continue
map_id = parts[0]
slots = []
rest = parts[1:]
i = 0
while i + 1 < len(rest):
species, level = rest[i], rest[i + 1]
if not re.match(r"^[A-Z][A-Z0-9_]*$", species):
break
try:
level_n = int(level)
except ValueError:
break
slots.append({"level": level_n, "species": species})
i += 2
if slots:
out[map_id] = slots
return out
def parse_trades(pokered):
"""data/events/trades.asm: npctrade give, get, dialogset, nickname."""
# TRADE_DIALOGSET_* order (constants/script_constants.asm) indexes
+1
View File
@@ -453,6 +453,7 @@ def derive(red, pokeyellow, symbols_path):
print(f"warning: parse_credits failed ({exc}); keeping Red credits")
# TODO: hand-author a Yellow credits banner if pret layout drifts.
yellow["field"]["trades"] = field.parse_trades(pokeyellow)
yellow["field"]["superRod"] = field.parse_super_rod_yellow(pokeyellow)
finally:
util.ASM_DEFINES = saved
+306 -250
View File
@@ -8360,94 +8360,74 @@
"superRod": {
"CELADON_CITY": [
{
"level": 23,
"species": "POLIWHIRL"
"level": 5,
"species": "GOLDEEN"
},
{
"level": 10,
"species": "GOLDEEN"
},
{
"level": 15,
"species": "SLOWPOKE"
"species": "GOLDEEN"
},
{
"level": 20,
"species": "GOLDEEN"
}
],
"CERULEAN_CAVE_1F": [
{
"level": 23,
"species": "SLOWBRO"
"level": 25,
"species": "GOLDEEN"
},
{
"level": 23,
"level": 35,
"species": "SEAKING"
},
{
"level": 23,
"species": "KINGLER"
},
{
"level": 23,
"species": "SEADRA"
}
],
"CERULEAN_CAVE_2F": [
{
"level": 23,
"species": "SLOWBRO"
},
{
"level": 23,
"level": 45,
"species": "SEAKING"
},
{
"level": 23,
"species": "KINGLER"
},
{
"level": 23,
"species": "SEADRA"
"level": 55,
"species": "SEAKING"
}
],
"CERULEAN_CAVE_B1F": [
{
"level": 23,
"species": "SLOWBRO"
"level": 30,
"species": "GOLDEEN"
},
{
"level": 23,
"level": 40,
"species": "SEAKING"
},
{
"level": 23,
"species": "KINGLER"
"level": 50,
"species": "SEAKING"
},
{
"level": 23,
"species": "SEADRA"
"level": 60,
"species": "SEAKING"
}
],
"CERULEAN_CITY": [
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"level": 25,
"species": "GOLDEEN"
},
{
"level": 15,
"species": "KRABBY"
}
],
"CERULEAN_GYM": [
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"level": 30,
"species": "GOLDEEN"
},
{
"level": 15,
"species": "KRABBY"
"level": 30,
"species": "SEAKING"
},
{
"level": 40,
"species": "SEAKING"
}
],
"CINNABAR_ISLAND": [
@@ -8457,99 +8437,123 @@
},
{
"level": 15,
"species": "HORSEA"
"species": "TENTACOOL"
},
{
"level": 15,
"species": "SHELLDER"
"level": 10,
"species": "STARYU"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 30,
"species": "TENTACOOL"
}
],
"FUCHSIA_CITY": [
{
"level": 23,
"species": "SEAKING"
"level": 5,
"species": "MAGIKARP"
},
{
"level": 10,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "GYARADOS"
}
],
"PALLET_TOWN": [
{
"level": 10,
"species": "STARYU"
},
{
"level": 10,
"species": "TENTACOOL"
},
{
"level": 5,
"species": "STARYU"
},
{
"level": 20,
"species": "TENTACOOL"
}
],
"ROUTE_10": [
{
"level": 15,
"species": "KRABBY"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 20,
"species": "KRABBY"
},
{
"level": 15,
"species": "MAGIKARP"
}
],
"PALLET_TOWN": [
{
"level": 15,
"species": "TENTACOOL"
"level": 10,
"species": "HORSEA"
},
{
"level": 15,
"species": "POLIWAG"
}
],
"ROUTE_10": [
{
"level": 23,
"species": "POLIWHIRL"
},
{
"level": 15,
"species": "SLOWPOKE"
"level": 25,
"species": "KINGLER"
}
],
"ROUTE_11": [
{
"level": 15,
"species": "KRABBY"
"species": "TENTACOOL"
},
{
"level": 15,
"species": "SHELLDER"
"level": 20,
"species": "TENTACOOL"
},
{
"level": 10,
"species": "TENTACOOL"
},
{
"level": 5,
"species": "HORSEA"
}
],
"ROUTE_12": [
{
"level": 5,
"species": "TENTACOOL"
"level": 20,
"species": "HORSEA"
},
{
"level": 15,
"species": "KRABBY"
"level": 25,
"species": "HORSEA"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 25,
"species": "SEADRA"
},
{
"level": 15,
"species": "MAGIKARP"
"level": 35,
"species": "SEADRA"
}
],
"ROUTE_13": [
{
"level": 5,
"level": 15,
"species": "HORSEA"
},
{
"level": 20,
"species": "HORSEA"
},
{
"level": 10,
"species": "TENTACOOL"
},
{
"level": 15,
"species": "KRABBY"
},
{
"level": 15,
"species": "GOLDEEN"
},
{
"level": 15,
"species": "MAGIKARP"
"level": 20,
"species": "SEADRA"
}
],
"ROUTE_17": [
@@ -8559,304 +8563,356 @@
},
{
"level": 15,
"species": "KRABBY"
"species": "TENTACOOL"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 25,
"species": "SHELLDER"
},
{
"level": 15,
"species": "MAGIKARP"
"level": 35,
"species": "SHELLDER"
}
],
"ROUTE_18": [
{
"level": 5,
"level": 15,
"species": "TENTACOOL"
},
{
"level": 15,
"species": "KRABBY"
"level": 20,
"species": "SHELLDER"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 30,
"species": "SHELLDER"
},
{
"level": 15,
"species": "MAGIKARP"
"level": 40,
"species": "SHELLDER"
}
],
"ROUTE_19": [
{
"level": 15,
"species": "TENTACOOL"
},
{
"level": 20,
"species": "STARYU"
},
{
"level": 15,
"species": "HORSEA"
"level": 30,
"species": "TENTACOOL"
},
{
"level": 15,
"species": "SHELLDER"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 30,
"species": "TENTACRUEL"
}
],
"ROUTE_20": [
{
"level": 15,
"level": 20,
"species": "TENTACOOL"
},
{
"level": 20,
"species": "TENTACRUEL"
},
{
"level": 30,
"species": "STARYU"
},
{
"level": 15,
"species": "HORSEA"
},
{
"level": 15,
"species": "SHELLDER"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 40,
"species": "TENTACRUEL"
}
],
"ROUTE_21": [
{
"level": 15,
"species": "TENTACOOL"
},
{
"level": 20,
"species": "STARYU"
},
{
"level": 15,
"species": "HORSEA"
"level": 30,
"species": "TENTACOOL"
},
{
"level": 15,
"species": "SHELLDER"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 30,
"species": "TENTACRUEL"
}
],
"ROUTE_22": [
{
"level": 15,
"species": "GOLDEEN"
"level": 5,
"species": "POLIWAG"
},
{
"level": 10,
"species": "POLIWAG"
},
{
"level": 15,
"species": "POLIWAG"
},
{
"level": 15,
"species": "POLIWHIRL"
}
],
"ROUTE_23": [
{
"level": 23,
"species": "SLOWBRO"
"level": 25,
"species": "POLIWAG"
},
{
"level": 23,
"species": "SEAKING"
"level": 30,
"species": "POLIWAG"
},
{
"level": 23,
"species": "KINGLER"
"level": 30,
"species": "POLIWHIRL"
},
{
"level": 23,
"species": "SEADRA"
"level": 40,
"species": "POLIWHIRL"
}
],
"ROUTE_24": [
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"level": 20,
"species": "GOLDEEN"
},
{
"level": 15,
"species": "KRABBY"
"level": 25,
"species": "GOLDEEN"
},
{
"level": 30,
"species": "GOLDEEN"
},
{
"level": 30,
"species": "SEAKING"
}
],
"ROUTE_25": [
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 10,
"species": "KRABBY"
},
{
"level": 15,
"species": "KRABBY"
},
{
"level": 15,
"species": "KINGLER"
},
{
"level": 25,
"species": "KINGLER"
}
],
"ROUTE_4": [
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"level": 20,
"species": "GOLDEEN"
},
{
"level": 15,
"species": "KRABBY"
"level": 25,
"species": "GOLDEEN"
},
{
"level": 30,
"species": "GOLDEEN"
},
{
"level": 30,
"species": "SEAKING"
}
],
"ROUTE_6": [
{
"level": 15,
"species": "KRABBY"
"level": 5,
"species": "GOLDEEN"
},
{
"level": 10,
"species": "GOLDEEN"
},
{
"level": 15,
"species": "SHELLDER"
"species": "GOLDEEN"
},
{
"level": 20,
"species": "GOLDEEN"
}
],
"SAFARI_ZONE_CENTER": [
{
"level": 15,
"level": 5,
"species": "MAGIKARP"
},
{
"level": 10,
"species": "MAGIKARP"
},
{
"level": 10,
"species": "DRATINI"
},
{
"level": 15,
"species": "KRABBY"
},
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"species": "SLOWPOKE"
"species": "DRAGONAIR"
}
],
"SAFARI_ZONE_EAST": [
{
"level": 5,
"species": "MAGIKARP"
},
{
"level": 10,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "DRATINI"
},
{
"level": 15,
"species": "KRABBY"
},
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"species": "SLOWPOKE"
}
],
"SAFARI_ZONE_NORTH": [
{
"level": 5,
"species": "MAGIKARP"
},
{
"level": 10,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "DRATINI"
},
{
"level": 15,
"species": "KRABBY"
},
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"species": "SLOWPOKE"
}
],
"SAFARI_ZONE_WEST": [
{
"level": 5,
"species": "MAGIKARP"
},
{
"level": 10,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "MAGIKARP"
},
{
"level": 15,
"species": "DRATINI"
},
{
"level": 15,
"species": "KRABBY"
},
{
"level": 15,
"species": "PSYDUCK"
},
{
"level": 15,
"species": "SLOWPOKE"
}
],
"SEAFOAM_ISLANDS_B3F": [
{
"level": 15,
"level": 25,
"species": "KRABBY"
},
{
"level": 20,
"species": "STARYU"
},
{
"level": 15,
"species": "HORSEA"
"level": 35,
"species": "KINGLER"
},
{
"level": 15,
"species": "SHELLDER"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 40,
"species": "STARYU"
}
],
"SEAFOAM_ISLANDS_B4F": [
{
"level": 15,
"level": 25,
"species": "KRABBY"
},
{
"level": 20,
"species": "STARYU"
},
{
"level": 15,
"species": "HORSEA"
"level": 35,
"species": "KINGLER"
},
{
"level": 15,
"species": "SHELLDER"
},
{
"level": 15,
"species": "GOLDEEN"
"level": 40,
"species": "STARYU"
}
],
"VERMILION_CITY": [
{
"level": 15,
"species": "KRABBY"
"species": "TENTACOOL"
},
{
"level": 15,
"species": "SHELLDER"
"level": 20,
"species": "TENTACOOL"
},
{
"level": 10,
"species": "TENTACOOL"
},
{
"level": 5,
"species": "HORSEA"
}
],
"VERMILION_DOCK": [
{
"level": 15,
"species": "KRABBY"
"level": 10,
"species": "TENTACOOL"
},
{
"level": 15,
"species": "SHELLDER"
}
],
"VIRIDIAN_CITY": [
{
"level": 15,
"species": "TENTACOOL"
},
{
"level": 15,
"species": "STARYU"
},
{
"level": 10,
"species": "SHELLDER"
}
],
"VIRIDIAN_CITY": [
{
"level": 5,
"species": "POLIWAG"
},
{
"level": 10,
"species": "POLIWAG"
},
{
"level": 15,
"species": "POLIWAG"
},
{
"level": 10,
"species": "POLIWAG"
}
]