mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-25 15:01:11 +02:00
Merge pull request #1680 from colsonrice/feat/gen2-rom-text
This commit is contained in:
@@ -42,7 +42,7 @@ check(type(RomExtractorGen2.extractDiploma) == "function",
|
||||
"RomExtractorGen2:extractDiploma exists")
|
||||
check(extractorSource:find("results.diploma = self:extractDiploma()", 1, true)
|
||||
~= nil, "and RomExtractorGen2:run calls it")
|
||||
check(extractorSource:find("local STAGE_COUNT = 26", 1, true) ~= nil,
|
||||
check(extractorSource:find("local STAGE_COUNT = 27", 1, true) ~= nil,
|
||||
"STAGE_COUNT counts the new stage, so the progress bar still ends at 1")
|
||||
|
||||
-- The three symbols the stage reads have to be in the curated manifest set or
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
-- Gen 2's engine text, the counterpart to Gen 1's data/generated/text.lua.
|
||||
--
|
||||
-- Gold and Silver had no label-keyed string table at all: the manifests
|
||||
-- carried no `text` section, RomExtractorGen2 had no extractText, and
|
||||
-- game.data.text was never assigned, so every call through
|
||||
-- src/core/RomText.lua fell back to the literal written beside it. These
|
||||
-- cover the three halves of closing that: the manifest names the labels and
|
||||
-- resolves every one, the decoder emits the runtime name slots rather than
|
||||
-- dropping them, and RomText fills those slots.
|
||||
--
|
||||
-- GOLD_CACHE="..." luajit tests/gen2_rom_text_test.lua
|
||||
--
|
||||
-- ROM-free apart from the last section, which reads an imported cache's
|
||||
-- rom_text.lua and skips cleanly when there is none.
|
||||
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||
|
||||
local S = require("tests.harness").suite("gen2 rom text")
|
||||
local check, eq = S.check, S.eq
|
||||
|
||||
love = require("tests.love_stub")
|
||||
|
||||
local Json = require("src.link.Json")
|
||||
local romText = require("src.core.RomText")
|
||||
|
||||
local function manifest(path)
|
||||
local file = assert(io.open(path, "r"))
|
||||
local data = assert(Json.decode(file:read("*a")))
|
||||
file:close()
|
||||
return data
|
||||
end
|
||||
|
||||
-- ---- the label list, and that every label resolves ------------------------
|
||||
-- A label the list names but the symbol table cannot place would fail the
|
||||
-- import at the Dialogue stage rather than at generation time, so the pairing
|
||||
-- is asserted here instead.
|
||||
for _, edition in ipairs({ "gold", "silver" }) do
|
||||
local data = manifest("tools/rom_manifest_" .. edition .. ".json")
|
||||
local labels = (data.text or {}).labels or {}
|
||||
check((data.text or {}).labels ~= nil,
|
||||
edition .. " carries a text section")
|
||||
check(#labels > 800,
|
||||
("%s names %d text labels"):format(edition, #labels))
|
||||
|
||||
local unresolved = {}
|
||||
for _, label in ipairs(labels) do
|
||||
if not data.symbols[label] then unresolved[#unresolved + 1] = label end
|
||||
end
|
||||
eq(#unresolved, 0,
|
||||
("every %s text label resolves to a symbol (%s)")
|
||||
:format(edition, table.concat(unresolved, ", "):sub(1, 60)))
|
||||
|
||||
local named = {}
|
||||
for _, label in ipairs(labels) do named[label] = true end
|
||||
|
||||
-- data/text/ also holds keyboard layouts and kana tables. Decoded as text
|
||||
-- they come out as keyboard rows, so make_gold_manifest.TEXT_SOURCES leaves
|
||||
-- their files out. `BattleText::` is excluded for a different reason: it
|
||||
-- is a bank anchor sharing an address with the first real label under it,
|
||||
-- and its own comment in the disassembly says so.
|
||||
for _, excluded in ipairs({ "NameInputLower", "MailEntry_Uppercase",
|
||||
"Dakutens", "Gen1TrainerClassNames", "BattleText" }) do
|
||||
check(not named[excluded],
|
||||
edition .. " leaves " .. excluded .. " out of the text list")
|
||||
end
|
||||
end
|
||||
|
||||
-- Both editions describe the same strings; only the addresses move.
|
||||
do
|
||||
local gold = (manifest("tools/rom_manifest_gold.json").text or {}).labels or {}
|
||||
local silver =
|
||||
(manifest("tools/rom_manifest_silver.json").text or {}).labels or {}
|
||||
eq(#gold, #silver, "Gold and Silver name the same number of labels")
|
||||
local mismatch
|
||||
for index, label in ipairs(gold) do
|
||||
if silver[index] ~= label then mismatch = label; break end
|
||||
end
|
||||
eq(mismatch, nil, "and the same labels in the same order")
|
||||
end
|
||||
|
||||
-- ---- the slots RomText fills ----------------------------------------------
|
||||
-- decodeGen2Text emits {USER}, {TARGET} and {ENEMY} for the three names
|
||||
-- PlaceMoveUsersName / PlaceMoveTargetsName / PlaceEnemysName write at
|
||||
-- runtime (home/text.asm:302, :307, :327). Dropped, the line printed with a
|
||||
-- hole where the name belongs.
|
||||
do
|
||||
local data = { text = {
|
||||
SubTookDamageText = "The SUBSTITUTE\ntook damage for\v{TARGET}!",
|
||||
WantsToBattleText = "{ENEMY}\nwants to battle!",
|
||||
ConfusedNoMoreText = "{USER}'s\nconfused no more!",
|
||||
SuperEffectiveText = "It's super-\neffective!",
|
||||
} }
|
||||
|
||||
eq(romText(data, "SubTookDamageText", "fallback", "GEODUDE"),
|
||||
"The SUBSTITUTE\ntook damage for\vGEODUDE!",
|
||||
"a {TARGET} slot takes the name the caller passes")
|
||||
eq(romText(data, "WantsToBattleText", "fallback", "FALKNER"),
|
||||
"FALKNER\nwants to battle!", "and so does {ENEMY}")
|
||||
eq(romText(data, "ConfusedNoMoreText", "fallback", "CYNDAQUIL"),
|
||||
"CYNDAQUIL's\nconfused no more!", "and {USER}")
|
||||
eq(romText(data, "SuperEffectiveText", "It's super effective!"),
|
||||
"It's super-\neffective!",
|
||||
"a line with no slot comes back as the cart wrote it")
|
||||
eq(romText(data, "NoSuchLabel", "the engine's own wording"),
|
||||
"the engine's own wording",
|
||||
"and a label the cache does not carry falls back")
|
||||
end
|
||||
|
||||
-- ---- against a real imported cache ----------------------------------------
|
||||
do
|
||||
local cache = os.getenv("GOLD_CACHE")
|
||||
if not cache then
|
||||
local home = os.getenv("HOME") or ""
|
||||
cache = home .. "/Library/Application Support/LOVE/gold-dev/gold"
|
||||
end
|
||||
local path = cache .. "/data/generated/rom_text.lua"
|
||||
local file = io.open(path, "r")
|
||||
if not file then
|
||||
print(" (skipped: no rom_text.lua at " .. path .. ")")
|
||||
else
|
||||
file:close()
|
||||
local texts = assert(loadfile(path))()
|
||||
check(next(texts) ~= nil, "the imported cache carries strings")
|
||||
-- Wording taken from pokegold's data/text/battle.asm, with \n for `line`
|
||||
-- and \v for `cont`, which is what RomExtractorGen2 decodes those to.
|
||||
eq(texts.SuperEffectiveText, "It's super-\neffective!",
|
||||
"SuperEffectiveText comes off the cart hyphenated and broken")
|
||||
eq(texts.NotVeryEffectiveText, "It's not very\neffective…",
|
||||
"NotVeryEffectiveText ends on the ellipsis glyph")
|
||||
eq(texts.StartPerishText, "Both POKéMON will\nfaint in 3 turns!",
|
||||
"StartPerishText names both sides")
|
||||
eq(texts.ButItFailedText, "But it failed!", "and a one-row line is one row")
|
||||
eq(texts.SubTookDamageText, "The SUBSTITUTE\ntook damage for\v{TARGET}!",
|
||||
"SpikesText's neighbour keeps its cont row and its target slot")
|
||||
eq(texts.PlayerHitTimesText, "Hit {NUM} times!",
|
||||
"a text_decimal reads back as {NUM}")
|
||||
end
|
||||
end
|
||||
|
||||
S.finish()
|
||||
@@ -45,7 +45,7 @@ check(type(RomExtractorGen2.extractTrade) == "function",
|
||||
"RomExtractorGen2:extractTrade exists")
|
||||
check(extractorSource:find("results.trade = self:extractTrade()", 1, true)
|
||||
~= nil, "and RomExtractorGen2:run calls it")
|
||||
check(extractorSource:find("local STAGE_COUNT = 26", 1, true) ~= nil,
|
||||
check(extractorSource:find("local STAGE_COUNT = 27", 1, true) ~= nil,
|
||||
"STAGE_COUNT counts the new stage, so the progress bar still ends at 1")
|
||||
|
||||
-- pokegold.sym, bank $0a. These are also what the cache is checked against
|
||||
|
||||
@@ -3526,6 +3526,7 @@ runSuites({
|
||||
"tests/gen2_decorations_test.lua",
|
||||
"tests/gen2_pokerus_test.lua",
|
||||
"tests/gen2_common_text_test.lua",
|
||||
"tests/gen2_rom_text_test.lua",
|
||||
"tests/gen2_magnet_train_test.lua",
|
||||
"tests/gen2_bank_of_mom_test.lua",
|
||||
"tests/gen2_trainerhouse_test.lua",
|
||||
|
||||
Reference in New Issue
Block a user