The rest of the Gen 3 review fixes, each with a gated suite in tests/engine/.
ROM semantics were checked against pret/pokefirered.
Scripts
- givemon carried the wrong operand layout, found earlier; four more layout
desyncs came out of pret asm/macros/event.inc: comparestat is {byte,word},
and setptr / loadbytefromptr / setptrbyte each carry a leading byte plus a
word. A wrong size mis-decodes every instruction after the bad one, so
Versions.CACHE_VERSION moves to 113 and existing caches re-import.
- handlers for previously handler-less verbs: comparestat,
bufferitemnameplural, setmonmove, setmonmetlocation, the modern
fateful-encounter pair, the script-locals family (copylocal, setptr,
loadbytefromptr, setptrbyte, copybyte, compare_local_to_* and
compare_ptr_to_*), the RAM-script family (setvaddress, vgoto, vcall,
vgoto_if, vcall_if, vmessage, vbuffermessage, vbufferstring, endram,
returnram) and the same-map forms of the *at verbs.
- setdooropen / setdoorclosed read their coordinates through VarGet.
Battles
- Knock Off and Thief / Trick persist the item change instead of only
touching the in-battle copy.
- knocked-off party slots are tracked in a bitmask, so a slot reused later
does not inherit the flag.
Field and UI
- Player.reset restores facing and clears the surf flags.
- a definition-less Map.load no longer leaves collision unbound.
- an unresolved region-map section no longer reports PALLET TOWN.
- the naming screen splits input from the timer, so update(dt) stops
indexing a number.
- the hall of fame commits through the engine save path and serializes its
fields.
Persistence
- gameStats, the link-battle records and the trainer card are serialized.
- the PC deposit refuses at the 999 cap instead of destroying the overflow.
Robustness
- Data.load runs cached modules sandboxed.
- the file browser quotes shell arguments.
- .meta dimensions are bounds-checked and mids.idx validates its header.
Most map sections never showed a Location Preview because the preview
artwork and the region-map GUIDE text were hand-authored placeholders:
only a handful of sections had art and none of it came from the ROM.
Read the real tables out of the dump instead.
Extraction (new):
- src/import/gba/region_map_tables.lua locates and validates
sMapPreviewScreenData. The pinned offset from versions.lua is tried
first and a bounded +/-0x8000 scan is only a guard. Validation is
structural (mapsec in 88..196, type 0/1, three in-range ROM pointers,
and the shipped invariant that the palette block is the first 0x40
bytes of the tile block) so all 28 entries must hold.
- src/import/gba/map_preview_extract.lua bakes 21 deduplicated 240x160
RGBA artworks (28 entries reuse art: Pattern Bush and the six Tanoby
chambers), 109 mapsec names verified against sRegionMapSectionIdToName,
and the 19 sDungeonInfo entries. Palette banks 13/14; bank-0 tilemap
refs only occur in off-screen padding columns.
- src/import/gba/bg_bake.lua holds the shared 4bpp BG baking helpers;
berry_pouch_extract.lua is refactored onto them (-94 lines).
Runtime:
- src/ui/game3/map_preview_screen.lua ports
Task_RunMapPreviewScreenForest: 120-frame first-visit hold, 40-frame
revisit, 48-frame fade-out, artwork and name window composited into one
canvas so they fade together. Only MPS_TYPE_FOREST (8 sections) takes
over the screen; the 20 MPS_TYPE_CAVE sections only change the warp
fade colour, matching pret.
- src/core/game3/map.lua gives a changed section with a forest preview
precedence over the map name popup (overworld.c state 12).
- src/core/game3/warp.lua routes every fade through warpFadeModes,
applying WarpFadeOutScreen/WarpFadeInScreen: a section change into a
cave-preview map forces FADE_TO_BLACK, otherwise MapTransitionIsEnter/
IsExit decide white vs black on MAP_TYPE_UNDERGROUND.
- setworldmapflag feeds the transient visit flag; the HUD ticks and
dismisses the screen; the dataset installs the cache on hydrate.
- region_map.lua's GUIDE panel uses the retail geometry, tint ramp and
delayed text, and ROM names/dungeon text overlay the hand-authored
fallbacks via ensureGenerated().
Two retail quirks are tolerated: MPS_ROCKET_WAREHOUSE and Berry Forest
share flagId 2231 (as do the six Tanoby chambers), and the Tanoby mapsec
is spelled MAPSEC_DILFORD_CHAMBER.
CACHE_VERSION 99 -> 100.
Verified: tests/game3_map_preview_extract_test.lua (new; ROM-gated, all
28 entries, 8 forest / 20 cave, 21 artworks, 109 names, 19 dungeons, the
shared flag, Pattern Bush art reuse), tests/game3_town_map_test.lua,
tests/run_engine.lua 587/587, scripts/test.sh --quick all tiers,
luacheck src 0 warnings / 0 errors.
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