Second wave of fixes from the Gen 3 codebase review (210 findings), the
regressions the full-suite sweep surfaced, and a T6 tier so the top-level
tests/game3_*.lua suites run inside ./scripts/test.sh instead of outside it.
Battle: Knock Off and Thief/Trick item persistence follow the ROM, not the
review - the party slot is never written through during battle, and the
knocked-off mask suppresses the item on later send-outs
(pokefirered/src/battle_script_commands.c:2731 MOVE_EFFECT_KNOCK_OFF with the
STICKY_HOLD guard at :2732, opponent-steal guard at :2610-2622, mask use at
:4489). Rapid Spin keeps its one-per-use chain order (:8435-8474); Growl
keeps pret's target (src/data/battle_moves.h, include/battle.h:63).
Scripting: operand layouts match pret/asm/macros/event.inc - givemon 15 bytes
(:989-997), comparestat {B,W} (:1573-1576), setptr/loadbytefromptr/setptrbyte
take a word pointer (:118-137). 18 of the 20 E10 ops are wired per
src/scrcmd.c (per-op citations in docs/game3/e10-opcode-spec.md), money and
random and the warp family read their operands as VarGets
(src/scrcmd.c:1798-1830, :455-461, :719-731), and the day-care party-full
guard is in place (src/daycare.c:525,:1081).
Field and UI: fishing counts rounds as the ROM does
(src/field_player_avatar.c:1740-1765), an unresolved map section no longer
reports Pallet Town (src/region_map.c:3782), and a font provider sits behind
a FireRed capability/profile seam.
Save data: profile-driven Options.block, a save version round-trip, and slot
id validation that blocks path traversal (slotDiskPath("firered", "../evil")
returns nil).
Importer: the parallel import path now writes both completion markers,
object kind/clone bytes decode as pret defines them
(include/global.fieldmap.h:110-130), and the HM table drops Whirlpool
(include/constants/items.h:411-418).
Tests: six new scenario suites (battle_ai, capture, event, menu, move,
overworld) and eight engine suites (profile, capabilities, cache paths, font
provider, options block, save version round-trip, version dispatch,
versions_game). T6 runs every top-level game3 suite at GAME3_JOBS default 8
with per-suite logs, failure cause classification and a KNOWN_GAME3_FAILURES
ceiling of 23 as a shrinking guard.
Docs: the working notes under docs/game3 (triage ledger, pret citation audit,
e10 opcode spec, RSE seams, sweep v3/v113, test baseline, artifact
conversions, merge trial).
Full gate at this snapshot: exit 0, all tiers passed - engine 624/624,
T6 279/279 (0 known, 0 fresh failures), gen2 146/146, modkit 37/37, luacheck
clean, privacy gate 3/3 over a 9,711-file publication set.
- Hidden Items & Itemfinder (fixes#2314):
* Extract BG_EVENT_HIDDEN_ITEM (kind 7) from GBA ROM with proper flag calculation (0x3E8 + id), underfoot flags, and quantities.
* Implement overworld Itemfinder scan logic (7-tile radius, directional response, underfoot detection, SFX 65, and OEM text).
* Wire up Bag Menu Itemfinder dispatch to overworld field runtime.
- Opponent Battle HUD Caught Marker (fixes#2313):
* Add authentic Pokédex caught Poké Ball icon (B_INTERFACE_GFX_BALL_CAUGHT / tile 70) to opponent healthbox.
* Match pokefirered parity in TryAddPokeballIconToHealthbox (wild encounters only, non-tutorial, non-ghost, checked against Dex).
* Ensure status ailment icons (PSN, PAR, SLP, FRZ, BRN) take rendering priority over the caught ball marker.
- Level-Up Learnset & Movepool Assignment (fixes#2315):
* Fix wild and generated Pokémon moveset assignment to assign the 4 most recent level-up moves up to the current level instead of getting stuck on basic moves (e.g. Tackle).
- Easy Chat / Profile Quick Chat:
* Extract full word groups, categories, and dictionary entries from ROM.
* Build Easy Chat interface with group selection, paginated word lists, and alphabetized filtering.
* Fix dialog text overflowing when exiting profile / quick chat prompts.
- Nurse Joy & PC Storage / Map Polishing:
* Implement Nurse Joy healing tray animation flow and audio cues in standard scripts.
* Fix PC storage box header/wallpaper rendering and storage data extraction.
* Correct Sevii Islands / Island 1 map section lookups and region map coordinate handling.
* Fix circular dependency in battle residual handlers (partialTrap).
fixes#2325fixes#2322fixes#2315fixes#2314fixes#2313
The location header drew `session.mapName or session.map`, and nothing in
src/ ever assigns session.mapName, so the fallback always won and the
screen printed the engine's internal id ("FR_ROUTE_22").
pret prints the sMapNames place name resolved from the map header:
start_menu.c PrintSaveStats -> SAVE_STAT_LOCATION
save_menu_util.c GetMapNameGeneric(dest, gMapHeader.regionMapSectionId)
region_map.c GetMapName(dst, mapsec, 0)
and centres it in the 14-tile stats window. Do the same via the existing
MapSectionsExtract.getInfo() lookup, and centre the run instead of
drawing it at a fixed x.
getInfo() also gets two fixes on the path the save screen now depends on:
- the fuzzy id match picked whichever section pairs() happened to visit
first, so "ROUTE_22" could resolve to "ROUTE 2". Prefer the exact match,
else the longest.
- return `resolved` so callers can tell a real section from the Pallet
Town placeholder the function falls back to for unknown maps.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Align CacheContract firered overrides with pure ROM extraction
- Fix door animation extraction tile sizes, palettes, and strides
- Update storage chrome, pokedex, summary, and battle chrome extractors
- Ensure 100% self-contained ROM extraction without external dependencies