mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-28 23:00:21 -04:00
146 lines
5.9 KiB
Lua
146 lines
5.9 KiB
Lua
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
|
|
local PRET = os.getenv("POKEPORT_POKEEMERALD") or "../pokeemerald"
|
|
local ROM_PATH = os.getenv("POKEPORT_EMERALD_ROM") or (PRET .. "/pokeemerald.gba")
|
|
local f = io.open(ROM_PATH, "rb")
|
|
if not f then
|
|
print("emerald_ow_test: skipped (no ROM at " .. ROM_PATH .. ")")
|
|
os.exit(0)
|
|
end
|
|
local data = f:read("*a")
|
|
f:close()
|
|
|
|
local rom = { md5 = "f3ae088181bf583e55daf962a92bb46f4f1d07b7", 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
|
|
function rom:readBytes(o, n)
|
|
local t = {}
|
|
for i = 1, n do t[i] = data:byte(o + i) end
|
|
return t
|
|
end
|
|
function rom:ptrOffset(p)
|
|
if not p or p < 0x08000000 or p >= 0x0A000000 then return nil end
|
|
return p - 0x08000000
|
|
end
|
|
|
|
local files = {}
|
|
local cache = {
|
|
write = function(_, rel, s) files[rel] = s; return true end,
|
|
read = function(_, rel) return files[rel] end,
|
|
exists = function(_, rel) return files[rel] ~= nil end,
|
|
}
|
|
|
|
local GameVersion = require("src.core.GameVersion")
|
|
GameVersion.set("emerald")
|
|
local Versions = require("src.import.gba.versions")
|
|
Versions.select("emerald")
|
|
local S = Versions.SYMS
|
|
local OwExtract = require("src.import.gba.ow_extract")
|
|
|
|
local ROOT = "data/generated/gba"
|
|
eq(Versions.NUM_OBJ_EVENT_GFX, 239, "239 Emerald object event graphics")
|
|
local res = OwExtract.run(rom, cache, { cacheRoot = ROOT })
|
|
eq(res.count, 239, "every gfx id extracted")
|
|
eq(res.total, 239, "manifest total")
|
|
check(res.avatars, "avatar table written")
|
|
check(OwExtract.ready(cache, ROOT), "step ready after run")
|
|
for _, rel in ipairs(OwExtract.REQUIRED) do
|
|
check(files[ROOT .. "/" .. rel] ~= nil, "wrote " .. rel)
|
|
end
|
|
|
|
local manifest = assert(load(files[ROOT .. "/ow/manifest.lua"], "@manifest", "t", {}))()
|
|
eq(manifest.ow_version, Versions.OW_VERSION, "manifest stamp")
|
|
eq(manifest.count, 239, "manifest count")
|
|
|
|
local pals = OwExtract.loadPaletteTable(rom)
|
|
local np = 0
|
|
for _ in pairs(pals) do np = np + 1 end
|
|
eq(np, Versions.OW_SPRITE_PALETTE_COUNT - 1, "every sObjectEventSpritePalettes entry loaded")
|
|
|
|
local frameMismatch, missingPal, blobBad = 0, 0, 0
|
|
for gid = 0, 238 do
|
|
local s = manifest.sprites[gid]
|
|
local info = rom:u32(Versions.OW_GFX_POINTERS + gid * 4) - 0x08000000
|
|
local images = rom:u32(info + 0x1C) - 0x08000000
|
|
local want
|
|
for _, n in ipairs(S.namesAt(images)) do
|
|
if n:find("PicTable", 1, true) then want = S.size(n) / 8 end
|
|
end
|
|
if not s or s.frameCount ~= want then frameMismatch = frameMismatch + 1 end
|
|
if s and not pals[s.paletteTag] then missingPal = missingPal + 1 end
|
|
local rgba = files[ROOT .. "/ow/" .. gid .. ".rgba"]
|
|
if not (s and rgba and #rgba == s.atlasW * s.atlasH * 4 and s.atlasH == s.height * s.frameCount) then
|
|
blobBad = blobBad + 1
|
|
end
|
|
local meta = OwExtract.decodeMeta(files[ROOT .. "/ow/" .. gid .. ".meta"])
|
|
if not meta or meta.graphicsId ~= gid then blobBad = blobBad + 1 end
|
|
end
|
|
eq(frameMismatch, 0, "frame counts equal pret pic table lengths")
|
|
eq(missingPal, 0, "every sprite palette tag resolves")
|
|
eq(blobBad, 0, "every rgba sheet and meta blob is well formed")
|
|
|
|
local av = manifest.avatars
|
|
local want = {
|
|
NORMAL = { Versions.OW_PLAYER_MALE, Versions.OW_PLAYER_FEMALE },
|
|
MACH_BIKE = { Versions.OW_PLAYER_MALE_BIKE, Versions.OW_PLAYER_FEMALE_BIKE },
|
|
ACRO_BIKE = { Versions.OW_PLAYER_MALE_ACRO_BIKE, Versions.OW_PLAYER_FEMALE_ACRO_BIKE },
|
|
SURFING = { Versions.OW_PLAYER_MALE_SURF, Versions.OW_PLAYER_FEMALE_SURF },
|
|
UNDERWATER = { Versions.OW_PLAYER_MALE_UNDERWATER, Versions.OW_PLAYER_FEMALE_UNDERWATER },
|
|
FIELD_MOVE = { Versions.OW_PLAYER_MALE_FIELD_MOVE, Versions.OW_PLAYER_FEMALE_FIELD_MOVE },
|
|
FISHING = { Versions.OW_PLAYER_MALE_FISH, Versions.OW_PLAYER_FEMALE_FISH },
|
|
WATERING = { Versions.OW_PLAYER_MALE_WATERING, Versions.OW_PLAYER_FEMALE_WATERING },
|
|
}
|
|
eq(#av.player, 8, "8 player avatar states")
|
|
eq(#av.rival, 8, "8 rival avatar states")
|
|
for _, row in ipairs(av.player) do
|
|
local w = want[row.state]
|
|
check(w and row.male == w[1] and row.female == w[2], "player " .. row.state .. " gfx matches event_objects.h")
|
|
end
|
|
eq(av.rival[1].male, 100, "rival Brendan normal")
|
|
eq(av.rival[1].female, 105, "rival May normal")
|
|
eq(#av.stateFlags.male, 5, "5 gfx-to-state flag rows per gender")
|
|
eq(av.stateFlags.male[1].gfx, Versions.OW_PLAYER_MALE, "state flag row 0 is Brendan normal")
|
|
eq(av.stateFlags.female[4].gfx, Versions.OW_PLAYER_FEMALE_SURF, "state flag row 3 is May surfing")
|
|
|
|
local function png_indices(path, fw, fh, frames)
|
|
local cmd = string.format(
|
|
"python3 -c \"import sys\nfrom PIL import Image\nim=Image.open(sys.argv[1]);px=im.load()\n"
|
|
.. "for f in range(%d):\n print(''.join('%%x'%%(px[f*%d+x,y]&15) for y in range(%d) for x in range(%d)))\" %s 2>/dev/null",
|
|
frames, fw, fh, fw, path)
|
|
local p = io.popen(cmd)
|
|
if not p then return nil end
|
|
local out = {}
|
|
for line in p:lines() do out[#out + 1] = line end
|
|
p:close()
|
|
if #out ~= frames then return nil end
|
|
return out
|
|
end
|
|
|
|
local pals2 = OwExtract.loadPaletteTable(rom)
|
|
for _, spec in ipairs({
|
|
{ gid = Versions.OW_PLAYER_MALE, png = PRET .. "/graphics/object_events/pics/people/brendan/walking.png" },
|
|
{ gid = Versions.OW_PLAYER_FEMALE, png = PRET .. "/graphics/object_events/pics/people/may/walking.png" },
|
|
}) do
|
|
local spr = assert(OwExtract.extractOne(rom, spec.gid, pals2))
|
|
local ref = png_indices(spec.png, spr.width, spr.height, 9)
|
|
if not ref then
|
|
print("emerald_ow_test: pixel spot check skipped (no python3/PIL or pret png)")
|
|
else
|
|
for fi = 1, 9 do
|
|
local got = {}
|
|
for p = 1, spr.width * spr.height do got[p] = string.format("%x", spr.frames[fi][p]) end
|
|
eq(table.concat(got), ref[fi], "gfx " .. spec.gid .. " walk frame " .. (fi - 1) .. " pixel exact vs pret png")
|
|
end
|
|
end
|
|
end
|
|
|
|
T.finish("emerald_ow_test")
|