Files
gen1recomp/tests/save_compat/_r2.lua
T
2026-10-01 17:30:52 -04:00

96 lines
3.5 KiB
Lua

local K = require("tests.save_compat._codec")
local Diff = require("tests.save_compat._diff")
local Expect = require("tests.save_compat._expect")
local R2 = {}
R2.ROOTS = {
[1] = { "player", "money", "coins", "currentBox", "playTime", "inventory", "pcItems", "pokedex", "party",
"boxes", "hallOfFame", "lastHeal", "options", "visited", "pikachuHappiness", "flags", "safari", "daycare",
"forcedBike", "usedPokecenter", "trashPuzzle", "labFossilMon", "hiddenTaken", "surfingHighScore",
"flashLit", "onBike", "pikachuMood", "pikachuEmotionModifier" },
[2] = { "player", "rival", "mom", "party", "boxes", "inventory", "currentBox", "pokedex", "position",
"playTime", "events", "mapScenes", "engineFlags", "boxNames", "variableSprites" },
[3] = { "name", "trainerId", "secretId", "gender", "money", "coins", "map", "x", "y", "party", "storage",
"bag", "roamer", "encryptionKey", "dex" },
}
R2.EXCLUDED = {
cartExtra = "Gen 3 per-mon carrier of raw cart bytes, regenerated on import",
cartImport = "Gen 3 marker set by every import",
rawImport = "Gen 1 template string, dropped on purpose for a templateless export",
warnings = "decode diagnostics",
}
local function fmt(v)
if type(v) == "number" and v ~= math.floor(v) then return ("%.4f"):format(v) end
return tostring(v)
end
local function flatten(v, path, out)
if type(v) ~= "table" then
out[path] = fmt(v)
return
end
local any = false
for k, x in pairs(v) do
if not (type(k) == "string" and R2.EXCLUDED[k]) then
any = true
local seg = type(k) == "number" and ("[" .. k .. "]") or ("." .. tostring(k))
flatten(x, path .. seg, out)
end
end
if not any then out[path] = "{}" end
end
function R2.project(gen, save)
local out = {}
for _, root in ipairs(R2.ROOTS[gen]) do
if save[root] ~= nil then flatten(save[root], root, out) end
end
return out
end
function R2.run(T, gen, cases)
local track = Expect.new("r2")
local verbose = os.getenv("SAVE_COMPAT_VERBOSE") == "1"
for _, c in ipairs(cases) do
track.case(c.id)
local want = R2.project(gen, c.save)
local out, err = K.export(gen, c.version, c.save, false)
if not out then
track.fail(c.id, "export", err)
else
for _, k in ipairs(K.compatKeys(out, c.version)) do track.fail(c.id, k.key, k.detail) end
local back, ierr = K.import(gen, c.version, out)
if not back then
track.fail(c.id, "reimport", ierr)
else
local got = R2.project(gen, back)
local paths = {}
for p in pairs(want) do paths[#paths + 1] = p end
table.sort(paths)
for _, p in ipairs(paths) do
if got[p] ~= want[p] then
local key = "field:" .. p:gsub("%[%d+%]", "[]")
track.fail(c.id, key, ("%s: %s -> %s"):format(p, want[p], tostring(got[p])))
if verbose then print(c.id, p, want[p], got[p]) end
end
end
for _, f in ipairs(c.extra and c.extra(back, out) or {}) do track.fail(c.id, f[1], f[2]) end
local again, aerr = K.export(gen, c.version, back, false)
if not again then
track.fail(c.id, "fixedpoint-export", aerr)
elseif again ~= out then
local entries = K.r1Diff(gen, c.version, out, again)
if #entries == 0 then entries = { { name = "derived", count = 0, first = 0, last = 0, sample = {} } } end
for _, e in ipairs(entries) do track.fail(c.id, "fixedpoint:" .. e.name, Diff.format({ e })) end
end
end
end
end
track.finish(T)
end
return R2