mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-06 17:10:55 -04:00
41935aa2a2
Second batch of the Gen 3 review work: the review lanes closed their queues and the test gate grew with them. Review census: 139 routed findings -- 118 fixed, 14 invalid (the report had Gen 4+ semantics in more than one place), 6 struck as stale after re-verification, 1 re-routed. Every fix carries its own pret citation in docs/game3/review-v3-triage.md; the E10 opcode closure is itemised in docs/game3/e10-opcode-spec.md (18 ops wired, 2 reclassified to the seam class). Representative ROM-grounded changes: - The POKéMON start-menu entry is now gated on FLAG_SYS_POKEMON_GET the way retail does it (pokefirered/src/start_menu.c:217-218, flag 0x828). - Money ops read their amount raw and gate the change on the disable byte (pokefirered/src/scrcmd.c:1798-1830, pokefirered/asm/macros/event.inc:1166-1186); random and the warp family VarGet theirs (pokefirered/src/scrcmd.c:455-461, :719-731). - The HM table matches FRLG: there is no Whirlpool HM (pokefirered/include/constants/items.h:411-418). - The day-care party-full guard follows src/daycare.c:525, :1081. - Knock Off keeps its battle-scoped send-out mask (pokefirered/src/battle_script_commands.c:2730-2752, :4489), carried from the first batch. Structural work: the I6/I9/J1 architecture items landed as seams (profile selector, capability flags, font provider, virtual-object layer), the adopted footprint register keeps a KEEP verdict, the quantizer target is met, and the 30 drain items plus carves 1-4 are folded in. Tests: T6 now runs 282 top-level suites (273 + 9 new), the re-sweep ends at 267 pass / 0 fail, the engine tier is 634 suites, modkit 37, and the full gate ran green twice with T3 active on an imported Red cache. Documented skips are the lua5.4 oversize-save oracle where lua5.4 is absent and the config-partials listed in docs/game3/game3-artifact-conversions-v3.md. Docs shipped: review-v3-triage.md, e10-opcode-spec.md, rse-seams.md, game3-suite-sweep-v113.md, game3-artifact-conversions-v3.md, test-baseline-v3.md (plus the first-batch docs already on the branch).
119 lines
5.6 KiB
Lua
119 lines
5.6 KiB
Lua
-- I9 import/world seam (review-v3 row I9): native_pack classified COLL bytes
|
|
-- through src/world/gen2/Permissions, i.e. an import module reaching into the
|
|
-- world layer. The byte vocabulary now lives in src/core/CollPermissions.lua
|
|
-- and Permissions re-exports it. This suite proves (1) the edge is gone, (2) the
|
|
-- two modules answer identically for every byte, and (3) the import path
|
|
-- NativePack.resolveLayoutColl behaves exactly as before on all four branches.
|
|
-- luajit tests/engine/game3_coll_permissions_test.lua
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
|
|
local Coll = require("src.core.CollPermissions")
|
|
local Permissions = require("src.world.gen2.Permissions")
|
|
local NativePack = require("src.import.gba.native_pack")
|
|
|
|
local function sourceOf(rel)
|
|
local f = io.open(rel, "r")
|
|
if not f then return nil end
|
|
local s = f:read("*a")
|
|
f:close()
|
|
return s
|
|
end
|
|
|
|
-- ------------------------------------------------------- the boundary itself
|
|
|
|
do
|
|
local pack = sourceOf("src/import/gba/native_pack.lua")
|
|
check(pack ~= nil, "native_pack.lua is readable")
|
|
check(pack:find('require("src.world', 1, true) == nil,
|
|
"native_pack no longer requires anything under src/world (I9 edge removed)")
|
|
|
|
local neutral = sourceOf("src/core/CollPermissions.lua")
|
|
check(neutral ~= nil, "CollPermissions.lua is readable")
|
|
check(neutral:find("require(", 1, true) == nil,
|
|
"CollPermissions has no requires at all (neutral module)")
|
|
check(neutral:find("src.world", 1, true) == nil, "CollPermissions never mentions src.world")
|
|
|
|
local island = sourceOf("src/import/gba/extract_island1.lua")
|
|
check(island ~= nil and island:find('require("src.world', 1, true) == nil,
|
|
"extract_island1 still has no src.world require (the edge was not moved here)")
|
|
|
|
local perms = sourceOf("src/world/gen2/Permissions.lua")
|
|
check(perms ~= nil and perms:find("local TABLE", 1, true) == nil,
|
|
"the permission table no longer lives in the gen2 world module")
|
|
end
|
|
|
|
-- ------------------------------------------- equivalence (byte-for-byte proof)
|
|
|
|
eq(Coll.LAND, Permissions.LAND, "LAND matches")
|
|
eq(Coll.WATER, Permissions.WATER, "WATER matches")
|
|
eq(Coll.WALL, Permissions.WALL, "WALL matches")
|
|
check(Permissions.of == Coll.of, "Permissions.of is the re-exported function")
|
|
check(Permissions.isWalkable == Coll.isWalkable, "isWalkable is re-exported")
|
|
check(Permissions.isLedge == Coll.isLedge, "isLedge is re-exported")
|
|
|
|
local mismatches = 0
|
|
local cases = { -1, -256, 0 }
|
|
for b = 0, 255 do cases[#cases + 1] = b end
|
|
cases[#cases + 1] = 256
|
|
cases[#cases + 1] = 257
|
|
cases[#cases + 1] = 0x1FF
|
|
for _, c in ipairs(cases) do
|
|
if Coll.of(c) ~= Permissions.of(c) then mismatches = mismatches + 1 end
|
|
if Coll.isWalkable(c) ~= Permissions.isWalkable(c) then mismatches = mismatches + 1 end
|
|
if Coll.isLedge(c) ~= Permissions.isLedge(c) then mismatches = mismatches + 1 end
|
|
if Coll.isLand(c) ~= Permissions.isLand(c) then mismatches = mismatches + 1 end
|
|
if Coll.isWater(c) ~= Permissions.isWater(c) then mismatches = mismatches + 1 end
|
|
if Coll.isWall(c) ~= Permissions.isWall(c) then mismatches = mismatches + 1 end
|
|
end
|
|
-- nil never reaches ipairs, so compare it explicitly.
|
|
if Coll.of(nil) ~= Permissions.of(nil) then mismatches = mismatches + 1 end
|
|
if Coll.isWalkable(nil) ~= Permissions.isWalkable(nil) then mismatches = mismatches + 1 end
|
|
if Coll.isLedge(nil) ~= Permissions.isLedge(nil) then mismatches = mismatches + 1 end
|
|
eq(mismatches, 0, "CollPermissions and Permissions agree on every tested byte")
|
|
|
|
-- ----------------------------------------- spot semantics from the moved table
|
|
|
|
eq(Coll.of(0), Coll.LAND, "coll 0 is LAND")
|
|
check(Coll.isWalkable(0) == true, "coll 0 is walkable")
|
|
eq(Coll.of(0x07), Coll.WALL, "coll 0x07 is WALL (row 1, index 8)")
|
|
check(Coll.isWalkable(0x07) == false, "a wall is not walkable")
|
|
eq(Coll.of(0x20), Coll.WATER, "coll 0x20 is WATER")
|
|
check(Coll.isWalkable(0x20) == false, "water is not walkable on foot")
|
|
check(Coll.isLedge(0xa0) == true, "0xa0 is a ledge tile")
|
|
eq(Coll.of(0xa0), Coll.LAND, "a ledge tile is LAND in the permission table")
|
|
check(Coll.isLedge(0x9f) == false, "0x9f is not a ledge")
|
|
check(Coll.isLedge(0xb0) == false, "0xb0 is not a ledge")
|
|
eq(Coll.of(nil), Coll.WALL, "nil reads as WALL")
|
|
eq(Coll.of(-1), Coll.WALL, "negative reads as WALL")
|
|
check(Coll.isLedge(nil) == false, "nil is not a ledge")
|
|
|
|
-- The gen2-specific half of Permissions still works off the re-exported of().
|
|
eq(Permissions.surfable(0x20), "water", "surfable still answers water (Permissions.of re-export)")
|
|
eq(Permissions.surfable(0), "land", "surfable still answers land")
|
|
check(type(Permissions.ledgeFacings(0xa0)) == "table",
|
|
"ledgeFacings still resolves (LEDGE_FACINGS + isLedge)")
|
|
|
|
-- --------------------------------- the import path, all four branches, unchanged
|
|
|
|
local Seed = require("src.core.game3.scripting.collision")
|
|
local seeded = Seed.seed("BLOCKED")
|
|
|
|
eq(NativePack.resolveLayoutColl(5, 0, false), 5,
|
|
"mapColl 0: the layout's coll passes through (branch 1)")
|
|
eq(NativePack.resolveLayoutColl(0xa0, 1, false), 0xa0,
|
|
"a ledge keeps its layout coll (branch 2)")
|
|
eq(NativePack.resolveLayoutColl(0x60, 1, true), 0x60,
|
|
"a warp cell keeps its layout coll (branch 3, pokefirered field_control_avatar.c:987)")
|
|
eq(NativePack.resolveLayoutColl(0x07, 1, false), 0x07,
|
|
"a non-walkable layout coll keeps itself (branch 4)")
|
|
eq(NativePack.resolveLayoutColl(0, 1, false), seeded,
|
|
"a walkable layout coll under a blocking map coll seeds BLOCKED (branch 5)")
|
|
eq(NativePack.resolveLayoutColl(0, 1, true), seeded,
|
|
"0x00 is not in the warp range, so it still seeds")
|
|
|
|
T.finish("game3_coll_permissions_test")
|