docs: macros.md 12.22, macros-wram.md section 12
This commit is contained in:
parent
2b1a6c0dea
commit
04657d3324
2 changed files with 98 additions and 0 deletions
|
|
@ -893,3 +893,41 @@ point of reading the figure; a border drawn somewhere the cursor is not parked i
|
|||
box; and a menu of more than two options is not this menu. What the pad makes of a readable prompt
|
||||
is `pokemon_red::macros::palette`'s business (`docs/design/macros.md` 12.12 and 12.20), not this
|
||||
accessor's.
|
||||
|
||||
## 12. The people off the screen, and a battle decided (2026-09-23, `docs/design/macros.md` 12.22)
|
||||
|
||||
Two readings row 58 added, both out of bytes the seam already had or a byte bracketed by two it had.
|
||||
|
||||
### `state::offscreen_npcs`
|
||||
|
||||
`CheckSpriteAvailability` (`engine/overworld/movement.asm`) writes `$ff` into
|
||||
`SPRITESTATEDATA1_IMAGEINDEX` (offset 2) for a sprite that is a toggleable object switched off, that
|
||||
is outside its window, or that stands on a text box's tiles. The window, for a sprite whose
|
||||
`SPRITESTATEDATA2_MOVEMENTBYTE1` (offset 6) is `WALK` (`$fe`) or `STAY` (`$ff`), compares the
|
||||
sprite's biased `MAPY` / `MAPX` (offsets 4 and 5) with `wYCoord` / `wXCoord`: drawn when equal, or
|
||||
when the sprite's is greater by at most `SCREEN_HEIGHT / 2 - 1` (8) rows and
|
||||
`SCREEN_WIDTH / 2 - 1` (9) columns. A scripted mover (movement byte below `WALK`) skips the test.
|
||||
|
||||
So a `$ff` sprite of the loaded map whose coordinates fall **outside** the window, and whose
|
||||
movement byte is `WALK` or above, is reported with those coordinates: the cartridge would hide it
|
||||
for being off the screen whatever else were true, and a sprite it is not updating does not move.
|
||||
Everything else `$ff` is not reported. Measured from the row-58 checkpoint at the Pewter Gym's
|
||||
doormat: BROCK at (4, 1) and the Jr. Trainer at (3, 6) reported, the guide at (7, 10) drawn.
|
||||
|
||||
What it cannot tell is a toggleable object switched off from one out of sight, because both are
|
||||
`$ff` outside the window. Its one reader is the rung's own list of people; the ladder's person
|
||||
places are Oak's lab and the gyms, and only the lab and Viridian Gym carry toggleable people
|
||||
(`data/maps/toggleable_objects.asm`).
|
||||
|
||||
### `poke::CUR_OPPONENT`, `wCurOpponent`
|
||||
|
||||
Written when a battle is decided (`home/trainers.asm` for a trainer, the encounter check for a wild
|
||||
one), cleared by `EndOfBattle` in the same block that clears `wIsInBattle`. Not in the generated
|
||||
table: `ram/wram.asm` at the pinned commit declares `wIsInBattle:: db`,
|
||||
`wPartyGainExpFlags:: flag_array PARTY_LENGTH` (one byte), `wCurOpponent:: db`,
|
||||
`wBattleType:: db`, `wDamageMultipliers:: db`, `wGymLeaderNo:: db`, `wTrainerNo:: db`, and the
|
||||
table's `wIsInBattle` (`$d057`), `wBattleType` (`$d05a`) and `wTrainerNo` (`$d05d`) are exactly
|
||||
where that layout puts them, so the byte is `wBattleType - 1` = `$d059`, asserted against both
|
||||
neighbours in `scene/tests.rs`. Measured on the cartridge in the Pewter Gym: `$00` in the
|
||||
overworld, `$cd` (`OPP_JR_TRAINER_M`) from the last box of the trainer's challenge through the
|
||||
219-frame transition and the battle. `controllable` reads it as zero.
|
||||
|
|
|
|||
|
|
@ -1445,6 +1445,66 @@ Nothing presses for the fly and nothing is ranked: one button leaves a pad it co
|
|||
one wall moves to the tile that earned it, and one walk goes where it can. The decoder, the reward catalog, the adapter
|
||||
version, the roles and the compatibility string are untouched.
|
||||
|
||||
### 12.22 The rung's people are in the room when the screen does not show them (2026-09-23, row 58)
|
||||
|
||||
Live on v0.5.3, rank 10, for twenty-five minutes: `GO OBJECTIVE` into the Pewter Gym, `GO OUT`
|
||||
straight back out, with `GO ITEM`, `GO FRONTIER`, `YES` and `NO` mixed in. Per ten brain minutes
|
||||
about 93 `GO OUT`, 47 `GO OBJECTIVE`, 200 starts in all, every one `done`, **no reward event of any
|
||||
kind**, the exploration count frozen at 1,892. Check 10 saw ten distinct names and said nothing.
|
||||
Surveyed from the live checkpoint with the route probe (`FLY_PROBE_CATCH=route`,
|
||||
`FLY_PROBE_CATCH_MAP=54`), which reads the room on the fly's Nth arrival.
|
||||
|
||||
- **The objective saw the room through the screen.** `objective_targets` read `npcs`, which is
|
||||
what the cartridge *draws*, and `CheckSpriteAvailability` writes `$ff` into the image index of
|
||||
every sprite outside a window of the player's coordinate. From the doormat at (4, 13) that window
|
||||
holds the guide at (7, 10) and nobody else: BROCK at (4, 1) and the Jr. Trainer at (3, 6) are not
|
||||
drawn. With the guide talked to (12.20), the rung's list was empty, so `GO OBJECTIVE` had nothing
|
||||
to aim at inside and 12.5's rule -- the ways out are withheld while the rung's person is in the
|
||||
room -- let `GO OUT` onto the pad. Outside, `GO OBJECTIVE` aimed at the gym's door. The pair
|
||||
undoes itself in about a second, and nothing on either side of the door earns anything.
|
||||
- **So the rung reads the people the cartridge hides only for being off the screen.** The window
|
||||
is a function of `wYCoord`, `wXCoord` and the sprite's own biased coordinates, all already read,
|
||||
so a sprite whose `$ff` falls outside it is one the cartridge would hide for that reason whatever
|
||||
else were true, and a sprite the cartridge is not updating does not move
|
||||
(`state::offscreen_npcs`). A `$ff` *inside* the window, or on a scripted mover, is not the
|
||||
screen's and is not reported. Only the rung reads the list: a sprite outside the window may also
|
||||
be a toggleable object switched off, which reads the same, so `GO NPC`, `TALK` and objects keep
|
||||
what is drawn.
|
||||
- **Facing any of the rung's people is the arrival.** 12.5 left out only the one ahead, which was
|
||||
enough for one target; a gym names three, and in front of BROCK `GO OBJECTIVE` still had the
|
||||
trainer to walk to. A fly facing a person the rung is waiting on has nothing left for a walk to
|
||||
do, and `TALK` is the press.
|
||||
|
||||
Three frames the seam read as the fly's own were the cartridge's, and each wrote a ledger entry that
|
||||
emptied the room again once the first fix let the fly into it:
|
||||
|
||||
- **A warp's tear.** `wCurMap` changes thirty-two frames before the header, the coordinates and the
|
||||
warp table follow it, while the screen fades, and no joypad bit is set until the fade is over.
|
||||
The seam read "map 54 at (16, 17)" -- Pewter City's doormat under the gym's id -- as an overworld
|
||||
and dealt it a pad; a walk started there planned over the wrong map, and what it aimed at went
|
||||
into the blocked ledger under the gym's id (live: `GO OUT` started and finished in 0.05 s). The
|
||||
driver now reads a tear as the map byte having changed while the fly still stands on a warp of
|
||||
the loaded table that leads to the map the byte names, deals it as `Unknown` with an empty pad,
|
||||
and records no ground from it. Teleport pads -- Saffron Gym, two Silph Co. floors -- do not change
|
||||
the map byte, so they are never a tear; a tear is bounded at ninety frames all the same.
|
||||
- **A battle's transition.** Between a trainer's challenge closing and the battle screen there are
|
||||
219 frames with every joypad and script bit clear. The pad was dealt, a walk toward BROCK pressed
|
||||
into the animation and gave up after three refused steps -- BROCK blocked for ten brain minutes --
|
||||
and the Jr. Trainer's conversation read as over, so the trainer the fly then lost to was
|
||||
"talked to" for the session. `wCurOpponent` is set when a battle is decided and cleared by
|
||||
`EndOfBattle` with `wIsInBattle`; it is not in the generated table and is derived as the byte
|
||||
between two that are, both neighbours checked in a test (`macros-wram.md` section 12), and
|
||||
`controllable` reads it.
|
||||
- **A trainer walking up.** 12.4 reads a macro the cartridge ended by taking the joypad as a
|
||||
refusal and wrote the target blocked and the tile pushed at once. A trainer who sees the fly
|
||||
takes the joypad the same way. The entries now wait until the cartridge gives the joypad back:
|
||||
in the overworld it was a refusal and is written as before; a battle teaches the ledgers nothing.
|
||||
|
||||
Nothing is ranked, nothing presses for the fly, and no button is added to any pad: `GO OBJECTIVE`
|
||||
has a person to walk to where it had none, `GO OUT` is withheld by 12.5's own rule, and three
|
||||
frames that were never the fly's deal nothing. The decoder, the reward catalog, the adapter
|
||||
version, the roles and the compatibility string are untouched.
|
||||
|
||||
## 13. Shops and Pokémon Centers (the operator, 2026-09-17: "refactor the shop macros. make it a
|
||||
## priority to visit the shop at least once per area; make shop macros item purchases. same
|
||||
## for the Pokécenter. heal should be a macro.")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue