Second batch of the Gen 3 review work: the review lanes closed their queues
and the test gate grew with them.
Review census: 139 routed findings -- 118 fixed, 14 invalid (the report had
Gen 4+ semantics in more than one place), 6 struck as stale after
re-verification, 1 re-routed. Every fix carries its own pret citation in
docs/game3/review-v3-triage.md; the E10 opcode closure is itemised in
docs/game3/e10-opcode-spec.md (18 ops wired, 2 reclassified to the seam class).
Representative ROM-grounded changes:
- The POKéMON start-menu entry is now gated on FLAG_SYS_POKEMON_GET the way
retail does it (pokefirered/src/start_menu.c:217-218, flag 0x828).
- Money ops read their amount raw and gate the change on the disable byte
(pokefirered/src/scrcmd.c:1798-1830, pokefirered/asm/macros/event.inc:1166-1186);
random and the warp family VarGet theirs
(pokefirered/src/scrcmd.c:455-461, :719-731).
- The HM table matches FRLG: there is no Whirlpool HM
(pokefirered/include/constants/items.h:411-418).
- The day-care party-full guard follows src/daycare.c:525, :1081.
- Knock Off keeps its battle-scoped send-out mask
(pokefirered/src/battle_script_commands.c:2730-2752, :4489), carried from
the first batch.
Structural work: the I6/I9/J1 architecture items landed as seams (profile
selector, capability flags, font provider, virtual-object layer), the adopted
footprint register keeps a KEEP verdict, the quantizer target is met, and the
30 drain items plus carves 1-4 are folded in.
Tests: T6 now runs 282 top-level suites (273 + 9 new), the re-sweep ends at
267 pass / 0 fail, the engine tier is 634 suites, modkit 37, and the full
gate ran green twice with T3 active on an imported Red cache. Documented
skips are the lua5.4 oversize-save oracle where lua5.4 is absent and the
config-partials listed in docs/game3/game3-artifact-conversions-v3.md.
Docs shipped: review-v3-triage.md, e10-opcode-spec.md, rse-seams.md,
game3-suite-sweep-v113.md, game3-artifact-conversions-v3.md,
test-baseline-v3.md (plus the first-batch docs already on the branch).
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.
- Save Editor: Implement full Gen 3 FireRed save editing including PID/personality, IVs/EVs, natures, ability slots, gender, shiny toggles, held items, Pokédex flags, and event/trainer toggles.
- Scripting & Specials: Add Pokédex rating evaluations, Magikarp/Heracross size records, Trainer Fan Club tracking, and FireRed event flag mappings.
- Overworld & Rendering: Interleave metatile and actor draw calls by row bucket with OAM elevation priority sorting for bridges and overhead layers.
- ROM Extractor: Parallelize Gen 3 extraction across 4 concurrent love.thread workers with love.filesystem searchers for cross-platform support (Switch/Xbox/Mobile/Desktop).
- LZ77 Decompressor: Accelerate GBA LZ77 with preallocated FFI buffers and 0-based displacement indexing ensuring 100% byte-for-byte asset parity.
- Testing: Add unit test suites for LZ77, size records, Pokédex rating, Fan Club, elevation priority, Seafoam puzzles, and Gen 3 save editor operations.
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>
- Implement pure ROM extraction for Trainer Card backgrounds and badges
- Connect TrainerCardExtract to RomExtractorGen3 and CacheContract
- Update TrainerCard, FrlgFont, Chrome, PcChrome, PokedexChrome, and SummaryChrome to route exclusively through CacheFs
- Remove all legacy fallback paths to src/import/gba/chrome and hardcoded pret directories
- Add standalone procedural fallbacks for field effects and Pokecenter heal
- 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