mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
144 lines
6.2 KiB
Lua
144 lines
6.2 KiB
Lua
-- Yellow's two extra pic rips and the plumbing that reaches for them.
|
|
--
|
|
-- #557: LoadPlayerBackPic (pokeyellow engine/battle/core.asm:6384-6391)
|
|
-- loads OldManPicBack for BATTLE_TYPE_OLD_MAN but ProfOakPicBack for
|
|
-- BATTLE_TYPE_PIKACHU, the Pallet Town catch scene, and DisplayBattleMenu
|
|
-- splits the displayed thrower name on the same wBattleType. The port
|
|
-- carries that split as makeOldManDemo's name argument.
|
|
--
|
|
-- #561: TalkToPikachu's framed portrait draws the chosen PikaPicAnimScript's
|
|
-- own base frame (data/pikachu/pikachu_pic_animation.asm), not the battle
|
|
-- front pic that stood in for all of them.
|
|
--
|
|
-- Both rips are gated on manifest symbols, so tools/rom_manifest_yellow.json
|
|
-- is as much a part of these fixes as the Lua is: without the symbol the
|
|
-- extractor writes nothing, the runtime existence check falls back, and the
|
|
-- screen looks exactly like the bug report.
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.modkit")
|
|
local BattleState = require("src.battle.BattleState")
|
|
local FieldDefaults = require("src.world.FieldDefaults")
|
|
local Sprites = require("src.pokemon.Sprites")
|
|
|
|
local PROF_BACK = "assets/generated/battle/profoakb.png"
|
|
local OLDMAN_BACK = "assets/generated/battle/oldmanb.png"
|
|
local RED_BACK = "assets/generated/battle/redb.png"
|
|
|
|
local function readFile(path)
|
|
local handle = io.open(path, "r")
|
|
if not handle then return nil end
|
|
local text = handle:read("*a")
|
|
handle:close()
|
|
return text
|
|
end
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- #557: the back pic keys and the wBattleType split
|
|
-- ---------------------------------------------------------------------
|
|
|
|
T.eq(FieldDefaults.fieldValue(nil, "playerPics", "oakBack"), PROF_BACK,
|
|
"playerPics carries a third back pic for the PROF.OAK demo")
|
|
T.eq(FieldDefaults.fieldValue(nil, "playerPics", "demoBack"), OLDMAN_BACK,
|
|
"the old man's back pic is untouched")
|
|
|
|
-- The love stub's filesystem is a table of written files, so writing the
|
|
-- path IS "this cache was imported after the rip landed".
|
|
love.filesystem.write(PROF_BACK, "png")
|
|
T.eq(Sprites.playerPath(nil, "back", { demo = true, oakDemo = true }),
|
|
PROF_BACK, "the Pallet catch demo fights behind Oak's own back pic")
|
|
T.eq(Sprites.playerPath(nil, "back", { demo = true }), OLDMAN_BACK,
|
|
"the Route 5 catch tutorial still gets the old man")
|
|
T.eq(Sprites.playerPath(nil, "back", {}), RED_BACK,
|
|
"an ordinary battle still gets the player")
|
|
|
|
love.filesystem.remove(PROF_BACK)
|
|
T.eq(Sprites.playerPath(nil, "back", { demo = true, oakDemo = true }),
|
|
OLDMAN_BACK,
|
|
"a cache built before the rip falls back to the old man, not a missing file")
|
|
|
|
-- makeOldManDemo only fills fields when a player battler already exists, so
|
|
-- a stub with one stays clear of Pokemon.new and the fixture dataset.
|
|
local oak = { player = true }
|
|
BattleState.makeOldManDemo(oak, "PROF.OAK")
|
|
T.eq(oak.demoName, "PROF.OAK", "the Yellow demo names PROF.OAK as the thrower")
|
|
T.eq(oak.oakDemo, true, "and asks for his back pic")
|
|
|
|
local oldMan = { player = true }
|
|
BattleState.makeOldManDemo(oldMan)
|
|
T.eq(oldMan.demoName, "OLD MAN", "the unnamed demo is still the old man")
|
|
T.eq(oldMan.oakDemo, false, "and does not reach for Oak's pic")
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- the symbol tables the two rips are gated on
|
|
-- ---------------------------------------------------------------------
|
|
|
|
local extractor = readFile("src/import/RomExtractor.lua")
|
|
T.check(extractor ~= nil, "src/import/RomExtractor.lua is readable")
|
|
extractor = extractor or ""
|
|
|
|
local yellowManifest = readFile("tools/rom_manifest_yellow.json")
|
|
T.check(yellowManifest ~= nil, "tools/rom_manifest_yellow.json is readable")
|
|
yellowManifest = yellowManifest or ""
|
|
|
|
local generator = readFile("tools/make_yellow_manifest.py")
|
|
T.check(generator ~= nil, "tools/make_yellow_manifest.py is readable")
|
|
generator = generator or ""
|
|
|
|
-- Every symbol below is real in pokeyellow.sym; what decides whether the
|
|
-- extractor can see it is whether the generator injects it. Red never
|
|
-- referenced any of them, so make_yellow_manifest's Red-name remap cannot
|
|
-- pick them up on its own -- they have to be listed in YELLOW_EXTRA_SYMBOLS.
|
|
-- One line per group rather than per label: a missing symbol list reads as
|
|
-- one fault to fix, not fifty-odd.
|
|
local function missingFrom(text, labels)
|
|
local missing = {}
|
|
for _, label in ipairs(labels) do
|
|
if not text:find('"' .. label .. '"', 1, true) then
|
|
missing[#missing + 1] = label
|
|
end
|
|
end
|
|
return missing
|
|
end
|
|
|
|
local function requireSymbols(labels, why)
|
|
local gone = missingFrom(yellowManifest, labels)
|
|
T.check(#gone == 0, why .. ": rom_manifest_yellow.json is missing "
|
|
.. (#gone == 0 and "nothing" or table.concat(gone, " ")))
|
|
gone = missingFrom(generator, labels)
|
|
T.check(#gone == 0, why .. ": make_yellow_manifest.py never asks for "
|
|
.. (#gone == 0 and "nothing" or table.concat(gone, " "))
|
|
.. " (add them to YELLOW_EXTRA_SYMBOLS)")
|
|
end
|
|
|
|
T.check(extractor:find('self.symbols["ProfOakPicBack"]', 1, true) ~= nil,
|
|
"the extractor gates Oak's back pic on the ProfOakPicBack symbol")
|
|
requireSymbols({ "ProfOakPicBack" }, "#557")
|
|
|
|
-- Read the label list out of the extractor itself rather than repeating it:
|
|
-- the contract under test is that the manifest answers whatever
|
|
-- extractField asks for, so a later edit to PIKAPIC_BASE stays covered.
|
|
local pikapicBlock = extractor:match("local PIKAPIC_BASE = {(.-)\n }")
|
|
T.check(pikapicBlock ~= nil, "RomExtractor's PIKAPIC_BASE table is readable")
|
|
local pikapic, seen = {}, {}
|
|
for label in (pikapicBlock or ""):gmatch('"([%w_]+)"') do
|
|
if not seen[label] then
|
|
seen[label] = true
|
|
pikapic[#pikapic + 1] = label
|
|
end
|
|
end
|
|
-- 28 PikaPicAnimScripts, script 26 sharing script 11's base pic
|
|
T.eq(#pikapic, 27, "PIKAPIC_BASE names 27 distinct base pics")
|
|
requireSymbols(pikapic, "#561")
|
|
|
|
-- Red and Blue have neither pic, so neither manifest may grow one: a stray
|
|
-- entry there would rip Yellow art out of the wrong ROM.
|
|
for _, path in ipairs({ "tools/rom_manifest.json", "tools/rom_manifest_blue.json" }) do
|
|
local text = readFile(path)
|
|
T.check(text ~= nil, path .. " is readable")
|
|
T.check(text == nil or text:find("ProfOakPicBack", 1, true) == nil,
|
|
path .. " has no ProfOakPicBack, matching pokered")
|
|
end
|
|
|
|
T.finish("yellow oak back pic and pikapic bases")
|