Files
2026-08-04 12:32:23 -04:00

132 lines
5.8 KiB
Lua

-- Driver: import a Stadium ROM through the OPTIONS row, with the modal file
-- dialog stubbed out.
--
-- Everything except the dialog itself is the real path: the row is built the
-- way the OPTIONS menu builds it, its step() is pressed, StadiumRomPick reads
-- the file with io.open (love.filesystem cannot see an absolute path),
-- StadiumInstall builds from those bytes, and the loading screen goes up over
-- whatever asked. A modal dialog cannot be driven, so choose() is replaced
-- with the answer a player would have given it.
return function(game)
local U = dofile("tests/drivers/util.lua")
local DIR = os.getenv("SHOT_DIR") or ".scratchpad"
local lib = game.mods.exports.DRAMATIC_SHAPE.lib
local Pick = lib.require("StadiumRomPick")
local Install = lib.require("StadiumInstall")
local Pack = lib.require("StadiumPack")
local Battles = lib.require("OverworldBattle")
U.teleport(game, "ROUTE_1", 5, 8, "down")
U.wait(30)
-- FIRST let the automatic first-run build finish. A ROM is sitting in
-- baseroms/ in this checkout, so StadiumScreen.maybePush has already pushed
-- a loading screen and started one -- and import() refuses to start a
-- second while that runs, so every step below would silently no-op against
-- it. maybePush asks ONCE per boot, so once this is drained it stays
-- drained and the purge below cannot be undone behind our backs.
local drain = 0
while (Install.pending() or Install.status.state == "building")
and drain < 5400 do
U.wait(10); drain = drain + 10
end
while game.stack:top() and game.stack:top() ~= game.overworld do
U.wait(10)
end
U.log(("drained the automatic first-run build in %d frames"):format(drain))
-- back to a machine that has never built them, whatever earlier runs left
for _, name in ipairs(love.filesystem.getDirectoryItems(Pack.CACHE_DIR)) do
love.filesystem.remove(Pack.CACHE_DIR .. "/" .. name)
end
Install.forget()
Pack.forget()
local function settle(what)
local waited = 0
while Install.status.state == "building" and waited < 5400 do
U.wait(10)
waited = waited + 10
end
U.log(("%s: %d frames (%.1fs) -- state=%s error=%s")
:format(what, waited, waited / 60, tostring(Install.status.state),
tostring(Install.status.error)))
return waited
end
U.log(("picker available on this platform: %s"):format(
tostring(Pick.available())))
U.log(("BEFORE: models available = %s, 3D-BTL offers %d rungs")
:format(tostring(Install.available()), Battles.setting:rungs()))
local row = Pick.row()
if not row then U.log("no import row on this platform") return end
U.log(("row reads: %s = %s"):format(row.label, row.value()))
-- ------- the wrong file first, because a refusal must not leave a mess
U.log("-- picking a file that is not a Stadium ROM --")
Pick.choose = function() return "/not/a/real/path.z64" end
local realRead = Pick.read
Pick.read = function() return ("\x80\x37\x12\x40"):rep(4096) end
row.step(game)
settle("wrong file")
U.shot(game, ("%s/import_1_refused.png"):format(DIR))
U.log((" still not installed: %s, row still reads %s")
:format(tostring(not Install.available()), row.value()))
U.wait(300) -- let the failure notice time out and pop itself
-- ------- and now the real one
U.log("-- picking the real ROM --")
Pick.read = realRead
local abs = love.filesystem.getWorkingDirectory() .. "/baseroms/baserom.z64"
local picked = false
Pick.choose = function() picked = true return abs end
Install.status.state = "idle"
row.step(game)
U.log((" choose() called: %s, state = %s, loading screen on top: %s")
:format(tostring(picked), tostring(Install.status.state),
tostring(game.stack:top() ~= game.overworld)))
U.wait(30)
U.shot(game, ("%s/import_2_building.png"):format(DIR))
settle("real ROM")
U.wait(120)
U.log(("AFTER: models available = %s, 3D-BTL offers %d rungs, row reads %s")
:format(tostring(Install.available()), Battles.setting:rungs(),
row.value()))
Battles.setting:setValue("stadium", game)
U.log((" and 3D-BTL can now be set to STADIUM A: %s")
:format(tostring(Battles.setting:get() == "stadium")))
-- and the ROM was NOT copied anywhere: the only baserom physfs can see is
-- the one in the game folder this checkout already had, never a copy in
-- the save directory (which is where a mod's writes land)
local where = love.filesystem.getRealDirectory("baseroms/baserom.z64")
U.log((" the only ROM on the read path is the game folder's own: %s (%s)")
:format(tostring(where == love.filesystem.getWorkingDirectory()),
tostring(where)))
U.log((" the save directory has no baseroms folder: %s")
:format(tostring(love.filesystem.getInfo(
love.filesystem.getSaveDirectory() .. "/baseroms") == nil)))
-- ------- and the wrong file, now that a GOOD set is installed
--
-- The serious case. The marker is the only thing that makes 151 files on
-- disk count as installed, so a refusal that writes one anyway would
-- UNINSTALL a working set -- and the player would have pressed a row called
-- STADIUM ROM, picked the wrong file, and lost the models they already had.
U.log("-- picking the wrong file again, with models already installed --")
Pick.read = function() return ("€7@"):rep(4096) end
Install.status.state = "idle"
row.step(game)
settle("wrong file over a good install")
U.wait(300)
Install.forget()
Pack.forget()
U.log((" the good install SURVIVED: %s, row reads %s, 3D-BTL offers %d rungs")
:format(tostring(Install.available()), row.value(),
Battles.setting:rungs()))
U.log((" and a real model still loads: %s")
:format(tostring(Pack.load(25) ~= nil)))
U.log("done -- " .. DIR)
end