Files
gen1recomp/tests/emerald_boot_assets_test.lua
T
bryanthaboi 690f0cd9a1 TOUCHDOWN
2026-09-27 16:07:31 -04:00

135 lines
5.2 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
local ROM_PATH = os.getenv("POKEPORT_EMERALD_ROM") or "../pokeemerald/pokeemerald.gba"
local f = io.open(ROM_PATH, "rb")
if not f then
print("emerald_boot_assets_test: skipped (no ROM at " .. ROM_PATH .. ")")
os.exit(0)
end
local data = f:read("*a")
f:close()
if data:sub(0xAD, 0xB0) ~= "BPEE" then
print("emerald_boot_assets_test: skipped (" .. ROM_PATH .. " is not Emerald)")
os.exit(0)
end
local rom = { id = "emerald", size = #data }
function rom.get(_, o) return data:byte(o + 1) end
function rom.u16(_, o) local a, b = data:byte(o + 1, o + 2); return a + b * 256 end
function rom.u32(_, o)
local a, b, c, d = data:byte(o + 1, o + 4)
return a + b * 256 + c * 65536 + d * 16777216
end
function rom.readString(_, o, n) return data:sub(o + 1, o + n) end
local files = {}
local cache = {
write = function(_, rel, bytes) files[rel] = bytes; return true end,
read = function(_, rel) return files[rel] end,
exists = function(_, rel) return files[rel] ~= nil end,
}
local K = require("src.import.gba.rse.boot_gfx")
local ROOT = "data/generated/gba"
local MODS = {
"intro_credits_gfx_extract", "extract_intro_emerald", "extract_title_rse",
"extract_birch_rse", "extract_naming_rse", "extract_wallclock_rse",
}
local required = {}
for _, name in ipairs(MODS) do
local M = require("src.import.gba.rse." .. name)
check(not M.ready(cache, ROOT), name .. " not ready before run")
local ok, man = M.run(rom, cache, { cacheRoot = ROOT })
eq(ok, true, name .. " ran")
check(M.ready(cache, ROOT), name .. " ready after run")
eq(man.format, K.FORMAT, name .. " manifest format")
local body = files[ROOT .. "/" .. M.SUB .. "/manifest.lua"]
local chunk = body and loadstring(body)
check(chunk ~= nil, name .. " manifest parses")
if chunk then
local loaded = chunk()
eq(#loaded.files, #M.REQUIRED - 1, name .. " manifest lists every image")
end
for _, rel in ipairs(M.REQUIRED) do required[ROOT .. "/" .. rel] = true end
end
local produced, dims = {}, {}
for rel, bytes in pairs(files) do
produced[#produced + 1] = rel
if rel:match("%.png$") then
local w, h = K.pngSize(bytes)
dims[rel] = { w, h }
check(w and h and w > 0 and h > 0, rel .. " is a png")
end
end
table.sort(produced)
print(string.format("emerald_boot_assets_test: %d files", #produced))
for _, rel in ipairs(produced) do
local d = dims[rel]
print(string.format(" %-62s %s", rel, d and (d[1] .. "x" .. d[2]) or (#files[rel] .. " bytes")))
check(required[rel], rel .. " is declared in REQUIRED")
end
for rel in pairs(required) do check(files[rel] ~= nil, rel .. " was produced") end
local function dim(rel, w, h)
local d = dims[ROOT .. "/" .. rel]
check(d ~= nil, rel .. " exists")
if d then eq(d[1] .. "x" .. d[2], w .. "x" .. h, rel .. " size") end
end
dim("intro/rse/copyright.png", 256, 256)
dim("intro/rse/scene1_bg3.png", 256, 512)
dim("intro/rse/scene3_pokeball.png", 256, 256)
dim("intro/rse/scene3_groudon.png", 512, 512)
dim("intro/rse/scene3_kyogre.png", 512, 512)
dim("intro/rse/scene3_clouds_left.png", 512, 256)
dim("intro/rse/manectric.png", 64, 256)
dim("intro/rse/scenery/trees_bg3_sunset.png", 256, 256)
dim("intro/rse/scenery/grass_night.png", 256, 256)
dim("intro/rse/scenery/brendan.png", 64, 256)
dim("intro/rse/scenery/bicycle.png", 64, 128)
dim("title/logo.png", 256, 256)
dim("title/version_banner_left.png", 64, 32)
dim("title/press_start.png", 32, 80)
dim("birch/bg_8.png", 256, 160)
dim("birch/lotad.png", 64, 128)
dim("naming/bg.png", 240, 160)
dim("naming/kb_upper.png", 176, 80)
dim("naming/cursor.png", 48, 16)
dim("wallclock/start_female.png", 256, 160)
dim("wallclock/minute_hand_male.png", 64, 64)
local function manifest(sub)
return loadstring(files[ROOT .. "/" .. sub .. "/manifest.lua"])()
end
local title = manifest("title")
eq(#title.alphaBlend, 64, "gTitleScreenAlphaBlend has 64 rows")
eq(title.alphaBlend[1][1] .. "," .. title.alphaBlend[1][2], "16,0", "first title blend step")
eq(title.sprites.press_start.frames, 10, "press start + copyright frames")
local birch = manifest("birch")
eq(#birch.presetNames.male, 20, "20 male preset names")
eq(birch.presetNames.male[1], "STU", "first male preset name")
eq(birch.presetNames.female[20], "HALIE", "last female preset name")
eq(birch.layers.bg.initialState, 8, "Birch gradient starts at state 8")
local naming = manifest("naming")
eq(#naming.templates, 5, "five naming templates")
eq(naming.templates[5].title, "Tell him the words.", "Walda template title")
eq(naming.keyboard.text[2][1], "ABCDEF .", "upper keyboard row")
local wall = manifest("wallclock")
eq(#wall.handCoords, 360, "360 hand coords")
eq(wall.handCoords[1][2], -24, "hand coord 0 y")
local intro = manifest("intro/rse")
eq(#intro.tables.sparkleCoords, 11, "11 sparkle coords")
eq(#intro.tables.gameFreakLetters, 9, "9 Game Freak letters")
eq(#intro.tables.groudonRocks, 6, "6 Groudon rocks")
eq(#intro.tables.kyogreBubbles, 12, "12 Kyogre bubbles")
eq(intro.sprites.torchic.anims[3][3].frame, 5, "Torchic trip anim third frame")
local scenery = manifest("intro/rse/scenery")
eq(#scenery.scenery.moving_clouds.sprites, 9, "9 cloud sprites")
eq(#scenery.scenery.moving_trees.sprites, 12, "12 tree sprites")
T.finish("emerald_boot_assets_test")