Files
gen1recomp/tests/drivers/gold_phone_caller_box.lua
bryanthaboi ae6cac89e1 G2 support
2026-08-11 11:53:30 -04:00

129 lines
4.5 KiB
Lua

-- The caller-ID box an incoming call puts across the top of the screen:
-- Phone_TextboxWithName (pokegold engine/phone/phone.asm:582), reached from
-- RingTwice_StartCall's .CallerTextboxWithName (:466, :474).
--
-- Three shots, because the whole bug was "there is no box at all" and only a
-- picture can answer that:
--
-- 01-ring.png the ring, box up, naming who is calling
-- 02-talking.png the caller's own script talking UNDER the box
-- 03-after.png the call over, box gone, overworld clean
--
-- POKEPORT_GAME=gold POKEPORT_DRIVER=tests/drivers/gold_phone_caller_box.lua love .
-- POKEPORT_SHOT_DIR=/tmp/gold-callerbox (default)
--
-- The assertions cover the same ground for a run nobody is looking at: the box
-- is on the stack while the call runs, it is UNDER the text pages rather than
-- over them, and it is off the stack once the script has ended (a box left
-- behind would sit on the overworld forever -- it has no `update`, so nothing
-- would ever take it down).
local U = require("tests.drivers.util")
local Phone = require("src.core.gen2.Phone")
-- The tag src/script/gen2/CallAsm.lua marks the pushed state with.
local CALLER_BOX = "gen2CallerBox"
return function(game)
local out = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/gold-callerbox"
local failures = 0
local function ok(label, condition, detail)
if condition then
print("[callerbox] ok " .. label)
else
failures = failures + 1
print("[callerbox] FAIL " .. label .. " " .. tostring(detail))
end
end
-- Index of the caller box on the stack, or nil.
local function boxIndex()
for index, state in ipairs(game.stack.states or {}) do
if state[CALLER_BOX] then return index end
end
return nil
end
U.wait(45)
local world = game.world
assert(world and world.map, "gold world did not boot")
local save = game.save
game.clock = { day = 0, hour = 9, minute = 0 }
save.phone = nil
assert(world:setMap("ROUTE_31", 8, 6, "down"), "setMap failed for ROUTE_31")
U.wait(3)
-- CheckStandingOnEntrance refuses a call on a door tile, so stand on floor.
local cx, cy = world.player.cellX, world.player.cellY
for y = 2, 16 do
for x = 2, 16 do
if world.map:cellCollision(x, y) == 0x00 then cx, cy = x, y end
end
end
assert(world:setMap("ROUTE_31", cx, cy, "down"), "no floor cell on ROUTE_31")
U.wait(3)
ok("no caller box before the phone rings", boxIndex() == nil, boxIndex())
Phone.addContact(save, 15) -- Joey, ROUTE_30, reachable from ROUTE_31
-- Wind the clock forward twenty in-game minutes at a time until
-- CheckReceiveCallTimer lands a random call.
local rang = false
for _ = 1, 40 do
game.clock.minute = game.clock.minute + 20
for _ = 1, 20 do
U.wait(1)
if world:busy() then break end
end
if world:busy() then rang = true break end
end
ok("a call rang in the overworld", rang)
if not rang then
print("FAIL gold_phone_caller_box (no call)")
love.event.quit(1)
return
end
-- The box goes up on the FIRST ring; the ring page only arrives after the
-- second pass, three Phone_Wait20Frames later (engine/phone/phone.asm:576),
-- so wait for the page rather than for a fixed count -- then let it type.
for _ = 1, 300 do
if #game.stack.states > 1 then break end
U.wait(1)
end
U.wait(40)
local ringIndex = boxIndex()
ok("the caller box is up during the ring", ringIndex ~= nil)
ok("and sits UNDER the ring's text page",
ringIndex ~= nil and ringIndex < #game.stack.states,
ringIndex and (ringIndex .. " of " .. #game.stack.states))
U.shot(game, out .. "/01-ring.png")
-- Into the caller's own script. One A gets past the ring page; the shot is
-- taken with a page of Joey's chatter up, which is what the player sees for
-- most of a call.
U.tap(game, "a")
U.wait(40)
ok("the box survives into the call itself", boxIndex() ~= nil)
U.shot(game, out .. "/02-talking.png")
-- Now page through to the end: the hang-up Click!, then the tail rows.
local finished = false
for _ = 1, 400 do
if not world:busy() and boxIndex() == nil then finished = true break end
U.tap(game, "a")
U.wait(4)
end
ok("the call ran to the end", finished, world:busy())
ok("and InitCallReceiveDelay took the caller box down",
boxIndex() == nil, boxIndex())
U.wait(10)
U.shot(game, out .. "/03-after.png")
print(failures == 0 and "PASS gold_phone_caller_box"
or ("FAIL gold_phone_caller_box (%d)"):format(failures))
love.event.quit(failures == 0 and 0 or 1)
end