symbols: the six WRAM names the engagement rewards read
wSpriteIndex, wWalkCounter, wMapSpriteExtraData, wToggleableObjectFlags, wToggleableObjectList and wObtainedHiddenItemsFlags, resolved by tools/resolve_wram.py from ram/wram.asm at the pinned commit and bracketed by addresses symbols.rs already carries. Two of the brackets needed the tool to count NUM_STATS and NUM_CITY_MAPS, which the decomp defines as const_value over an enumeration; both are now counted up to the line that defines them.
This commit is contained in:
parent
7784a9d172
commit
ed0080ab2c
3 changed files with 63 additions and 4 deletions
|
|
@ -28,9 +28,11 @@ pub mod ram {
|
|||
pub const wJoyIgnore: u16 = 0xcd6b; // 52587
|
||||
pub const wNumMovesMinusOne: u16 = 0xcd6c; // 52588
|
||||
pub const wBattleResult: u16 = 0xcf0b; // 53003
|
||||
pub const wSpriteIndex: u16 = 0xcf13; // 53011
|
||||
pub const wItemList: u16 = 0xcf7b; // 53115
|
||||
pub const wListMenuID: u16 = 0xcf94; // 53140
|
||||
pub const wFontLoaded: u16 = 0xcfc4; // 53188
|
||||
pub const wWalkCounter: u16 = 0xcfc5; // 53189
|
||||
pub const wEnemyMonSpecies: u16 = 0xcfe5; // 53221
|
||||
pub const wEnemyMonHP: u16 = 0xcfe6; // 53222
|
||||
pub const wEnemyMonLevel: u16 = 0xcff3; // 53235
|
||||
|
|
@ -71,11 +73,15 @@ pub mod ram {
|
|||
pub const wSignCoords: u16 = 0xd4b1; // 54449
|
||||
pub const wSignTextIDs: u16 = 0xd4d1; // 54481
|
||||
pub const wNumSprites: u16 = 0xd4e1; // 54497
|
||||
pub const wMapSpriteExtraData: u16 = 0xd504; // 54532
|
||||
pub const wTilesetBank: u16 = 0xd52b; // 54571
|
||||
pub const wTilesetBlocksPtr: u16 = 0xd52c; // 54572
|
||||
pub const wTilesetCollisionPtr: u16 = 0xd530; // 54576
|
||||
pub const wTilesetTalkingOverTiles: u16 = 0xd532; // 54578
|
||||
pub const wNumHoFTeams: u16 = 0xd5a2; // 54690
|
||||
pub const wToggleableObjectFlags: u16 = 0xd5a6; // 54694
|
||||
pub const wToggleableObjectList: u16 = 0xd5ce; // 54734
|
||||
pub const wObtainedHiddenItemsFlags: u16 = 0xd6f0; // 55024
|
||||
pub const wStatusFlags5: u16 = 0xd730; // 55088
|
||||
pub const wStatusFlags6: u16 = 0xd732; // 55090
|
||||
pub const wStatusFlags7: u16 = 0xd733; // 55091
|
||||
|
|
|
|||
|
|
@ -209,6 +209,22 @@ EXTRA_RAM = (
|
|||
# services/flysim/tools/resolve_wram.py is the second reading of it, from ram/wram.asm at
|
||||
# this commit, bracketed by wFontLoaded and wForcePlayerToChooseMon.
|
||||
'wCapturedMonSpecies',
|
||||
# The engagement rewards (`docs/rewards-learning.md`, the operator 2026-09-23).
|
||||
# `talk`: DisplayTextID copies its argument -- the sprite slot, or a sign's text id --
|
||||
# into wSpriteIndex before it looks the text up, and the overworld's A press only
|
||||
# reaches it while wWalkCounter is zero. `item`: an item ball is a sprite whose
|
||||
# wMapSpriteExtraData entry is (item id, 0) -- LoadMapHeader writes that shape for
|
||||
# an ITEM-flagged object_event and no other -- found in the map's
|
||||
# wToggleableObjectList; PickUpItem hides it by setting its global bit in
|
||||
# wToggleableObjectFlags, and FoundHiddenItemText sets the hidden item's bit in
|
||||
# wObtainedHiddenItemsFlags, each only after GiveItem succeeded.
|
||||
# services/flysim/tools/resolve_wram.py is the second reading of all six.
|
||||
'wSpriteIndex',
|
||||
'wWalkCounter',
|
||||
'wMapSpriteExtraData',
|
||||
'wToggleableObjectFlags',
|
||||
'wToggleableObjectList',
|
||||
'wObtainedHiddenItemsFlags',
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,22 @@ WANTED = {
|
|||
# this one caught", and the only signal that needs no second rule to tell a
|
||||
# catch apart from a gift, a trade or an evolution.
|
||||
'wCapturedMonSpecies': 'the species a ball just caught, 0 for none',
|
||||
# The engagement rewards (`docs/rewards-learning.md`, the operator 2026-09-23).
|
||||
# DisplayTextID stores its argument here -- a sprite slot, or a sign's text id --
|
||||
# before it looks the text up, so it names what a conversation is with.
|
||||
'wSpriteIndex': "DisplayTextID's argument, a sprite slot or a text id",
|
||||
# Non-zero for the frames of a step; the overworld only reads an A press at zero.
|
||||
'wWalkCounter': 'frames left in the step the player is taking',
|
||||
# Two bytes per sprite slot: (item id, 0) for an ITEM-flagged object_event,
|
||||
# (trainer class, trainer number) for a TRAINER one, zeroes otherwise.
|
||||
'wMapSpriteExtraData': 'per sprite slot: item id, or trainer class and number',
|
||||
# One bit per global toggleable object; PickUpItem's HideObject sets an item
|
||||
# ball's bit once GiveItem has succeeded.
|
||||
'wToggleableObjectFlags': 'global hidden bits of every toggleable object',
|
||||
# The current map's (sprite slot, global toggleable index) pairs, $ff-terminated.
|
||||
'wToggleableObjectList': "this map's toggleable sprites and their global indices",
|
||||
# One bit per hidden item, set by FoundHiddenItemText once GiveItem succeeded.
|
||||
'wObtainedHiddenItemsFlags': 'hidden items already found',
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -76,9 +92,33 @@ WANTED = {
|
|||
COUNTED = {
|
||||
'NUM_HMS': ('constants/item_constants.asm', r'^\s*add_hm\s+\w+'),
|
||||
'NUM_TMS': ('constants/item_constants.asm', r'^\s*add_tm\s+\w+'),
|
||||
# The engagement rewards need two more, for the same reason: each is an
|
||||
# `EQU const_value` over an enumeration, and each is the size of a declaration
|
||||
# the cursor has to cross. `ds NUM_STATS` sits between wFontLoaded and
|
||||
# wTrainerClass, the bracket of wWalkCounter; `flag_array NUM_CITY_MAPS` sits
|
||||
# between wNumHoFTeams and wStatusFlags5, the bracket of the toggleable-object
|
||||
# and hidden-item flags. Both are counted only up to the line that defines
|
||||
# them, which is where `const_value` is read.
|
||||
'NUM_STATS': (
|
||||
'constants/battle_constants.asm', r'^\s*const\s+STAT_\w+', r'^DEF NUM_STATS\b'
|
||||
),
|
||||
'NUM_CITY_MAPS': (
|
||||
'constants/map_constants.asm', r'^\s*map_const\s+\w+', r'^DEF NUM_CITY_MAPS\b'
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def count_in(root: Path, path: str, pattern: str, stop: str | None = None) -> int:
|
||||
"""Lines of `path` matching `pattern`, up to the first line matching `stop`."""
|
||||
text = (root / path).read_text()
|
||||
if stop is not None:
|
||||
match = re.search(stop, text, re.M)
|
||||
if match is None:
|
||||
raise SystemExit(f'{path}: no line matches {stop}')
|
||||
text = text[: match.start()]
|
||||
return len(re.findall(pattern, text, re.M))
|
||||
|
||||
|
||||
def pinned(text: str) -> dict[str, int]:
|
||||
"""Every address `symbols.rs` carries today, by symbol name."""
|
||||
return {
|
||||
|
|
@ -95,10 +135,7 @@ def constants(root: Path) -> dict[str, int]:
|
|||
BLOCK_WIDTH`). A name whose expression never becomes evaluable is simply left
|
||||
out, which kills the cursor at any declaration that uses it.
|
||||
"""
|
||||
counted = {
|
||||
name: len(re.findall(pattern, (root / path).read_text(), re.M))
|
||||
for name, (path, pattern) in COUNTED.items()
|
||||
}
|
||||
counted = {name: count_in(root, *spec) for name, spec in COUNTED.items()}
|
||||
pending: dict[str, str] = {}
|
||||
sources = sorted((root / 'constants').glob('*.asm')) + sorted(
|
||||
(root / 'constants').glob('*.inc')
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue