Files
gen1recomp/tests/game3_summary_chrome_bake_s3_test.lua
bryanthaboi 72a17b27dd CLOSES #2444
2026-09-24 08:39:43 -04:00

170 lines
6.9 KiB
Lua

#!/usr/bin/env luajit
-- pokefirered/src/pokemon_summary_screen.c:1862
package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
local PRET = "../pokefirered"
local GFX = PRET .. "/graphics/summary_screen/"
local ROM_SHA1 = "41cb23d8dccc8ebd7c649cd8fbb58eeace6e2fdc"
local function slurp(p)
local f = io.open(p, "rb")
if not f then return nil end
local d = f:read("*a")
f:close()
return d
end
local tiles = slurp(GFX .. "bg.4bpp")
local pal = slurp(GFX .. "bg.gbapal")
local romPresent = slurp(PRET .. "/pokefirered.gba") ~= nil
if not (tiles and pal and romPresent) then
print("[skip] " .. PRET .. " summary graphics or ROM not present")
os.exit(0)
end
local function u16(s, i) return s:byte(i + 1) + s:byte(i + 2) * 256 end
-- pokefirered/src/pokemon_summary_screen.c:3276
local BASE = 345
local PROGRESS = {
info = { { 17, 13, 0 }, { 33, 13, 1 }, { 16, 14, 0 }, { 32, 14, 1 }, { 18, 15, 0 }, { 34, 15, 1 },
{ 20, 16, 0 }, { 36, 16, 1 }, { 18, 17, 0 }, { 34, 17, 1 }, { 21, 18, 0 }, { 37, 18, 1 } },
moves = { { 49, 13, 0 }, { 65, 13, 1 }, { 1, 14, 0 }, { 19, 14, 1 }, { 49, 15, 0 }, { 65, 15, 1 },
{ 1, 16, 0 }, { 19, 16, 1 }, { 17, 17, 0 }, { 33, 17, 1 }, { 48, 18, 0 }, { 64, 18, 1 } },
moves_info_select = { { 1, 13, 0 }, { 1, 14, 0 }, { 1, 15, 0 }, { 1, 16, 0 },
{ 19, 13, 1 }, { 19, 14, 1 }, { 19, 15, 1 }, { 19, 16, 1 },
{ 50, 17, 0 }, { 66, 17, 1 }, { 48, 18, 0 }, { 64, 18, 1 } },
}
local function render(binName, progressKind, shiny)
local map = assert(slurp(GFX .. binName), binName)
local entries = {}
for i = 0, 32 * 20 - 1 do entries[i] = u16(map, i * 2) end
for _, p in ipairs(PROGRESS[progressKind] or {}) do
entries[p[3] * 32 + p[2]] = p[1] + BASE
end
local out = {}
for ty = 0, 19 do
for tx = 0, 29 do
local e = entries[ty * 32 + tx]
local tile, hf, vf, pn = e % 1024, math.floor(e / 1024) % 2 == 1, math.floor(e / 2048) % 2 == 1, math.floor(e / 4096)
local bank = pn
if shiny and pn == 0 then bank = 6 elseif shiny and pn == 1 then bank = 5 end
for y = 0, 7 do
for x = 0, 7 do
local sx, sy = hf and (7 - x) or x, vf and (7 - y) or y
local b = tiles:byte(tile * 32 + sy * 4 + math.floor(sx / 2) + 1) or 0
local idx = (sx % 2 == 0) and (b % 16) or math.floor(b / 16)
if idx ~= 0 then
out[(ty * 8 + y) * 240 + tx * 8 + x] = u16(pal, bank * 32 + idx * 2) % 32768
end
end
end
end
end
return out
end
local function to15(rgba, i)
local r, g, b = rgba:byte(i * 4 + 1), rgba:byte(i * 4 + 2), rgba:byte(i * 4 + 3)
local function c5(v) return math.floor(v * 31 / 255 + 0.5) end
return c5(r) + c5(g) * 32 + c5(b) * 1024, rgba:byte(i * 4 + 4)
end
local function compare(label, bake, want, w, h, ox, oy, opaque)
if not bake then check(false, label .. " was baked") return end
eq(#bake, w * h * 4, label .. " size")
local bad = 0
for y = 0, h - 1 do
for x = 0, w - 1 do
local c, a = to15(bake, y * w + x)
local p = want[(y + oy) * 240 + x + ox]
if p == nil then
if not opaque and a ~= 0 then bad = bad + 1 end
elseif a == 0 or c ~= p then
bad = bad + 1
end
end
end
eq(bad, 0, label .. " matches pret's tilemap render pixel for pixel")
end
local FileIO = require("src.import.gba.file_io")
local imports = FileIO.makeImports(PRET .. "/pokefirered.gba", ROM_SHA1, "firered")
local rom = assert(require("src.import.gba.rom").open(imports, "firered"))
local mem = { files = {} }
function mem:write(p, d) self.files[p] = d end
function mem:exists(p) return self.files[p] ~= nil end
require("src.import.gba.summary_chrome_extract").run(rom, mem, { cacheRoot = "X" })
local function baked(name) return mem.files["X/pokemon/summary/" .. name] end
print("[test] 1. KNOWN MOVES keeps the picture frame; move detail swaps it")
for _, shiny in ipairs({ false, true }) do
local sfx = shiny and "_shiny" or ""
compare("bg3_info" .. sfx, baked("bg3_info" .. sfx .. ".rgba"), render("moves_info_page.bin", nil, shiny), 240, 160, 0, 0, true)
compare("bg3_moves" .. sfx, baked("bg3_moves" .. sfx .. ".rgba"), render("moves_page.bin", nil, shiny), 240, 160, 0, 0, true)
for _, layer in ipairs({ "info", "moves", "moves_info" }) do
compare("layer_" .. layer .. sfx, baked("layer_" .. layer .. sfx .. ".rgba"),
render("page_" .. layer .. ".bin", nil, shiny), 240, 160, 0, 0, false)
end
for _, kind in ipairs({ "info", "moves", "moves_info_select" }) do
local base = kind == "moves_info_select" and "moves_page.bin" or "moves_info_page.bin"
compare("progress_" .. kind .. sfx, baked("progress_" .. kind .. sfx .. ".rgba"),
render(base, kind, shiny), 48, 16, 104, 0, true)
end
end
check(baked("page_moves.rgba") == nil, "the old move-detail bake under the KNOWN MOVES name is gone")
check(baked("page_info.rgba") ~= nil, "page_info.rgba still marks the cache ready")
print("[test] 2. manifest carries the ROM tables the screen reads")
local manifest = baked("manifest.lua")
local m = manifest and load(manifest, "=manifest", "t", {})()
check(m ~= nil, "the manifest loads")
if m then
local n = 0
for _ in pairs(m.noFlip or {}) do n = n + 1 end
eq(n, 18, "eighteen species are never flipped")
eq(m.noFlip and m.noFlip[25], nil, "Pikachu is flipped")
local lens = {}
for i, d in ipairs(m.monPicBounce or {}) do lens[i] = #d end
eq(table.concat(lens, ","), "3,5,7,7", "four pic bounce tables")
eq(m.monPicBounce and m.monPicBounce[4] and m.monPicBounce[4][1], -5, "the full-HP bounce starts at -5")
local el = {}
for i, d in ipairs(m.eggPicShake or {}) do el[i] = #d end
eq(table.concat(el, ","), "11,11,15", "three egg shake tables")
eq(m.eggPicShake and m.eggPicShake[3] and m.eggPicShake[3][7], -2, "AlmostReadyToHatch step 7 is -2")
local c = m.moveTextColors and m.moveTextColors[3]
check(c and c.fg[1] > 200 and c.fg[2] < 40, "PP colour 3 is red")
eq(m.coords and m.coords.status and m.coords.status.y, 34, "status is stored as a top-left")
end
print("[test] 3. markings sheet")
local marks = baked("markings.rgba")
eq(marks and #marks, 32 * 128 * 4, "sixteen 32x8 marking combos")
if marks then
local lit0, lit5 = 0, 0
for i = 0, 32 * 8 - 1 do
if marks:byte(i * 4 + 4) > 0 then lit0 = lit0 + 1 end
if marks:byte((5 * 256 + i) * 4 + 4) > 0 then lit5 = lit5 + 1 end
end
check(lit0 > 0 and lit5 > 0, "combos have pixels")
end
print("[test] 4. the imported cache")
local Cache = require("tests.game3_cache")
local root = Cache.root("meta.json")
if not root then
print("[skip] " .. tostring(Cache.reason))
else
for _, name in ipairs({ "bg3_info.rgba", "layer_moves.rgba", "progress_moves_info_select.rgba", "markings.rgba" }) do
local d = slurp(root .. "/pokemon/summary/" .. name)
check(d ~= nil and d == baked(name), "the cache's " .. name .. " is the current bake")
end
end
T.finish("game3_summary_chrome_bake_s3_test")