mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
96 lines
4.0 KiB
Lua
96 lines
4.0 KiB
Lua
-- Real-time check of the credits roll vs Music_Credits (#703).
|
|
-- The song is a fixed 5880-frame program (audio/music/credits.asm: tempo 140,
|
|
-- no loop), so on hardware it outlasts THE END by ~12s. Our roll ran 135
|
|
-- frames short of pokered because Credits:update skipped DisplayCreditsMon's
|
|
-- three CreditsCopyTileMapToVRAM calls (each `jp Delay3`, 9 frames per mon
|
|
-- screen, 15 mon screens); that stretched the overhang to ~14.3s and made the
|
|
-- music look too fast. This driver plays the whole roll in real time (~98s,
|
|
-- do NOT set POKEPORT_SPEED: the ear half needs the real clock), counts the
|
|
-- fixed frames itself, and leaves the screen on THE END with the theme still
|
|
-- going so a listener can judge the tail.
|
|
-- SHOT_DIR=/tmp/shots POKEPORT_DRIVER=tests/drivers/credits_overhang_bug703_test.lua POKEPORT_IDENTITY=bug703 POKEPORT_TOUCH=0 love .
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
|
|
local function check(label, ok)
|
|
U.log(ok and "PASS" or "FAIL", label)
|
|
return ok
|
|
end
|
|
|
|
if os.getenv("POKEPORT_SPEED") then
|
|
U.log("warning: POKEPORT_SPEED is set; the listening half of this run",
|
|
"is meaningless at any speed but 1")
|
|
end
|
|
local opts = game.save and game.save.options
|
|
if opts and opts.musicVolume == 0 then
|
|
U.log("warning: options music volume is 0, nothing will be audible")
|
|
end
|
|
|
|
-- the roll ends in an autosave; put the user's save back afterwards
|
|
local prevSave = love.filesystem.read("save.lua")
|
|
|
|
U.teleport(game, "HALL_OF_FAME", 4, 2, "right")
|
|
game.save.party = { { species = "PIKACHU", level = 81 } }
|
|
game.overworld.runner:run({ { "record_hall_of_fame" } })
|
|
U.wait(2)
|
|
|
|
-- A through the induction until the credits state is on top; the full
|
|
-- hall-of-fame walk takes well over 60 taps, so give it real room
|
|
local Credits = require("src.ui.Credits")
|
|
local credits
|
|
for _ = 1, 2000 do
|
|
local top = game.stack:top()
|
|
if getmetatable(top) == Credits then credits = top break end
|
|
U.tap(game, "a")
|
|
U.wait(2)
|
|
end
|
|
if not check("credits state reached", credits ~= nil) then
|
|
while true do coroutine.yield() end
|
|
end
|
|
|
|
-- Frame accounting, one fixed step per sample. From the frame Music_Credits
|
|
-- starts (phase leaves "white") pokered reaches the end of THE END's fade at
|
|
-- 128 + 35 screens + 16 + 20 = 5154 frames; the 15 mon screens each spend
|
|
-- 9 frames in mon_prep (the Delay3 x3) before their 27-frame wipe.
|
|
-- no screenshots inside this loop: U.shot yields extra fixed steps of its
|
|
-- own and would silently skew the count
|
|
local musicStart, theEndAt, prepFrames = nil, nil, 0
|
|
for f = 1, 7000 do
|
|
U.wait(1)
|
|
local phase = credits.phase
|
|
if not musicStart and phase ~= "white" then musicStart = f end
|
|
if phase == "mon_prep" then prepFrames = prepFrames + 1 end
|
|
if phase == "end_hold" then theEndAt = f break end
|
|
end
|
|
|
|
check("mon_prep ran 9 frames on each of the 15 mon screens (135 total)",
|
|
prepFrames == 135)
|
|
check("THE END finishes fading 5154 frames after the music starts",
|
|
musicStart ~= nil and theEndAt ~= nil
|
|
and theEndAt - musicStart == 5154)
|
|
U.log("music started at driver frame", musicStart,
|
|
"THE END done at", theEndAt, "mon_prep frames", prepFrames)
|
|
U.shot(game, DIR .. "/bug703_the_end.png")
|
|
|
|
-- Music_Credits is 5880 frames long, so from here the theme has
|
|
-- 5880 - 5154 = 726 frames (~12.1s) left. That overhang is authentic:
|
|
-- the original does the same on hardware, and this fix only removed the
|
|
-- extra 2.2s our shortened roll had added on top of it.
|
|
U.log("listen: the theme should keep playing about 12 seconds past this")
|
|
U.wait(726)
|
|
U.log("the song should be ending right about now; silence after this",
|
|
"point is correct, the program has no loop")
|
|
U.wait(120)
|
|
|
|
if prevSave then
|
|
love.filesystem.write("save.lua", prevSave)
|
|
else
|
|
love.filesystem.remove("save.lua")
|
|
end
|
|
U.log("done; screen stays on THE END (A or B would soft-reset)")
|
|
while true do
|
|
coroutine.yield()
|
|
end
|
|
end
|