Files
gen1recomp/tests/game3_import2_cache_version_test.lua
T
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

219 lines
8.6 KiB
Lua

#!/usr/bin/env luajit
package.path = "./?.lua;./?/init.lua;" .. package.path
local failed = 0
local function check(cond, msg)
if cond then
print("[ok] " .. msg)
else
failed = failed + 1
print("[FAIL] " .. msg)
end
end
local Versions = require("src.import.gba.versions")
local CacheContract = require("src.import.CacheContract")
print("[test] 1. the importer advertises a whole cache version")
local V = Versions.CACHE_VERSION
check(type(V) == "number" and V == math.floor(V) and V > 0,
"Versions.CACHE_VERSION is a positive integer, got " .. tostring(V))
print("[test] 2. cacheVersionCurrent rejects the previous cache version")
local function metaFs(version)
return {
prefix = nil,
read = function(path)
if path == "data/generated/gba/meta.json" then
return string.format('{"cache_version":%d,"native_version":%d}',
version, Versions.NATIVE_VERSION)
end
return nil
end,
exists = function() return true end,
}
end
check(CacheContract.cacheVersionCurrent("firered", metaFs(V)) == true,
"a meta.json at the importer's own version is current")
check(CacheContract.cacheVersionCurrent("firered", metaFs(V - 1)) == false,
"a meta.json one version behind is rejected as stale")
check(CacheContract.cacheVersionCurrent("firered", metaFs(V + 1)) == false,
"a meta.json from a newer importer is rejected too")
local noMeta = { prefix = nil, read = function() return nil end, exists = function() return true end }
check(CacheContract.cacheVersionCurrent("firered", noMeta) == false,
"a cache with no meta.json is rejected")
check(CacheContract.cacheVersionCurrent("firered", metaFs(V * 10)) == false,
"a meta.json whose version merely starts with this one is rejected, got " .. tostring(V * 10))
print("[test] 3. the stitch round's new keys are in the firered required list")
local required = CacheContract.requiredFilesFor("firered")
local have = {}
for _, path in ipairs(required) do have[path] = true end
local NEW_KEYS = {
-- src/region_map.c:425
"data/generated/gba/region_map/fly_icon.rgba",
"data/generated/gba/region_map/fly_icon.png",
-- src/heal_location.c:62, src/region_map.c:4023
"data/generated/gba/region_map/heal_locations.lua",
"data/generated/gba/region_map/fly_destinations.lua",
-- src/scrcmd.c:711
"data/generated/gba/native/layouts/alt_264.mid",
"data/generated/gba/native/layouts/alt_278.mid",
"data/generated/gba/native/layouts/alt_279.mid",
"data/generated/gba/native/layouts/alt_319.mid",
-- src/data/field_effects/field_effect_objects.h:99,565,1203
"data/generated/gba/field_effects/ripple.rgba",
"data/generated/gba/field_effects/splash.rgba",
"data/generated/gba/field_effects/hot_springs_water.rgba",
"data/generated/gba/field_effects/fly_bird.rgba",
"data/generated/gba/field_effects/rock_smash.rgba",
}
for _, path in ipairs(NEW_KEYS) do
check(have[path] == true, "required: " .. path)
end
print("[test] 4. every key this round's importer writes is in the firered required list")
local ROUND2_KEYS = {
-- src/slot_machine.c:399, :739
"data/generated/gba/slot_machine/manifest.lua",
"data/generated/gba/slot_machine/reel_icons.rgba",
"data/generated/gba/slot_machine/clefairy.rgba",
"data/generated/gba/slot_machine/digits.rgba",
"data/generated/gba/slot_machine/bg.rgba",
"data/generated/gba/slot_machine/payout_lights.rgba",
"data/generated/gba/slot_machine/match_lines.rgba",
"data/generated/gba/slot_machine/button_pressed.rgba",
"data/generated/gba/slot_machine/combos_window.rgba",
-- src/trade_scene.c:151
"data/generated/gba/trade/manifest.lua",
"data/generated/gba/trade/gba_screen.rgba",
"data/generated/gba/trade/gba_screen_wireless.rgba",
"data/generated/gba/trade/gba_screen_flash.rgba",
"data/generated/gba/trade/cable_closeup.rgba",
"data/generated/gba/trade/cable_end.rgba",
"data/generated/gba/trade/link_mon_glow.rgba",
"data/generated/gba/trade/link_mon_shadow.rgba",
"data/generated/gba/trade/ball.rgba",
"data/generated/gba/trade/ball_spin.rgba",
-- src/link_rfu_3.c:34, src/union_room_chat_objects.c:30
"data/generated/gba/union_room/manifest.lua",
"data/generated/gba/union_room/wireless_icon.rgba",
"data/generated/gba/union_room/chat_bg.rgba",
"data/generated/gba/union_room/chat_panel.rgba",
"data/generated/gba/union_room/chat_icons.rgba",
"data/generated/gba/union_room/chat_selector_cursor.rgba",
-- src/wireless_communication_status_screen.c:50
"data/generated/gba/wireless_status/manifest.lua",
"data/generated/gba/wireless_status/bg.rgba",
"data/generated/gba/wireless_status/palettes.pal",
-- src/fame_checker.c:119, src/graphics.c:1230
"data/generated/gba/fame_checker/manifest.lua",
"data/generated/gba/fame_checker/bg.rgba",
"data/generated/gba/fame_checker/0.rgba",
"data/generated/gba/fame_checker/1.rgba",
"data/generated/gba/fame_checker/13.rgba",
"data/generated/gba/fame_checker/14.rgba",
"data/generated/gba/fame_checker/cursor.rgba",
"data/generated/gba/fame_checker/question_mark.rgba",
"data/generated/gba/fame_checker/silhouette.pal",
"data/generated/gba/fame_checker/pack.lua",
-- src/graphics.c:1117, src/teachy_tv.c:526, :637, :1218
"data/generated/gba/teachy_tv/manifest.lua",
"data/generated/gba/teachy_tv/screen.rgba",
"data/generated/gba/teachy_tv/title.rgba",
"data/generated/gba/teachy_tv/end.rgba",
"data/generated/gba/teachy_tv/static.rgba",
"data/generated/gba/teachy_tv/bg3.rgba",
-- src/mystery_gift_show_card.c:150, src/mystery_gift_show_news.c:99
"data/generated/gba/mystery_gift/manifest.lua",
"data/generated/gba/mystery_gift/card_bg0.rgba",
"data/generated/gba/mystery_gift/card_bg7.rgba",
"data/generated/gba/mystery_gift/news_bg0.rgba",
"data/generated/gba/mystery_gift/news_bg7.rgba",
-- src/trainer_tower_sets.c:8956, src/battle_records.c:563
"data/generated/gba/trainer_tower.lua",
"data/generated/gba/trainer_tower/manifest.lua",
"data/generated/gba/trainer_tower/records_bg.rgba",
-- src/data/pokemon/tutor_learnsets.h:22
"data/generated/gba/pokemon/tutor.lua",
-- src/trainer_tower.c:554, include/constants/layouts.h:355, :363
"data/generated/gba/native/layouts/alt_366.mid",
"data/generated/gba/native/layouts/alt_373.mid",
"data/generated/gba/native/layouts/alt_374.mid",
"data/generated/gba/native/layouts/alt_381.mid",
-- src/script_menu.c:1161
"data/generated/gba/museum/manifest.lua",
"data/generated/gba/museum/kabutops.rgba",
"data/generated/gba/museum/aerodactyl.rgba",
-- src/region_map.c:790
"data/generated/gba/region_map/dungeon_icon_visited.rgba",
"data/generated/gba/region_map/dungeon_icon_visited.png",
-- src/learn_move.c:403
"data/generated/gba/move_relearner/manifest.lua",
"data/generated/gba/move_relearner/bg.rgba",
-- src/daycare.c:137, :138, :139
"data/generated/gba/pokemon/egg/manifest.lua",
"data/generated/gba/pokemon/egg/hatch.rgba",
"data/generated/gba/pokemon/egg/shard.rgba",
"data/generated/gba/pokemon/front/412.rgba",
"data/generated/gba/pokemon/icons/412.rgba",
-- src/trainer_card.c:265, :1454, :1560
"data/generated/gba/trainer_card/front_0.rgba",
"data/generated/gba/trainer_card/front_4_female.rgba",
"data/generated/gba/trainer_card/back_0.rgba",
"data/generated/gba/trainer_card/back_4_female.rgba",
"data/generated/gba/trainer_card/screen_0.rgba",
"data/generated/gba/trainer_card/screen_4_female.rgba",
"data/generated/gba/trainer_card/star.rgba",
"data/generated/gba/trainer_card/stickers.rgba",
}
for _, path in ipairs(ROUND2_KEYS) do
check(have[path] == true, "required: " .. path)
end
print("[test] 5. an imported cache at this version walks with zero missing keys")
local Cache = require("tests.game3_cache")
local root = Cache.root("meta.json")
if not root then
print("[skip] cache half: " .. tostring(Cache.reason))
else
print("[info] FireRed cache at " .. root)
local base = root:gsub("/data/generated/gba$", "")
local diskFs = {
prefix = nil,
read = function(path)
local f = io.open(base .. "/" .. path, "rb")
if not f then return nil end
local data = f:read("*a")
f:close()
return data
end,
exists = function(path)
local f = io.open(base .. "/" .. path, "rb")
if not f then return false end
f:close()
return true
end,
}
check(CacheContract.cacheVersionCurrent("firered", diskFs) == true,
"the imported cache passes the staleness gate")
local complete, missing = CacheContract.allRequiredFilesExist("firered", diskFs)
check(complete == true, "zero missing required keys, first missing: " .. tostring(missing))
end
if failed > 0 then
print(string.format("[result] %d CHECK(S) FAILED", failed))
os.exit(1)
end
print("[result] all checks passed")
os.exit(0)