mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 20:50:21 +02:00
G2 support
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
-- Two things only a human can see, in one run.
|
||||
--
|
||||
-- POKEPORT_IDENTITY=gold-dev POKEPORT_GAME=gold \
|
||||
-- POKEPORT_DRIVER=tests/drivers/gold_naming_and_trade_item.lua \
|
||||
-- perl -e 'alarm 300; exec @ARGV' \
|
||||
-- python3 -c "import pty; pty.spawn(['love','.'])"
|
||||
--
|
||||
-- Only the gold-dev identity has a complete Gold cache; another one is missing
|
||||
-- data/generated/marts.lua, RomImporter never reports ready, and the driver
|
||||
-- coroutine is simply never resumed (a silent hang with no output).
|
||||
--
|
||||
-- 1. The naming keyboard. Typing the LAST character does not close the screen:
|
||||
-- `.a` is `call NamingScreen_TryAddCharacter / ret nc`, and
|
||||
-- AdvanceCursor_CheckEndOfString answers CARRY once the buffer is full, so
|
||||
-- the handler falls through into `.start` and parks the cursor on END with
|
||||
-- the keyboard still up (engine/menus/naming_screen.asm:401-410). Only
|
||||
-- `.end` stores the entry. The blank cells are typeable too: the NameInput*
|
||||
-- rows are written into the tilemap and GetLastCharacter reads the tile
|
||||
-- under the cursor back out, so the trailing spaces of "S T U V W X Y Z "
|
||||
-- are real characters (data/text/name_input_chars.asm).
|
||||
--
|
||||
-- 2. Kyle's Onix (VioletKylesHouse, NPC_TRADE_KYLE) arrives holding
|
||||
-- BITTER_BERRY. NPCTRADE_ITEM is an item id BYTE in the table
|
||||
-- (data/events/npc_trades.asm:15) and DoNPCTrade copies it into
|
||||
-- wPartyMon1Item; the port names it, so the summary's green page prints
|
||||
-- BITTER BERRY and TAKE drops a real BITTER BERRY into the bag instead of
|
||||
-- killing the game in Bag.isBadge.
|
||||
--
|
||||
-- Screenshots land in POKEPORT_SHOT_DIR (default /tmp/gold-naming-trade):
|
||||
-- keyboard-parked-on-end.png full buffer, cursor bracketing END
|
||||
-- keyboard-on-blank-cell.png the cursor sitting on the blank after Z
|
||||
-- keyboard-typed-a-space.png a name with a space in the middle of it
|
||||
-- onix-summary-item.png the green page's ITEM field
|
||||
-- onix-item-taken.png "TOOK BITTER BERRY from ROCKY."
|
||||
local U = require("tests.drivers.util")
|
||||
|
||||
local Mon = require("src.battle.gen2.Mon")
|
||||
local NpcTrade = require("src.core.gen2.NpcTrade")
|
||||
local Screens = require("src.ui.Screens")
|
||||
local SummaryMenu = require("src.ui.gen2.SummaryMenu")
|
||||
|
||||
return function(game)
|
||||
local out = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/gold-naming-trade"
|
||||
local fails = 0
|
||||
local function ok(cond, msg)
|
||||
if cond then print("[naming] ok " .. msg)
|
||||
else fails = fails + 1 print("[naming] FAIL " .. msg) end
|
||||
return cond
|
||||
end
|
||||
|
||||
local function tap(btn) U.tap(game, btn) U.wait(3) end
|
||||
local function top() return game.stack:top() end
|
||||
|
||||
U.wait(45)
|
||||
ok(game.world and game.world.map, "gold world booted")
|
||||
|
||||
-- ---------------------------------------------------------- the keyboard
|
||||
local typed
|
||||
Screens.push(game, "Gen2NamingScreen", {
|
||||
type = "rival",
|
||||
menuGfx = game.data.gen2MenuGfx,
|
||||
-- The pop is the caller's, exactly as World:nameRival does it.
|
||||
onDone = function(name) game.stack:pop() typed = name end,
|
||||
})
|
||||
U.wait(10)
|
||||
local keyboard = top()
|
||||
if not ok(keyboard and keyboard.text == "", "the rival keyboard opened") then
|
||||
error("gold naming: no keyboard, cannot continue")
|
||||
end
|
||||
|
||||
-- Seven A presses on the A key fill a 7-character rival name.
|
||||
for _ = 1, keyboard.maxLength do tap("a") end
|
||||
ok(top() == keyboard, "a full buffer leaves the keyboard up")
|
||||
ok(typed == nil, "and hands nothing back yet")
|
||||
ok(keyboard:cursorCharacter() == "END", "the cursor parked itself on END")
|
||||
U.shot(game, out .. "/keyboard-parked-on-end.png")
|
||||
|
||||
-- The blank cell after Z types a space. Back off two characters so the
|
||||
-- buffer has room for a space AND a letter after it (a name with a gap in
|
||||
-- the middle is the only way to see the space at all), then walk up out of
|
||||
-- the bottom row to row 2, column 8.
|
||||
tap("b")
|
||||
tap("b")
|
||||
tap("up")
|
||||
tap("up")
|
||||
tap("right")
|
||||
tap("right")
|
||||
ok(keyboard:cursorCharacter() == " ", "the cell after Z is a space")
|
||||
U.shot(game, out .. "/keyboard-on-blank-cell.png")
|
||||
tap("a")
|
||||
ok(keyboard.text:sub(-1) == " ", "and A types it into the name")
|
||||
-- Up twice from (8,2) is the I key, so the field ends up reading "AAAAA I".
|
||||
tap("up")
|
||||
tap("up")
|
||||
tap("a")
|
||||
ok(keyboard.text == "AAAAA I", "the space really is in the stored name")
|
||||
U.shot(game, out .. "/keyboard-typed-a-space.png")
|
||||
|
||||
-- Only A on END ends entry.
|
||||
tap("start")
|
||||
tap("a")
|
||||
ok(typed ~= nil and #typed == keyboard.maxLength,
|
||||
"A on END is what stores the entry")
|
||||
U.wait(5)
|
||||
|
||||
-- ------------------------------------------------------- Kyle's Onix
|
||||
-- data/generated/events.lua, which World loads as its own eventTables.
|
||||
local row = NpcTrade.row(game.world.eventTables, 1)
|
||||
if not ok(row and row.get == "ONIX", "the cache carries NPC_TRADE_KYLE") then
|
||||
error("gold naming: no trade row, cannot continue")
|
||||
end
|
||||
local save = game.save
|
||||
save.party = { Mon.new(game.data, "BELLSPROUT", 12) }
|
||||
local _, onix = NpcTrade.perform(game.data, save, row, 1)
|
||||
ok(onix and onix.nickname == "ROCKY", "the trade handed ROCKY over")
|
||||
ok(onix and onix.item == "BITTER_BERRY",
|
||||
"wearing a NAMED BITTER_BERRY, not the table's byte 83")
|
||||
|
||||
-- START > POKeMON > A > STATS, then the green page.
|
||||
tap("start")
|
||||
local menu = top()
|
||||
for _ = 1, 10 do
|
||||
if menu.list:current().value == "pokemon" then break end
|
||||
tap("down")
|
||||
end
|
||||
tap("a")
|
||||
local party = top()
|
||||
if not ok(party and party.screenId == "Gen2PartyMenu",
|
||||
"the party list opened") then
|
||||
error("gold naming: no party list, cannot continue")
|
||||
end
|
||||
tap("a")
|
||||
tap("a") -- STATS leads the submenu
|
||||
local summary = top()
|
||||
ok(summary and summary.screenId == "Gen2SummaryMenu", "STATS opened STATS")
|
||||
tap("right") -- page 1 (pink) -> page 2 (green), which is the ITEM page
|
||||
U.wait(5)
|
||||
local placed = summary and summary:placements()
|
||||
local text = {}
|
||||
for _, p in ipairs(placed or {}) do text[#text + 1] = tostring(p.text or "") end
|
||||
ok(table.concat(text, "|"):find("BITTER BERRY", 1, true) ~= nil,
|
||||
"the green page prints BITTER BERRY, not 83")
|
||||
U.shot(game, out .. "/onix-summary-item.png")
|
||||
tap("b")
|
||||
|
||||
-- ITEM > TAKE. This is the press that used to crash in Bag.isBadge.
|
||||
tap("a")
|
||||
local submenu = party and party.submenu
|
||||
for _ = 1, 8 do
|
||||
if submenu and submenu.items[submenu.index]
|
||||
and submenu.items[submenu.index].id == "ITEM" then break end
|
||||
tap("down")
|
||||
submenu = party and party.submenu
|
||||
end
|
||||
ok(submenu and submenu.items[submenu.index]
|
||||
and submenu.items[submenu.index].id == "ITEM", "the cursor found ITEM")
|
||||
tap("a")
|
||||
local held = top()
|
||||
ok(held and held.screenId == "Gen2HeldItemMenu", "GIVE / TAKE opened")
|
||||
tap("down")
|
||||
tap("a")
|
||||
U.wait(5)
|
||||
ok(save.party[1].item == nil, "TAKE pulled the berry off")
|
||||
ok((save.inventory or {}).BITTER_BERRY == 1, "and it landed in the bag")
|
||||
U.shot(game, out .. "/onix-item-taken.png")
|
||||
|
||||
print(("[naming] %d failure(s)"):format(fails))
|
||||
love.event.quit()
|
||||
end
|
||||
Reference in New Issue
Block a user