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.
59 lines
2.4 KiB
Lua
59 lines
2.4 KiB
Lua
-- The givemon opcode must consume the pret operand layout.
|
|
--
|
|
-- Regression: opcodes.lua declared
|
|
-- [0x79] = op("givemon", 9, { H, B, H, H, H })
|
|
-- but pret (asm/macros/event.inc) is
|
|
-- .byte 0x79 / .2byte species / .byte level / .2byte item / .4byte 0 / .4byte 0 / .byte 0
|
|
-- i.e. two WORDS where the port had two halves -- 14 operand bytes after the
|
|
-- opcode, not 9. disasm.decodeOne iterates def.args (the size field is unused)
|
|
-- and extract_scripts decodes a script linearly, so every command after a
|
|
-- givemon was misaligned and baked into the dataset with wrong operands.
|
|
--
|
|
-- Disasm.decodeOne takes a 1-based array of byte values (not a string).
|
|
-- luajit tests/engine/game3_givemon_opcode_layout_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")
|
|
|
|
local Disasm = require("src.core.game3.scripting.disasm")
|
|
local Opcodes = require("src.core.game3.scripting.opcodes")
|
|
|
|
local function push8(t, v) t[#t + 1] = v % 256 end
|
|
local function push16(t, v) push8(t, v % 256); push8(t, math.floor(v / 256) % 256) end
|
|
local function push32(t, v) push16(t, v % 65536); push16(t, math.floor(v / 65536) % 65536) end
|
|
|
|
-- opcode, species 25, level 10, item 13, two words, trailing byte
|
|
local stream = {}
|
|
push8(stream, 0x79)
|
|
push16(stream, 25)
|
|
push8(stream, 10)
|
|
push16(stream, 13)
|
|
push32(stream, 0x11223344)
|
|
push32(stream, 0x55667788)
|
|
push8(stream, 0)
|
|
|
|
local row, nextIdx = Disasm.decodeOne(stream, 1)
|
|
eq(row.op, "givemon", "the opcode decodes as givemon")
|
|
eq(nextIdx, 16, "givemon consumes 15 bytes: opcode + the pret operand layout")
|
|
eq(row[1], 25, "species")
|
|
eq(row[2], 10, "level")
|
|
eq(row[3], 13, "item")
|
|
eq(row[4], 0x11223344, "the first word operand")
|
|
eq(row[5], 0x55667788, "the second word operand")
|
|
eq(row[6], 0, "the trailing byte operand")
|
|
|
|
-- The desync: the command after a givemon must still decode.
|
|
push8(stream, 0x02) -- 0x02 = end
|
|
local _, afterGivemon = Disasm.decodeOne(stream, 1)
|
|
local following = Disasm.decodeOne(stream, afterGivemon)
|
|
eq(following.op, "end", "the command after givemon decodes (no stream desync)")
|
|
|
|
-- The declared size must agree with the argument list: every other entry adds
|
|
-- the opcode byte to its args (addvar is 5 for two halves).
|
|
eq(Opcodes.get(0x79).size, 15, "the declared size includes the opcode byte")
|
|
|
|
T.finish("game3_givemon_opcode_layout_test")
|