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

154 lines
6.1 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_battle_assets_test: skipped (no ROM at " .. ROM_PATH .. ")")
os.exit(0)
end
local raw = f:read("*a")
f:close()
if raw:sub(0xAD, 0xB0) ~= "BPEE" then
print("emerald_battle_assets_test: skipped (" .. ROM_PATH .. " is not Emerald)")
os.exit(0)
end
local ok, ffi = pcall(require, "ffi")
local Rom = require("src.import.gba.rom")
local Versions = require("src.import.gba.versions")
local GameVersion = require("src.core.GameVersion")
GameVersion.set("emerald")
Versions.select("emerald")
local rom = setmetatable({ _raw = raw, size = #raw, _cdata = ok and ffi.cast("const uint8_t*", raw) or nil }, Rom)
local files = {}
local cache = {
write = function(_, rel, data) files[rel] = data; return true end,
exists = function(_, rel) return files[rel] ~= nil end,
read = function(_, rel) return files[rel] end,
}
local ROOT = "data/generated/gba"
local function load(rel)
local src = files[ROOT .. "/" .. rel]
if not src then return nil end
return assert(loadstring(src))()
end
local function run(name)
local M = require("src.import.gba." .. name)
local okR, res = pcall(M.run, rom, cache, { cacheRoot = ROOT, strict = true, force = true })
check(okR, name .. " runs strict on Emerald: " .. tostring(okR or res))
for _, rel in ipairs(M.REQUIRED or {}) do
check(files[ROOT .. "/" .. rel] ~= nil, name .. " wrote required " .. rel)
end
return res
end
run("battle_anim_extract")
local pack = load("pokemon/battle_anims/pack.lua")
check(pack ~= nil, "anim pack written")
if pack then
local Names = require("src.import.gba.anim_names_emerald")
local hexTasks, noCb, noTmpl, tasks = 0, 0, 0, {}
local function scan(list)
for _, op in ipairs(list or {}) do
if op.op == "createvisualtask" or op.op == "createsoundtask" then
if tostring(op.task):match("^0x") then hexTasks = hexTasks + 1 end
tasks[op.task] = true
elseif op.op == "createsprite" then
if not op.callback then noCb = noCb + 1 end
if not op.template then noTmpl = noTmpl + 1 end
end
end
end
for _, s in pairs(pack.moves) do scan(s) end
for _, s in pairs(pack.labels) do scan(s) end
for _, k in ipairs({ "general", "special", "status" }) do
for _, s in pairs(pack[k]) do scan(s) end
end
eq(hexTasks, 0, "0 unresolved task names")
eq(noCb, 0, "0 unresolved sprite callbacks")
eq(noTmpl, 0, "0 unresolved sprite templates")
local moves = 0
for _ in pairs(pack.moves) do moves = moves + 1 end
eq(moves, 355, "355 move scripts")
eq(pack.generalNames[4], "POKEBLOCK_THROW", "general anim names are emerald's")
check(tasks.LoadBaitGfx and tasks.FreeBaitGfx, "pokeblock gfx tasks carry the FR canonical names")
check(tasks.IsBallBlockedByTrainer and tasks.ThrowBall_StandingTrainer, "emerald-only ball tasks are named")
for _, name in ipairs(Names.gameOnly.tasks) do
check(tasks[(name:gsub("^AnimTask_", ""))], "game-only task " .. name .. " is used by a script")
end
check(pack.tags.POKEBLOCK ~= nil, "POKEBLOCK sprite sheet baked")
check(pack.statMask and #pack.statMask.pals == 8, "8 stat change palettes")
local bgs = 0
for k in pairs(pack.animBgs) do if type(k) == "number" then bgs = bgs + 1 end end
eq(bgs, 27, "27 anim backgrounds")
check(pack.animBgs.SURF_PLAYER and pack.animBgs.CURSE and pack.animBgs.FOG, "named anim backgrounds")
end
run("battle_ai_extract")
local ai = load("battle_ai/pack.lua")
check(ai and #ai.table == 32, "32 AI script entries")
if ai then
local seen = {}
for _, body in pairs(ai.scripts) do
for _, ir in ipairs(body) do seen[ir.op] = true end
end
for _, op in ipairs({ "if_target_is_ally", "is_of_type", "check_ability", "if_flash_fired", "if_holds_item" }) do
check(seen[op], "emerald AI op " .. op .. " decoded")
end
end
run("battle_chrome_extract")
local chrome = load("pokemon/battle/manifest.lua")
check(chrome and chrome.layout == "rse", "rse chrome manifest")
if chrome then
eq(#(files[ROOT .. "/pokemon/battle/textbox.rgba"] or ""), chrome.textboxW * chrome.textboxH * 4, "textbox size")
eq(chrome.environments[0], "grass", "environment 0")
eq(chrome.environments[9], "plain", "environment 9")
for _, key in ipairs(chrome.scenes) do
check(files[ROOT .. "/pokemon/battle/terrain_" .. key .. ".rgba"], "scene " .. key .. " baked")
end
eq(#chrome.scenes, 13, "13 scenes")
eq(chrome.elementsTiles, 118, "118 healthbox element tiles")
eq(#chrome.windows.normal, 24, "24 normal battle windows")
end
run("battle_transition_extract")
local tr = load("pokemon/battle_transition/manifest.lua")
check(tr and tr.layout == "rse", "rse transition manifest")
if tr then
eq(tr.ids.AQUA, 17, "transition 17 is AQUA on Emerald")
eq(tr.ids.SPIRAL, nil, "no SPIRAL transition on Emerald")
eq(tr.ids.FRONTIER_CIRCLES_SYMMETRIC_SPIRAL_IN_SEQ, 41, "last transition id")
eq(tr.assets.rayquaza.tiles, 938, "rayquaza tileset tiles")
eq(tr.assets.rayquaza.w * tr.assets.rayquaza.h, #files[ROOT .. "/pokemon/battle_transition/rayquaza.idx"],
"rayquaza index map")
eq(tr.mugshotTrainerPics[5], 54, "champion mugshot pic")
for _, key in ipairs(tr.mugshots) do
check(files[ROOT .. "/pokemon/battle_transition/vsbar_" .. key .. "_female.rgba"], "vsbar " .. key)
end
end
run("ball_open_extract")
check(load("pokemon/battle/ball_open/manifest.lua") ~= nil, "ball open manifest")
run("battle_rse_data_extract")
local data = load("pokemon/battle/rse_data.lua")
check(data ~= nil, "rse battle data")
if data then
eq(#data.pickupItems, 18, "18 pickup items")
eq(#data.rarePickupItems, 11, "11 rare pickup items")
eq(data.pickupProbabilities[9], 98, "pickup probability tail")
eq(data.stevenMons[1].speciesName, "SPECIES_METANG", "Steven mon 1")
eq(data.stevenMons[1].level, 42, "Steven mon level")
eq(data.stevenMons[3].speciesName, "SPECIES_AGGRON", "Steven mon 3")
eq(#data.environmentToType, 10, "environment to type")
end
Versions.select("firered")
T.finish("emerald_battle_assets_test")