Files
gen1recomp/tests/drivers/game3_import2_fresh_cache.lua
thibautbus aaacf02dc0 Draw a FireRed egg's menu icon as an egg
The party, the PC boxes and the release animation drew an egg with the icon
of the species it will hatch into, so a Pichu egg showed as a Pichu. pret's
party menu picks the icon from GetMonData(MON_DATA_SPECIES_OR_EGG), which is
SPECIES_EGG for any egg (pokefirered/src/pokemon.c:3245, party_menu.c:2655).

Pokemon.speciesOrEgg does the same, and the icon call sites use it. The
species pass only extracted icons up to NUM_SPECIES - 1, so the egg extractor
now also bakes gMonIconTable[SPECIES_EGG] as pokemon/icons/412.rgba. Cache
version 114 re-imports existing caches so the icon appears.
2026-09-22 12:10:44 +02:00

170 lines
6.1 KiB
Lua

local U = require("tests.drivers.util")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_import2_fresh_cache"
local PALLET = "FR_PALLET_TOWN"
local BEDROOM = "FR_PLAYERS_HOUSE_2F"
local HOUSE_1F = "FR_PLAYERS_HOUSE_1F"
local failures = 0
local function result(ok, label)
print((ok and "PASS " or "FAIL ") .. label)
if not ok then failures = failures + 1 end
return ok
end
local function finish()
if failures == 0 then
print("PASS import2_fresh_cache")
love.event.quit(0)
else
print("FAIL import2_fresh_cache failures=" .. failures)
love.event.quit(1)
end
end
local ROUND2_SAMPLE = {
"data/generated/gba/slot_machine/reel_icons.rgba",
"data/generated/gba/slot_machine/bg.rgba",
"data/generated/gba/trade/gba_screen.rgba",
"data/generated/gba/trade/ball.rgba",
"data/generated/gba/union_room/chat_bg.rgba",
"data/generated/gba/wireless_status/bg.rgba",
"data/generated/gba/fame_checker/bg.rgba",
"data/generated/gba/fame_checker/0.rgba",
"data/generated/gba/teachy_tv/screen.rgba",
"data/generated/gba/mystery_gift/card_bg0.rgba",
"data/generated/gba/trainer_tower.lua",
"data/generated/gba/trainer_tower/records_bg.rgba",
"data/generated/gba/pokemon/tutor.lua",
"data/generated/gba/museum/kabutops.rgba",
"data/generated/gba/museum/aerodactyl.rgba",
"data/generated/gba/region_map/dungeon_icon_visited.rgba",
"data/generated/gba/move_relearner/bg.rgba",
"data/generated/gba/pokemon/egg/hatch.rgba",
"data/generated/gba/pokemon/front/412.rgba",
"data/generated/gba/pokemon/icons/412.rgba",
"data/generated/gba/native/layouts/alt_366.mid",
}
return function(game)
print("PASS driver_started")
for _ = 1, 900 do
if game.phase == "boot" and game.boot then break end
U.wait(1)
end
local Versions = require("src.import.gba.versions")
local CacheContract = require("src.import.CacheContract")
local CacheFs = require("src.import.CacheFs")
local Dataset = require("src.core.game3.dataset")
local meta = CacheFs.readActive("data/generated/gba/meta.json")
if not result(type(meta) == "string", "the mounted cache has a meta.json") then
return finish()
end
local stampedCache = tonumber(meta:match('"cache_version"%s*:%s*(%d+)'))
local stampedNative = tonumber(meta:match('"native_version"%s*:%s*(%d+)'))
print("[driver] meta cache_version=" .. tostring(stampedCache)
.. " native_version=" .. tostring(stampedNative)
.. " importer=" .. tostring(Versions.CACHE_VERSION) .. "/"
.. tostring(Versions.NATIVE_VERSION))
result(stampedCache == Versions.CACHE_VERSION,
"the booted cache is stamped at the importer's cache version")
result(stampedNative == Versions.NATIVE_VERSION,
"the booted cache is stamped at the importer's native version")
result(CacheContract.cacheVersionCurrent("firered") == true,
"the engine's own staleness gate accepts this cache")
local complete, missing = CacheContract.allRequiredFilesExist("firered")
result(complete == true,
"zero missing required keys, first missing: " .. tostring(missing))
result(CacheContract.isReady("firered") == true, "the firered cache reports ready")
local cache = Dataset.cache()
local absent = {}
for _, rel in ipairs(ROUND2_SAMPLE) do
local bytes = cache:read(rel)
if type(bytes) ~= "string" or #bytes == 0 then absent[#absent + 1] = rel end
end
result(#absent == 0, "all " .. #ROUND2_SAMPLE
.. " sampled round 2 assets read back from the booted cache, absent: "
.. (absent[1] or "none"))
game:_handleBootAction({ action = "new_game", name = "RED" })
U.wait(240)
local Runtime = require("src.core.game3.runtime")
local Space = require("src.core.game3.scripting.space")
local Player = require("src.core.game3.player")
local session = Runtime.getSession()
if not result(session ~= nil, "new game reached the game3 field") then
U.shot(game, DIR .. "/import2_fresh_cache_00_stuck.png")
return finish()
end
for _ = 1, 600 do
if Space.mapId then break end
U.wait(1)
end
print("[driver] map=" .. tostring(Space.mapId) .. " at ("
.. tostring(Player.cellX) .. "," .. tostring(Player.cellY) .. ")")
result(Space.mapId == BEDROOM,
"a new game starts in the player's bedroom, map=" .. tostring(Space.mapId))
result(U.shot(game, DIR .. "/import2_fresh_cache_01_bedroom.png"),
"the bedroom screenshot reached disk")
local function stepOnce(dir)
local x0, y0, m0 = Player.cellX, Player.cellY, Space.mapId
U.hold(game, dir, 20)
U.wait(10)
return Player.cellX ~= x0 or Player.cellY ~= y0 or Space.mapId ~= m0
end
local function walkTo(targetX, targetY, budget)
local from = Space.mapId
for _ = 1, (budget or 40) do
if Space.mapId ~= from then return true end
if Player.cellX == targetX and Player.cellY == targetY then return true end
local dir
if Player.cellX < targetX then dir = "right"
elseif Player.cellX > targetX then dir = "left"
elseif Player.cellY < targetY then dir = "down"
else dir = "up" end
stepOnce(dir)
end
return Space.mapId ~= from
end
local function waitMap(target, frames)
for _ = 1, (frames or 240) do
if Space.mapId == target then break end
U.wait(1)
end
U.wait(30)
end
-- pokefirered/src/field_control_avatar.c:924
walkTo(10, 2, 30)
if Space.mapId ~= HOUSE_1F then stepOnce("left") end
waitMap(HOUSE_1F, 240)
print("[driver] down the stairs: map=" .. tostring(Space.mapId) .. " at ("
.. tostring(Player.cellX) .. "," .. tostring(Player.cellY) .. ")")
result(Space.mapId == HOUSE_1F,
"the stairs warp reached the ground floor, map=" .. tostring(Space.mapId))
walkTo(10, 8, 20)
walkTo(4, 8, 40)
if Space.mapId == HOUSE_1F then stepOnce("down") end
waitMap(PALLET, 300)
U.wait(60)
print("[driver] out the front door: map=" .. tostring(Space.mapId) .. " at ("
.. tostring(Player.cellX) .. "," .. tostring(Player.cellY) .. ")")
result(Space.mapId == PALLET,
"the player walked out into Pallet Town, map=" .. tostring(Space.mapId))
result(U.shot(game, DIR .. "/import2_fresh_cache_02_pallet_town.png"),
"the Pallet Town screenshot reached disk")
finish()
end