mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-23 14:07:34 +02:00
Give Gen 2 the ROM text table Gen 1 has had all along
Gold and Silver had no label-keyed string table at all. The manifests carried no text section, RomExtractorGen2 had no extractText, and game.data.text was never assigned, so every call through src/core/RomText.lua fell back to the literal written beside it. The only Gen 2 text the cache held was the script text in data/generated/text.lua, keyed by bank:address for the overworld VM, which nothing can look a battle line up in. make_gold_manifest.py now walks data/text/'s five dialogue files for their labels, the way make_rom_manifest.text_metadata walks pokered's, and embeds each one's symbol. 889 labels, all of them resolving in both editions. make_silver_manifest.py inherits the list unchanged and re-resolves the addresses from pokesilver.sym. RomExtractorGen2:extractText decodes them into data/generated/rom_text.lua. The mechanism is the one extractOakSpeech already used for _OakText1-7: resolve the label, decode from the cart, key by name. What is new is that the list comes from the manifest rather than being written out in Lua, so all of data/text/ arrives instead of seven strings. decodeGen2Text also emits the three runtime name slots it used to drop. PlaceMoveUsersName, PlaceMoveTargetsName and PlaceEnemysName (home/text.asm) substitute a battler's name as the line prints, so <USER>, <TARGET> and <ENEMY> are markers, not glyphs. Skipped as control glyphs, SubTookDamageText decoded as "The SUBSTITUTE / took damage for" with nothing after it. Game2:load assigns the table to self.data.text, which is what makes the existing shared RomText helper work on Gold and Silver at all. The new cache file is listed in the Gold override rather than bumping CACHE_FORMAT, so caches built before this stage re-import themselves and Red, Blue and Yellow are left alone.
This commit is contained in:
@@ -907,9 +907,62 @@ REQUIRED_SYMBOLS = {
|
||||
}
|
||||
|
||||
|
||||
def embedded_symbols(symbols, pokemon_labels, song_labels=()):
|
||||
"""Resolve REQUIRED_SYMBOLS + pic labels + Music_* song headers."""
|
||||
names = set(REQUIRED_SYMBOLS) | set(pokemon_labels) | set(song_labels)
|
||||
# The engine's own text, the counterpart to make_rom_manifest.text_metadata.
|
||||
#
|
||||
# Only these five carry dialogue. data/text/'s other files are character
|
||||
# tables rather than strings: dakutens.asm and name_input_chars.asm /
|
||||
# mail_input_chars.asm are keyboard layouts, and unused_gen1_trainer_names.asm
|
||||
# is a dead Gen 1 leftover. Decoding those as text yields keyboard rows and
|
||||
# kana runs, so they are left out by name rather than filtered afterwards.
|
||||
#
|
||||
# None of the five carries an IF DEF(_GOLD) / IF DEF(_SILVER) arm, so the
|
||||
# label set is one list for both editions and make_silver_manifest.py inherits
|
||||
# it with the addresses re-resolved from pokesilver.sym.
|
||||
TEXT_SOURCES = (
|
||||
"battle.asm",
|
||||
"common_1.asm",
|
||||
"common_2.asm",
|
||||
"common_3.asm",
|
||||
"std_text.asm",
|
||||
)
|
||||
|
||||
|
||||
def text_labels(pokegold):
|
||||
"""Every text label in TEXT_SOURCES, in sorted order.
|
||||
|
||||
Unlike Gen 1 there is no `dynamic` map beside this. pokered's decoder is
|
||||
told which runtime token each label carries; RomExtractorGen2's reads the
|
||||
cart's own TX_RAM / TX_DECIMAL command bytes and emits {STRBUF} / {NUM}
|
||||
itself, so the label alone is enough.
|
||||
"""
|
||||
labels = set()
|
||||
for name in TEXT_SOURCES:
|
||||
path = os.path.join(pokegold, "data/text", name)
|
||||
pending = None
|
||||
for _, line in read_asm(path):
|
||||
stripped = line.strip()
|
||||
if not stripped:
|
||||
continue
|
||||
match = re.match(r"(\w+)::?\s*$", stripped)
|
||||
if match:
|
||||
# A label whose next line is another label owns no string of
|
||||
# its own. `BattleText::` is the one in this set: its own
|
||||
# comment says "used only for BANK(BattleText)", and it shares
|
||||
# an address with the first real label under it, so taking it
|
||||
# would decode that neighbour's string a second time.
|
||||
pending = match.group(1)
|
||||
continue
|
||||
if pending:
|
||||
labels.add(pending)
|
||||
pending = None
|
||||
return sorted(labels)
|
||||
|
||||
|
||||
def embedded_symbols(symbols, pokemon_labels, song_labels=(),
|
||||
text_label_names=()):
|
||||
"""Resolve REQUIRED_SYMBOLS + pic labels + songs + text labels."""
|
||||
names = (set(REQUIRED_SYMBOLS) | set(pokemon_labels)
|
||||
| set(song_labels) | set(text_label_names))
|
||||
for symbol_name in symbols.by_name:
|
||||
# Pokedex entries are split across four banks and the game derives the
|
||||
# bank arithmetically from the species id (radio.asm's rlca/maskbits
|
||||
@@ -1111,6 +1164,7 @@ def generate(pokegold, symbols_path):
|
||||
pokemon_labels.append(asset["backLabel"])
|
||||
|
||||
songs = music_order(pokegold)
|
||||
text_label_names = text_labels(pokegold)
|
||||
sfx = sfx_order(pokegold)
|
||||
|
||||
# Index 0 is NO_ITEM, so the parsed list is already 1-based on item id.
|
||||
@@ -1202,6 +1256,9 @@ def generate(pokegold, symbols_path):
|
||||
"battleAnimBgPaletteOrder": battle_anim_bg_pals,
|
||||
"battleAnimObPaletteOrder": battle_anim_ob_pals,
|
||||
},
|
||||
# Label -> decoded string is built at import time from these, the
|
||||
# same way Gen 1 builds data/generated/text.lua from its own list.
|
||||
"text": {"labels": text_label_names},
|
||||
"charmap": charmap(pokegold),
|
||||
"fontCharmap": font_extract.parse_charmap(pokegold),
|
||||
"pokemonAssets": assets,
|
||||
@@ -1210,7 +1267,8 @@ def generate(pokegold, symbols_path):
|
||||
"maps": {name: map_groups[name] for name in map_order},
|
||||
"tilesets": {name: {} for name in tilesets},
|
||||
}
|
||||
data["symbols"] = embedded_symbols(symbols, pokemon_labels, songs)
|
||||
data["symbols"] = embedded_symbols(
|
||||
symbols, pokemon_labels, songs, text_label_names)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user