mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
2c356f28ea
The rest of the Gen 3 review fixes, each with a gated suite in tests/engine/.
ROM semantics were checked against pret/pokefirered.
Scripts
- givemon carried the wrong operand layout, found earlier; four more layout
desyncs came out of pret asm/macros/event.inc: comparestat is {byte,word},
and setptr / loadbytefromptr / setptrbyte each carry a leading byte plus a
word. A wrong size mis-decodes every instruction after the bad one, so
Versions.CACHE_VERSION moves to 113 and existing caches re-import.
- handlers for previously handler-less verbs: comparestat,
bufferitemnameplural, setmonmove, setmonmetlocation, the modern
fateful-encounter pair, the script-locals family (copylocal, setptr,
loadbytefromptr, setptrbyte, copybyte, compare_local_to_* and
compare_ptr_to_*), the RAM-script family (setvaddress, vgoto, vcall,
vgoto_if, vcall_if, vmessage, vbuffermessage, vbufferstring, endram,
returnram) and the same-map forms of the *at verbs.
- setdooropen / setdoorclosed read their coordinates through VarGet.
Battles
- Knock Off and Thief / Trick persist the item change instead of only
touching the in-battle copy.
- knocked-off party slots are tracked in a bitmask, so a slot reused later
does not inherit the flag.
Field and UI
- Player.reset restores facing and clears the surf flags.
- a definition-less Map.load no longer leaves collision unbound.
- an unresolved region-map section no longer reports PALLET TOWN.
- the naming screen splits input from the timer, so update(dt) stops
indexing a number.
- the hall of fame commits through the engine save path and serializes its
fields.
Persistence
- gameStats, the link-battle records and the trainer card are serialized.
- the PC deposit refuses at the 999 cap instead of destroying the overflow.
Robustness
- Data.load runs cached modules sandboxed.
- the file browser quotes shell arguments.
- .meta dimensions are bounds-checked and mids.idx validates its header.
61 lines
2.4 KiB
Lua
61 lines
2.4 KiB
Lua
-- Generated cache modules must load without access to the process API.
|
|
--
|
|
-- L1 regression: Data's cache loader used
|
|
-- loadstring(bytes, "@" .. prefix .. path)
|
|
-- with no environment, so any file at <save dir>/data/generated/<name>.lua ran
|
|
-- at boot with the real `os`, `io` and `loadfile` in scope -- local code
|
|
-- execution from a directory the game treats as data. Every other generated
|
|
-- loader in the engine sandboxes (dataset.lua, doors.lua, field.lua, ... all use
|
|
-- load(src, name, "t", {})), and LuaWriter only ever emits literals, so the
|
|
-- module format has no need for globals.
|
|
-- luajit tests/engine/game3_cache_module_sandbox_test.lua
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
love = love or require("tests.love_stub")
|
|
|
|
-- A generated module that reports whether the process API is reachable.
|
|
local HOSTILE = [[
|
|
if os ~= nil or io ~= nil or require ~= nil or loadfile ~= nil or loadstring ~= nil then
|
|
return "ESCAPED"
|
|
end
|
|
return "sandboxed"
|
|
]]
|
|
|
|
package.preload["src.import.CacheFs"] = function()
|
|
return { readActive = function() return HOSTILE end }
|
|
end
|
|
package.preload["src.core.GameVersion"] = function()
|
|
return { cachePrefix = function() return "red/" end }
|
|
end
|
|
|
|
local Data = require("src.core.Data")
|
|
|
|
check(type(Data._loadModule) == "function", "Data exposes its cache loader as a seam")
|
|
if type(Data._loadModule) == "function" then
|
|
local called, ok, res = pcall(Data._loadModule, nil, "pokemon")
|
|
check(called and ok, "the cache module loads through the sandbox")
|
|
eq(res, "sandboxed", "a generated module cannot reach os/io/require/loadfile")
|
|
end
|
|
|
|
-- Real generated data must survive the sandbox: fixture modules are written in
|
|
-- the same literal-only format LuaWriter emits, so one must compile and evaluate
|
|
-- to its table under the sandbox expression the loader now uses.
|
|
do
|
|
local f = io.open("tests/fixture_data/pokemon.lua", "r")
|
|
check(f ~= nil, "a fixture generated module is readable")
|
|
if f then
|
|
local src = f:read("*a")
|
|
f:close()
|
|
local chunk = load(src, "@tests/fixture_data/pokemon.lua", "t", {})
|
|
check(chunk ~= nil, "a real generated module compiles under the sandbox")
|
|
if chunk then
|
|
local okEval, mod = pcall(chunk)
|
|
check(okEval and type(mod) == "table", "...and evaluates to its table")
|
|
end
|
|
end
|
|
end
|
|
|
|
T.finish("game3_cache_module_sandbox_test") |