mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-28 23:00:21 -04:00
193 lines
8.9 KiB
Lua
193 lines
8.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_pokedex_test: skipped (no ROM at " .. ROM_PATH .. ")")
|
|
os.exit(0)
|
|
end
|
|
local data = f:read("*a")
|
|
f:close()
|
|
|
|
local rom = {}
|
|
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:ptrOffset(p)
|
|
if not p or p < 0x08000000 or p >= 0x0A000000 then return nil end
|
|
return p - 0x08000000
|
|
end
|
|
|
|
local files = {}
|
|
local cache = {}
|
|
function cache:write(rel, bytes) files[rel] = bytes; return true end
|
|
function cache:read(rel) return files[rel] end
|
|
function cache:exists(rel) return files[rel] ~= nil end
|
|
|
|
local ROOT = "data/generated/gba"
|
|
local function loadLua(rel)
|
|
local src = assert(files[ROOT .. "/" .. rel], "missing " .. rel)
|
|
return assert(load(src, "@" .. rel, "t", {}))()
|
|
end
|
|
|
|
require("src.core.GameVersion").set("emerald")
|
|
require("src.import.gba.versions").select("emerald")
|
|
local C = require("src.core.game3.constants").of("emerald")
|
|
local S = require("src.import.gba.syms").of("emerald")
|
|
|
|
local Dex = require("src.import.gba.rse.pokedex_chrome_extract")
|
|
local ok, man = Dex.run(rom, cache, { cacheRoot = ROOT, game = "emerald" })
|
|
check(ok and type(man) == "table", "pokedex chrome extractor runs")
|
|
for _, rel in ipairs(Dex.REQUIRED) do
|
|
check(files[ROOT .. "/" .. rel] ~= nil, "pokedex extractor writes " .. rel)
|
|
end
|
|
man = loadLua("rse/pokedex/manifest.lua")
|
|
local orders = loadLua("rse/pokedex/orders.lua")
|
|
eq(#orders.numerical_hoenn, 202, "HOENN_DEX_COUNT entries in regional order")
|
|
eq(orders.numerical_hoenn[1], 252, "Hoenn #001 is TREECKO (national 252)")
|
|
eq(orders.numerical_hoenn[12], 263, "Hoenn #012 is ZIGZAGOON (national 263)")
|
|
eq(orders.type, nil, "Emerald has no type order table")
|
|
eq(orders.numerical_kanto, nil, "Emerald writes no Kanto order")
|
|
eq(#orders.atoz, 386, "gPokedexOrder_Alphabetical minus the 25 old Unown slots")
|
|
eq(orders.atoz[1], 63, "A TO Z starts with ABRA")
|
|
eq(#man.search.orders, 6, "six listing modes")
|
|
eq(man.search.orders[1].title, "NUMERICAL MODE", "sDexOrderOptions[0] title")
|
|
eq(#man.search.types, 18, "type list: NONE + 17 types")
|
|
eq(#man.search.colors, 11, "color list: DON'T SPECIFY + 10 body colors")
|
|
eq(#man.search.names, 10, "name list: DON'T SPECIFY + 9 letter groups")
|
|
eq(man.search.letterRanges[1][2], 3, "NAME_ABC covers 3 letters")
|
|
eq(man.search.typeIds[1], 255, "sDexSearchTypeIds[0] is TYPE_NONE")
|
|
eq(man.bodyColor[C.species.byName.SPECIES_TREECKO], 3, "TREECKO body color GREEN")
|
|
eq(man.sine[64], 256, "gSineTable[64]")
|
|
eq(#man.area.glowMapping, 256, "sAreaGlowTilemapMapping has 256 entries")
|
|
eq(man.area.feebas[1][1], C.species.byName.SPECIES_FEEBAS, "sFeebasData lists FEEBAS")
|
|
eq(#man.palettes.hoenn, 96, "gPokedexBgHoenn_Pal is 6 palettes")
|
|
|
|
local EncountersExtract = require("src.import.gba.encounters_extract")
|
|
EncountersExtract.run(rom, cache, { cacheRoot = ROOT })
|
|
local encounters = loadLua("encounters.lua")
|
|
|
|
local groups = S.off("gMapGroups")
|
|
local function mapsecOf(g, n)
|
|
local gp = rom:ptrOffset(rom:u32(groups + g * 4))
|
|
local hp = gp and rom:ptrOffset(rom:u32(gp + n * 4))
|
|
return hp and rom:get(hp + 0x14) or 213
|
|
end
|
|
|
|
local RM = require("src.import.gba.rse.region_map_extract")
|
|
RM.run(rom, cache, { cacheRoot = ROOT, game = "emerald" })
|
|
require("src.import.gba.rse.map_sections_extract").run(rom, cache, { cacheRoot = ROOT })
|
|
package.loaded["src.core.game3.dataset"] = { cache = function() return cache end }
|
|
_G.love = {
|
|
filesystem = {
|
|
getInfo = function(p) return files[p] and { type = "file" } or nil end,
|
|
load = function(p) return load(files[p], "@" .. p) end,
|
|
read = function(p) return files[p] end,
|
|
},
|
|
}
|
|
local RegionMap = require("src.ui.game3.rse.region_map")
|
|
local Area = require("src.ui.game3.rse.pokedex_area")
|
|
|
|
local flagsSet = {}
|
|
local function ctx(extra)
|
|
local c = {
|
|
encounters = encounters,
|
|
groups = {
|
|
towns = C:map("MAP_PETALBURG_CITY").group,
|
|
dungeons = C:map("MAP_METEOR_FALLS_1F_1R").group,
|
|
special = C:map("MAP_SAFARI_ZONE_NORTHWEST").group,
|
|
},
|
|
mapsecOf = mapsecOf,
|
|
correct = function(sec) return RegionMap.correctSpecialMapSecId({ session = {} }, sec) end,
|
|
alteringCaveMapSec = mapsecOf(C:map("MAP_ALTERING_CAVE").group, C:map("MAP_ALTERING_CAVE").num),
|
|
alteringCaveId = 0,
|
|
flag = function(id) return flagsSet[id] == true end,
|
|
feebas = man.area.feebas,
|
|
landmarks = man.area.landmarks,
|
|
hiddenSpecies = man.area.hiddenSpecies,
|
|
movingMapSecs = man.area.movingMapSecs,
|
|
NONE = 213,
|
|
}
|
|
for k, v in pairs(extra or {}) do c[k] = v end
|
|
return c
|
|
end
|
|
|
|
local sp = C.species.byName
|
|
local zig = Area.findMapsWithMon(sp.SPECIES_ZIGZAGOON, ctx())
|
|
local secs = {}
|
|
for _, o in ipairs(zig.overworld) do secs[o.sec] = true end
|
|
check(secs[16] and secs[17] and secs[18], "ZIGZAGOON glows on Routes 101-103")
|
|
eq(#zig.special, 0, "ZIGZAGOON has no cave markers")
|
|
local feebas = Area.findMapsWithMon(sp.SPECIES_FEEBAS, ctx())
|
|
local f119 = false
|
|
for _, o in ipairs(feebas.overworld) do if o.sec == 34 then f119 = true end end
|
|
check(f119, "FEEBAS glows on Route 119 (sFeebasData)")
|
|
local wynaut = Area.findMapsWithMon(sp.SPECIES_WYNAUT, ctx())
|
|
eq(#wynaut.overworld + #wynaut.special, 0, "WYNAUT is hidden from the area screen")
|
|
local zubat = Area.findMapsWithMon(sp.SPECIES_ZUBAT, ctx())
|
|
check(#zubat.special > 0, "ZUBAT gets cave markers (" .. #zubat.special .. ")")
|
|
local roamer = Area.findMapsWithMon(sp.SPECIES_LATIAS, ctx({ roamer = { species = sp.SPECIES_LATIAS, active = true,
|
|
group = C:map("MAP_ROUTE120").group, num = C:map("MAP_ROUTE120").num } }))
|
|
eq(#roamer.overworld, 1, "roamer species shows its current map only")
|
|
eq(roamer.overworld[1].sec, 35, "roamer on Route 120")
|
|
|
|
local glow = Area.buildGlowTilemap(zig.overworld, RegionMap.mapSecAt, man.area.glowMapping)
|
|
eq(glow[(13 - 1) * 32 + 5] % 4096, Area.GLOW_TILE_FULL, "Route 101 square is a full glow tile")
|
|
eq(math.floor(glow[(13 - 1) * 32 + 5] / 4096), Area.GLOW_PALETTE, "glow uses palette 10")
|
|
check(glow[(13 - 1) * 32 + 4] ~= 0, "the square left of Route 101 gets an edge tile")
|
|
local g = Area.newGlow(#zig.overworld, 0)
|
|
for _ = 1, 16 do Area.stepGlow(g, function(i) return man.sine[i % 256] end) end
|
|
check(g.eva > 0 and g.evb < 16, "area glow blends in (" .. g.eva .. "," .. g.evb .. ")")
|
|
|
|
local List = require("src.ui.game3.rse.pokedex_list")
|
|
local seen, owned = {}, {}
|
|
for _, n in ipairs({ 252, 253, 263, 265 }) do seen[n], owned[n] = true, true end
|
|
seen[261] = true
|
|
local lctx = {
|
|
orders = orders, nationalEnabled = false, nationalCount = 386,
|
|
seen = function(n) return seen[n] == true end,
|
|
owned = function(n) return owned[n] == true end,
|
|
hoennNumber = function(n)
|
|
for i, v in ipairs(orders.numerical_hoenn) do if v == n then return i end end
|
|
return 203
|
|
end,
|
|
firstChar = function(n) return (n == 252 or n == 253) and 0xCE or 0xD4 end,
|
|
bodyColor = function(n) return (n == 252 or n == 253) and 3 or 5 end,
|
|
types = function(n) return (n == 252 or n == 253) and { 12, 12 } or { 0, 0 } end,
|
|
TYPE_NONE = 0xFF,
|
|
}
|
|
local list = List.create(lctx, List.DEX_MODE_HOENN, List.ORDER_NUMERICAL)
|
|
eq(list.count, 14, "Hoenn numerical list ends at the last seen mon (WURMPLE #014)")
|
|
eq(list.items[2].seen, false, "SCEPTILE unseen in the middle of the list")
|
|
local alpha = List.create(lctx, List.DEX_MODE_HOENN, List.ORDER_ALPHABETICAL)
|
|
eq(alpha.count, 5, "A TO Z lists seen mons only")
|
|
local heavy = List.create(lctx, List.DEX_MODE_HOENN, List.ORDER_HEAVIEST)
|
|
eq(heavy.count, 4, "HEAVIEST lists owned mons only")
|
|
local green = List.search(lctx, List.DEX_MODE_HOENN, List.ORDER_NUMERICAL, 0xFF, 3, 0xFF, 0xFF, man.search.letterRanges)
|
|
eq(green.count, 2, "color GREEN search finds TREECKO and GROVYLE")
|
|
local grass = List.search(lctx, List.DEX_MODE_HOENN, List.ORDER_NUMERICAL, 0xFF, 0xFF, 12, 0xFF, man.search.letterRanges)
|
|
eq(grass.count, 2, "type GRASS search finds owned grass mons")
|
|
|
|
local Pokedex = require("src.ui.game3.rse.pokedex")
|
|
eq(Pokedex.heightText(5):sub(4), "1'08\"", "TREECKO height 1'08\"")
|
|
eq(Pokedex.heightText(5):byte(3), 18, "height uses CLEAR_TO 18 for single-digit feet")
|
|
eq(Pokedex.weightText(50), "{UNK_SPACER}{UNK_SPACER}11.0 lbs.", "TREECKO weight 11.0 lbs. behind two CHAR_SPACERs")
|
|
eq(Pokedex.weightText(3520), "{UNK_SPACER}776.0 lbs.", "a 3-digit weight keeps one CHAR_SPACER")
|
|
|
|
local Cry = require("src.ui.game3.rse.pokedex_cry")
|
|
local tile = {}
|
|
for i = 0, 63 do tile[i] = 1 end
|
|
local c = Cry.new(tile)
|
|
check(c.pixels[28 * 256 + 10] ~= 1, "flatline at y 28 (pokeemerald/src/pokedex_cry_screen.c:390)")
|
|
eq(c.needle.rotation, Cry.MIN_NEEDLE_POS, "needle rests at MIN_NEEDLE_POS")
|
|
|
|
T.finish()
|