Files
gen1recomp/tests/engine/gen2_menu_whites_s6.lua

211 lines
7.6 KiB
Lua

-- ../pokecrystal/home/map.asm:1910-1940
-- ../pokecrystal/engine/menus/start_menu.asm:444-518
package.path = "./?.lua;./?/init.lua;" .. package.path
love = love or require("tests.love_stub")
local T = require("tests.harness")
local eq, check = T.eq, T.check
local MenuFade = require("src.ui.gen2.MenuFade")
local World = require("src.world.gen2.World")
local StateStack = require("src.core.StateStack")
local Game2 = require("src.core.Game2")
local function newStack()
local stack = setmetatable({}, { __index = StateStack })
stack:init()
return stack
end
do
eq(MenuFade.OUT_FRAMES, 8,
"FadeToMenu -> FadeOutToWhite: 4 entries x DelayFrames 2 = 8")
eq(MenuFade.OUT_WHITE_FRAMES, 2,
"of which entry 6 (every index -> colour 0, white) is the last 2")
eq(MenuFade.IN_RAMP_FRAMES, 6,
"FadeInFromWhite entries 5, 4, 3 at 2 frames each after the white")
eq(MenuFade.PARTY_FONT_FRAMES, 3,
"LoadPartyMenuGFX -> _LoadFontsBattleExtra: Get2bppViaHDMA 25 tiles then"
.. " LoadFrame's 6 and 1, one DelayFrame each with the LCD on")
eq(MenuFade.PARTY_WHITE, 11,
"StartMenu_Pokemon: .choosemenu ClearBGPalettes 4 + the font's 3"
.. " + WaitBGMap 4 = 11; the DelayFrame at :518 is the colour latch")
eq(MenuFade.PARTY_ICON_FRAMES, 3,
"InitPartyMenuGFX: GetIconGFX 8 tiles 2 + HeldItemIcons 2 tiles 1 per mon")
eq(MenuFade.openWhite("pokemon", 6), 11 + 18, "six mons: 29")
eq(MenuFade.PACK_WHITE, 16,
"Pack_InitGFX: ClearBGPalettes 4 + ClearTilemap 4 + LCD off 2"
.. " + DrawPackGFX 15 tiles 2 + Pack_InitColors WaitBGMap 4 = 16")
eq(MenuFade.GEAR_WHITE, 20,
"PokeGear.InitTilemap: ClearBGPalettes 4 + ClearTilemap 4 + LCD off 5"
.. " + InitPokegearTilemap.UpdateBGMap 3 + 4 = 20")
eq(MenuFade.CARD_WHITE, 14,
"TrainerCard.InitRAM: ClearBGPalettes 4 + ClearTilemap 4 + LCD off 2"
.. " + WaitBGMap 4 = 14; the second WaitBGMap latches the colour")
eq(MenuFade.DEX_WHITE, 27,
"InitPokedex: ClearBGPalettes 4 + ClearTilemap 4 + LCD off 6 + DelayFrame 1"
.. " + SetBGMapMode 4 then 3 for 8 + WaitBGMap 4 = 27")
eq(MenuFade.OPTION_WHITE, 8, "_Option: ClearBGPalettes 4 + WaitBGMap 4 = 8")
eq(MenuFade.openWhite("save"), nil, "SAVE draws over the map, no fade")
eq(MenuFade.openWhite("mods"), nil, "and MODS is not a cart page")
eq(MenuFade.exitWhite(), World.MENU_EXIT_WHITE_FRAMES,
"CloseSubmenu shares ExitAllMenus' count")
eq(MenuFade.closeWhite("pack"), 23,
"CloseSubmenu: ClearBGPalettes 4 + reload 9 + WaitBGMap2 8 + entry 6 for 2")
eq(MenuFade.closeWhite("pokegear"), 27,
"PokeGear.done's own ClearBGPalettes 4 ahead of CloseSubmenu's 23")
eq(MenuFade.closeWhite("status"), 23, "the card returns straight into it")
eq(MenuFade.closeWhite("save"), nil, "SAVE closes with no white")
end
do
local stack = newStack()
local game = { stack = stack, world = {} }
local fired = 0
local fade = MenuFade.new(game, { kind = "out", white = 16,
onDone = function() fired = fired + 1 end })
stack:push(fade)
local want = { .25, .25, .5, .5, .75, .75, 1, 1 }
local levels = { fade:level() }
for _ = 1, 8 + 16 - 1 do
fade:update()
levels[#levels + 1] = fade:level()
end
eq(#levels, 24, "the PACK fade is 8 + 16 = 24 drawn frames")
for i = 1, 8 do
eq(levels[i], want[i], ("ramp frame %d at %.2f"):format(i, want[i]))
end
local white = 0
for i = 1, #levels do if levels[i] >= 1 then white = white + 1 end end
eq(white, 2 + 16, "18 of them white: entry 6's 2 plus the pack's 16")
eq(fired, 0, "the page is not up yet")
eq(stack:top(), fade, "and the fade still owns the stack")
fade:update()
eq(fired, 1, "the 24th update hands over")
eq(stack:top(), nil, "after popping itself")
fade:update()
eq(fired, 1, "...once")
end
do
local stack = newStack()
local game = { stack = stack, world = {} }
local fade = MenuFade.new(game, { kind = "in", white = 23 })
stack:push(fade)
local levels = { fade:level() }
for _ = 1, 23 + 6 - 1 do
fade:update()
levels[#levels + 1] = fade:level()
end
eq(#levels, 29, "CloseSubmenu: 23 white + 6 ramp = 29 drawn frames")
for i = 1, 23 do
check(levels[i] >= 1, ("frame %d white"):format(i))
end
local ramp = { .75, .75, .5, .5, .25, .25 }
for i = 1, 6 do
eq(levels[23 + i], ramp[i], ("ramp frame %d at %.2f"):format(i, ramp[i]))
end
eq(stack:top(), fade, "still up on the last ramp frame")
fade:update()
eq(stack:top(), nil, "the 29th update pops it")
end
do
local stack = newStack()
local pushed = {}
local game = setmetatable({
stack = stack, world = {}, data = {},
save = { party = { {}, {} } },
}, { __index = Game2 })
game.pushStartMenuItem = function(_, id) pushed[#pushed + 1] = id end
game:openStartMenuItem("pokemon")
local fade = stack:top()
eq(fade and fade.screenId, "Gen2MenuFade", "POKEMON opens on the fade")
eq(fade.kind, "out", "outward")
eq(fade.white, 11 + 3 * 2, "two mons: 11 + 6 white after the ramp")
for _ = 1, 8 + 17 - 1 do fade:update() end
eq(#pushed, 0, "24 updates: still white")
fade:update()
eq(pushed[1], "pokemon", "the 25th pushes the list")
eq(stack:top(), nil, "over a stack the fade has left")
game:openStartMenuItem("pack")
eq(stack:top().white, 16, "PACK: 16")
stack:clear()
game:openStartMenuItem("pokegear")
eq(stack:top().white, 20, "POKEGEAR: 20")
stack:clear()
game:openStartMenuItem("status")
eq(stack:top().white, 14, "trainer card: 14")
stack:clear()
game:openStartMenuItem("pokedex")
eq(stack:top().white, 27, "POKEDEX: 27")
stack:clear()
game:openStartMenuItem("option")
eq(stack:top().white, 8, "OPTION: 8")
stack:clear()
pushed = {}
game:openStartMenuItem("save")
eq(pushed[1], "save", "SAVE goes straight to the page")
eq(stack:top(), nil, "with no fade")
local page = { screenId = "Gen2PackMenu" }
stack:push({ screenId = "Gen2StartMenu" })
stack:push(page)
game:closeStartMenuItem("pack")
local out = stack:top()
eq(out and out.screenId, "Gen2MenuFade", "closing the PACK pops it onto a fade")
eq(out.kind, "in", "inward")
eq(out.white, 23, "23 white")
eq(#stack.states, 2, "over the START menu")
for _ = 1, 23 + 6 do out:update() end
eq(stack:top().screenId, "Gen2StartMenu", "which is back after 29 frames")
stack:push({ screenId = "Gen2Pokegear" })
game:closeStartMenuItem("pokegear")
eq(stack:top().white, 27, "the gear's close holds 27")
stack:pop()
stack:push({ screenId = "Gen2SaveMenu" })
game:closeStartMenuItem("save")
eq(stack:top().screenId, "Gen2StartMenu", "SAVE just pops")
end
do
local PartyMenu = require("src.ui.gen2.PartyMenu")
local PackMenu = require("src.ui.gen2.PackMenu")
local function harness()
local calls = 0
local world = {
exitMenusFade = function() calls = calls + 1 end,
}
local stack = newStack()
stack:push({ screenId = "Gen2StartMenu" })
stack:push({ screenId = "page" })
return { stack = stack, world = world }, function() return calls end, world
end
local game, calls = harness()
local party = setmetatable({ game = game }, PartyMenu)
party:exitToField()
eq(#game.stack.states, 0, "the field-move exit clears the stack")
eq(calls(), 1, "and runs ExitAllMenus' fade")
local game2, calls2, world2 = harness()
world2.mapSetup = { phase = "in" }
local party2 = setmetatable({ game = game2 }, PartyMenu)
party2:exitToField()
eq(calls2(), 0, "a fade already armed (FLY) is left alone")
local game3, calls3 = harness()
local pack = setmetatable({ game = game3 }, PackMenu)
pack.storeCursor = function() end
pack:exitToField()
eq(#game3.stack.states, 0, "PACKSTATE_QUITRUNSCRIPT clears the stack")
eq(calls3(), 1, "through the same fade")
end
T.finish("gen2 START page whites S6")