Files
gen1recomp/docs/game3/location-previews.md
Shane McGovern 38a7e03f13 Show retail location previews for every FireRed map section
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>
2026-09-19 14:21:30 +01:00

5.1 KiB
Raw Permalink Blame History

Location Previews

Entering a FireRed map section that owns a preview now shows the retail full-screen artwork and location-name window during the warp transition, and the Town Map GUIDE panel shows the retail artwork and flavour text instead of the hand-authored placeholders. Before this, only a handful of sections had art, and none of it came from the ROM.

What the ROM provides

src/import/gba/map_preview_extract.lua reads two tables straight from the user's dump and bakes them into the cache:

Table Source Contents
sMapPreviewScreenData src/map_preview_screen.c 28 entries: mapsec, type, flagId, tilesptr, tilemapptr, palptr
sMapsecName_* src/region_map.c 109 display names for mapsec 88..196
sDungeonInfo src/region_map.c 19 dungeon GUIDE entries: name + pre-wrapped flavour text

src/import/gba/region_map_tables.lua locates sMapPreviewScreenData by validating the pinned offset from versions.lua and only then falling back to a bounded ±0x8000 scan. Validation is structural, not a magic byte match: every one of the 28 entries must have a mapsec in range, a type of 0 or 1, three in-range ROM pointers, and satisfy the shipped invariant that the palette block is physically the first 0x40 bytes of the tile block.

Artwork is deduplicated by its tiles:tilemap:palette key, so 28 entries bake 21 images. Pattern Bush and the six Tanoby chambers reuse another section's art, exactly as the retail table does. Each image is 240×160 RGBA at 4bpp using palette banks 13 and 14.

src/import/gba/bg_bake.lua holds the shared 4bpp BG baking helpers (bgr555ToRgb8, decodeTile4bpp, loadPalBanks, bakeBgRgba); the Berry Pouch extractor was refactored onto them.

Cache files

<root>/map_preview/manifest.lua        entries, by_mapsec index, name-window colours
<root>/map_preview/<mapsec>.rgba       240x160 RGBA artwork, deduplicated
<root>/region_map/names.lua            mapsec 88..196 display names
<root>/region_map/dungeon_info.lua     sDungeonInfo name + flavour text

versions.lua CACHE_VERSION is bumped when any of these change shape.

Two ROM quirks the importer tolerates

  • MPS_ROCKET_WAREHOUSE (mapsec 178) and Berry Forest (mapsec 176) share flagId = 2231, so the first one the player visits marks both as seen. The six Tanoby chambers likewise share one flag. This is retail behaviour.
  • The Tanoby chamber mapsec is spelled MAPSEC_DILFORD_CHAMBER (not DILFORD) in the name table.

Runtime behaviour

src/ui/game3/map_preview_screen.lua ports Task_RunMapPreviewScreenForest. Only MPS_TYPE_FOREST sections (8 of them) take over the screen; the other 20 are MPS_TYPE_CAVE and only change the warp fade colour. The artwork and the name window are composited into one canvas so they fade out together, matching the retail BG0/BLDALPHA blend.

  • Hold: 120 frames on a first visit, 40 on a revisit. Caves key off their own world-map flag; forests key off the transient sHasVisitedMapBefore global that ScrCmd_setworldmapflag refreshes (MapPreviewScreen.setVisitedFlag captures the pre-visit state).
  • Fade-out: 48 frames.

Wiring:

  • src/core/game3/map.lua — a changed section with a forest preview wins over the map-name popup (mirrors overworld.c state 12). Suppressed for seamless warps.
  • src/core/game3/gfx.lua — a running preview suppresses MapNamePopup.
  • src/core/game3/warp.lua — warpFadeModes applies WarpFadeOutScreen/WarpFadeInScreen: a section change into a cave-preview map forces FADE_TO_BLACK, otherwise MapTransitionIsEnter/IsExit decide white-vs-black using MAP_TYPE_UNDERGROUND.
  • src/core/game3/scripting/ops_a.lua — setworldmapflag feeds the visit flag.
  • src/ui/game3/hud.lua — ticks and dismisses the screen on menu open.
  • src/core/game3/dataset.lua — installs the cache during hydrate.
  • src/ui/game3/region_map.lua — GUIDE panel geometry, tint ramp and delayed text now follow the retail timings; ROM names and dungeon text overlay the hand-authored map_sections_extract.SECTIONS / region_map_extract fallbacks via ensureGenerated().

Verification

Run from the project root:

luajit tests/game3_map_preview_extract_test.lua
luajit tests/game3_town_map_test.lua
luajit tests/run_engine.lua
luacheck src -q --codes --only 0 1 511

tests/game3_map_preview_extract_test.lua covers the pinned offsets, the BGR555→RGB8 conversion, the manifest/screen logic against a synthetic cache (so it runs without a ROM), and — when a FireRed dump is present at the repo root — the full extraction: 28 entries, 8 forest / 20 cave, 21 deduplicated 240×160×4 artworks, 109 verified mapsec names, 19 dungeon entries, the shared 2231 flag, and Pattern Bush reusing Viridian Forest's artwork.

The tests/game3_* suites are run manually; they are not wired into a CI workflow. Extraction was additionally checked against a real FireRed 1.0 dump (all 28 entries and 109 names decode, sMapsecName_* pointers match sRegionMapSectionIdToName). Timing was reasoned against pret source; no in-game visual capture has been performed.