mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
162 lines
6.1 KiB
Lua
162 lines
6.1 KiB
Lua
#!/usr/bin/env luajit
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local failed = 0
|
|
local function check(cond, msg)
|
|
if cond then
|
|
print("[ok] " .. msg)
|
|
else
|
|
failed = failed + 1
|
|
print("[FAIL] " .. msg)
|
|
end
|
|
end
|
|
|
|
local BattleChromeExtract = require("src.import.gba.battle_chrome_extract")
|
|
local Versions = require("src.import.gba.versions")
|
|
|
|
-- include/constants/battle.h:287
|
|
local PRET_KEYS = {
|
|
[0] = "grass", "long_grass", "sand", "underwater", "water", "pond", "mountain",
|
|
"cave", "building", "plain", "link", "gym", "leader", "indoor_2", "indoor_1",
|
|
"lorelei", "bruno", "agatha", "lance", "champion",
|
|
}
|
|
|
|
print("[test] 1. every sBattleTerrainTable id has a sheet key")
|
|
local keys = BattleChromeExtract.TERRAIN_KEYS or {}
|
|
local count = 0
|
|
for _ in pairs(keys) do count = count + 1 end
|
|
check(count == 20, "20 terrain ids are named (" .. count .. ")")
|
|
for id = 0, 19 do
|
|
check(keys[id] == PRET_KEYS[id],
|
|
string.format("terrain %d is %s (%s)", id, tostring(PRET_KEYS[id]), tostring(keys[id])))
|
|
end
|
|
|
|
print("[test] 2. the terrain table is read out of the ROM")
|
|
check(type(BattleChromeExtract.terrainTable) == "function"
|
|
and tonumber(BattleChromeExtract.TERRAIN_ENTRY_SIZE) ~= nil
|
|
and tonumber(BattleChromeExtract.TERRAIN_TABLE) ~= nil,
|
|
"battle_chrome_extract reads sBattleTerrainTable")
|
|
if type(BattleChromeExtract.terrainTable) ~= "function"
|
|
or not BattleChromeExtract.TERRAIN_ENTRY_SIZE then
|
|
print("[test] FAILED " .. failed)
|
|
os.exit(1)
|
|
end
|
|
local grass = Versions.BATTLE_UI.terrain_grass
|
|
local base = BattleChromeExtract.TERRAIN_TABLE
|
|
local bytes = {}
|
|
local function poke32(off, value)
|
|
for i = 0, 3 do
|
|
bytes[off + i] = math.floor(value / 256 ^ i) % 256
|
|
end
|
|
end
|
|
local function entry(id, tiles, tilemap, pal)
|
|
local off = base + id * BattleChromeExtract.TERRAIN_ENTRY_SIZE
|
|
poke32(off, tiles + 0x08000000)
|
|
poke32(off + 4, tilemap + 0x08000000)
|
|
poke32(off + 8, 0x08000000)
|
|
poke32(off + 12, 0x08000000)
|
|
poke32(off + 16, pal + 0x08000000)
|
|
end
|
|
entry(0, grass.tiles, grass.tilemap, grass.pal)
|
|
for id = 1, 19 do
|
|
entry(id, 0x100000 + id * 0x1000, 0x200000 + id * 0x1000, 0x300000 + id * 0x100)
|
|
end
|
|
local function get(off) return bytes[off] or 0 end
|
|
|
|
local table_ = BattleChromeExtract.terrainTable(get)
|
|
check(type(table_) == "table" and #table_ == 20, "20 entries parsed (" ..
|
|
tostring(type(table_) == "table" and #table_ or table_) .. ")")
|
|
if type(table_) == "table" and #table_ == 20 then
|
|
check(table_[1].key == "grass" and table_[1].cfg.tiles == grass.tiles,
|
|
"entry 0 is the pinned grass set")
|
|
check(table_[8].key == "cave" and table_[8].cfg.tiles == 0x100000 + 7 * 0x1000,
|
|
"entry 7 is cave (" .. tostring(table_[8].key) .. ")")
|
|
check(table_[5].key == "water" and table_[5].cfg.pal == 0x300000 + 4 * 0x100,
|
|
"entry 4 is water (" .. tostring(table_[5].key) .. ")")
|
|
check(table_[20].key == "champion", "entry 19 is champion (" .. tostring(table_[20].key) .. ")")
|
|
end
|
|
|
|
print("[test] 3. a table that does not match the pinned grass set is refused")
|
|
entry(0, grass.tiles + 4, grass.tilemap, grass.pal)
|
|
check(BattleChromeExtract.terrainTable(get) == nil, "a shifted entry 0 falls back")
|
|
entry(0, grass.tiles, grass.tilemap, grass.pal)
|
|
poke32(base + 4 * BattleChromeExtract.TERRAIN_ENTRY_SIZE, 0)
|
|
check(BattleChromeExtract.terrainTable(get) == nil, "a null tilemap pointer falls back")
|
|
local okRequire, requireErr = pcall(BattleChromeExtract.requireTerrainTable, get)
|
|
check(okRequire == false and tostring(requireErr):find("sBattleTerrainTable") ~= nil,
|
|
"the bake refuses a table it cannot decode instead of writing a partial terrain set")
|
|
entry(4, 0x100000 + 4 * 0x1000, 0x200000 + 4 * 0x1000, 0x300000 + 4 * 0x100)
|
|
local okAll, allTerrains = pcall(BattleChromeExtract.requireTerrainTable, get)
|
|
check(okAll and type(allTerrains) == "table" and #allTerrains == 20,
|
|
"a decodable table bakes all 20 sets")
|
|
|
|
print("[test] 4. baked terrain sheets in an imported cache")
|
|
local Cache = require("tests.game3_cache")
|
|
local root = Cache.root("pokemon/battle/manifest.lua")
|
|
if not root then
|
|
print("[skip] baked terrains: " .. tostring(Cache.reason))
|
|
if failed > 0 then
|
|
print("[test] FAILED " .. failed)
|
|
os.exit(1)
|
|
end
|
|
print("[test] all passed")
|
|
os.exit(0)
|
|
end
|
|
print("[info] FireRed cache at " .. root)
|
|
|
|
local function readFile(rel)
|
|
local f = io.open(root .. "/pokemon/battle/" .. rel, "rb")
|
|
if not f then return nil end
|
|
local data = f:read("*a")
|
|
f:close()
|
|
return data
|
|
end
|
|
|
|
local manifestSrc = readFile("manifest.lua")
|
|
local manifest = manifestSrc and loadstring(manifestSrc)
|
|
manifest = manifest and manifest()
|
|
if type(manifest) ~= "table" or (tonumber(manifest.format) or 0) < 6 then
|
|
print("[skip] baked terrains: cache manifest is format " ..
|
|
tostring(manifest and manifest.format) .. ", the terrain bake needs 6")
|
|
if failed > 0 then
|
|
print("[test] FAILED " .. failed)
|
|
os.exit(1)
|
|
end
|
|
print("[test] all passed")
|
|
os.exit(0)
|
|
end
|
|
|
|
local baked = manifest.terrains or {}
|
|
for id = 0, 19 do
|
|
local key = PRET_KEYS[id]
|
|
local info = baked[key]
|
|
check(type(info) == "table" and info.w == 256 and info.h == 256,
|
|
"manifest lists terrain " .. key)
|
|
local sheet = readFile("terrain_" .. key .. ".rgba")
|
|
check(sheet ~= nil and #sheet == 256 * 256 * 4,
|
|
string.format("terrain_%s.rgba is %s bytes", key, tostring(sheet and #sheet)))
|
|
for _, layer in ipairs({ "bg", "enemy", "player" }) do
|
|
local split = readFile("terrain_" .. layer .. "_" .. key .. ".rgba")
|
|
check(split ~= nil and #split == 256 * 160 * 4,
|
|
string.format("terrain_%s_%s.rgba is %s bytes", layer, key, tostring(split and #split)))
|
|
end
|
|
end
|
|
|
|
local cave = readFile("terrain_cave.rgba")
|
|
local water = readFile("terrain_water.rgba")
|
|
local building = readFile("terrain_building.rgba")
|
|
check(cave ~= building, "the cave sheet is not the building sheet")
|
|
check(water ~= building and water ~= cave, "the water sheet is its own art")
|
|
local opaque = 0
|
|
for i = 4, #cave, 4 do
|
|
if cave:byte(i) == 255 then opaque = opaque + 1 end
|
|
end
|
|
check(opaque > 256 * 100, "the cave sheet is opaque battle art (" .. opaque .. " pixels)")
|
|
|
|
if failed > 0 then
|
|
print("[test] FAILED " .. failed)
|
|
os.exit(1)
|
|
end
|
|
print("[test] all passed")
|