mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 05:32:07 -04:00
197 lines
8.6 KiB
Lua
197 lines
8.6 KiB
Lua
#!/usr/bin/env luajit
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
require("tests.game3_cache").stubSpeciesNames()
|
|
local ROM_TEXT = { gText_PkmnsNickname = "'s nickname?" }
|
|
local function romTextKey(n, i, j) return j and (n .. "[" .. i .. "][" .. j .. "]") or (n .. "[" .. i .. "]") end
|
|
local function romTextPlain(key, ctx) return ((ROM_TEXT[key] or key):gsub("{PLAYER}", ctx and ctx.playerName or "")) end
|
|
package.loaded["src.core.game3.rom_text"] = {
|
|
plain = romTextPlain, box = romTextPlain, ascii = romTextPlain, has = function() return true end,
|
|
key = romTextKey, at = function(n, i, j, ctx) return romTextPlain(romTextKey(n, i, j), ctx) end,
|
|
count = function() return 0 end, list = function() return {} end,
|
|
lazy = function(map) return setmetatable({}, { __index = function(_, k) return map[k] end }) end,
|
|
}
|
|
|
|
local failed = 0
|
|
local function check(cond, msg)
|
|
if cond then
|
|
print("[ok] " .. msg)
|
|
else
|
|
failed = failed + 1
|
|
print("[FAIL] " .. msg)
|
|
end
|
|
end
|
|
|
|
local Ctx = require("src.core.game3.scripting.ctx")
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local Std = require("src.core.game3.scripting.stdscripts")
|
|
local Natives = require("src.core.game3.scripting.natives")
|
|
local Ops = require("src.core.game3.scripting.ops_a")
|
|
|
|
local function newCtx()
|
|
local ctx = Ctx.new({})
|
|
ctx.mode = "bytecode"
|
|
ctx.status = "running"
|
|
return ctx
|
|
end
|
|
|
|
local function session(tbl)
|
|
package.loaded["src.core.game3.runtime"] = {
|
|
getSession = function() return tbl end,
|
|
isActive = function() return true end,
|
|
}
|
|
return tbl
|
|
end
|
|
|
|
print("[test] 1. ChoosePartyMon writes the slot into VAR_0x8004")
|
|
local s = session({
|
|
trainerId = 4242,
|
|
party = {
|
|
{ species = 1, nickname = "", otId = 4242 },
|
|
{ species = 4, nickname = "SPIKE", otId = 999 },
|
|
},
|
|
})
|
|
local ctx = newCtx()
|
|
local picked, pending
|
|
local adapters = {
|
|
log = function() end,
|
|
chooseParty = function(opts, done)
|
|
picked = opts.menuType
|
|
pending = done
|
|
end,
|
|
}
|
|
local yielded = Natives.special(ctx, Std.SPECIAL.ChoosePartyMon, adapters)
|
|
check(picked == "choose_single", "party chooser opened in choose_single mode")
|
|
check(yielded == true, "script yields while the picker is up")
|
|
check(ctx.nativePoll and ctx.nativePoll() == false, "native still waiting before a pick")
|
|
if pending then pending(1) end
|
|
check(Flags.getVar(nil, ctx, 0x8004) == 1, "VAR_0x8004 = 1 (got " ..
|
|
tostring(Flags.getVar(nil, ctx, 0x8004)) .. ")")
|
|
check(ctx.nativePoll() == true, "native finished after the callback")
|
|
|
|
print("[test] 2. cancel writes SLOT_CANCEL (7), which scripts read as >= PARTY_SIZE")
|
|
local ctx2 = newCtx()
|
|
Natives.special(ctx2, Std.SPECIAL.ChoosePartyMon, {
|
|
log = function() end,
|
|
chooseParty = function(_, done) done(nil) end,
|
|
})
|
|
check(Flags.getVar(nil, ctx2, 0x8004) == 7, "VAR_0x8004 = 7 on cancel (got " ..
|
|
tostring(Flags.getVar(nil, ctx2, 0x8004)) .. ")")
|
|
|
|
print("[test] 3. ChoosePartyMon is no longer the nickname keyboard")
|
|
local namedOpened = false
|
|
local ctx3 = newCtx()
|
|
Natives.special(ctx3, Std.SPECIAL.ChoosePartyMon, {
|
|
log = function() end,
|
|
openNaming = function(_, done) namedOpened = true; done("NOPE") end,
|
|
chooseParty = function(_, done) done(0) end,
|
|
})
|
|
check(not namedOpened, "openNaming not reached by ChoosePartyMon")
|
|
check(s.party[1].nickname == "", "slot 1 nickname untouched")
|
|
|
|
print("[test] 4. specialvar writes the cart return value to its destination var")
|
|
local store = Flags.newStore()
|
|
local ctx4 = newCtx()
|
|
ctx4.lastBattleOutcome = Natives.B_OUTCOME.CAUGHT
|
|
local a = { log = function() end }
|
|
local function exec(c, row)
|
|
return Ops.dispatch({ ctx = c, store = store, adapters = a, setPc = function() end }, row)
|
|
end
|
|
exec(ctx4, { op = "specialvar", [1] = 0x800D, [2] = Std.SPECIAL.GetBattleOutcome })
|
|
check(Flags.getVar(nil, ctx4, 0x800D) == Natives.B_OUTCOME.CAUGHT,
|
|
"VAR_RESULT = B_OUTCOME_CAUGHT (got " .. tostring(Flags.getVar(nil, ctx4, 0x800D)) .. ")")
|
|
exec(ctx4, { op = "specialvar", [1] = 0x8008, [2] = Std.SPECIAL.GetBattleOutcome })
|
|
check(Flags.getVar(nil, ctx4, 0x8008) == Natives.B_OUTCOME.CAUGHT,
|
|
"VAR_0x8008 = B_OUTCOME_CAUGHT (got " .. tostring(Flags.getVar(nil, ctx4, 0x8008)) .. ")")
|
|
|
|
print("[test] 5. GetDaycareState is not a battle outcome any more")
|
|
local ctx5 = newCtx()
|
|
ctx5.lastBattleOutcome = Natives.B_OUTCOME.CAUGHT
|
|
exec(ctx5, { op = "specialvar", [1] = 0x800D, [2] = Std.SPECIAL.GetDaycareState })
|
|
check(Flags.getVar(nil, ctx5, 0x800D) == 0, "empty daycare = DAYCARE_NO_MONS (got " ..
|
|
tostring(Flags.getVar(nil, ctx5, 0x800D)) .. ")")
|
|
s.daycare = { { species = 16 } }
|
|
local ctx5b = newCtx()
|
|
exec(ctx5b, { op = "specialvar", [1] = 0x800D, [2] = Std.SPECIAL.GetDaycareState })
|
|
check(Flags.getVar(nil, ctx5b, 0x800D) == 2, "one mon = DAYCARE_ONE_MON (got " ..
|
|
tostring(Flags.getVar(nil, ctx5b, 0x800D)) .. ")")
|
|
s.daycare = nil
|
|
|
|
print("[test] 6. IsMonOTIDNotPlayers answers the Name Rater")
|
|
local ctx6 = newCtx()
|
|
Flags.setVar(nil, ctx6, 0x8004, 0)
|
|
Natives.special(ctx6, Std.SPECIAL.IsMonOTIDNotPlayers, { log = function() end })
|
|
check(Flags.getVar(nil, ctx6, 0x800D) == 0, "own mon: VAR_RESULT = FALSE")
|
|
Flags.setVar(nil, ctx6, 0x8004, 1)
|
|
Natives.special(ctx6, Std.SPECIAL.IsMonOTIDNotPlayers, { log = function() end })
|
|
check(Flags.getVar(nil, ctx6, 0x800D) == 1, "traded mon: VAR_RESULT = TRUE")
|
|
|
|
print("[test] 7. the museum fossil id no longer touches FLAG_SYS_POKEDEX_GET")
|
|
local dexStore = Flags.newStore()
|
|
package.loaded["src.core.game3.scripting.space"] = { store = dexStore }
|
|
local ctx7 = newCtx()
|
|
Natives.special(ctx7, 0x18B, { log = function() end })
|
|
check(Flags.getFlag(dexStore, nil, 0x829) ~= true,
|
|
"0x18B (OpenMuseumFossilPic) leaves FLAG_SYS_POKEDEX_GET clear")
|
|
Natives.special(ctx7, Std.SPECIAL.SetUnlockedPokedexFlags, { log = function() end })
|
|
check(Flags.getFlag(dexStore, nil, 0x829) ~= true,
|
|
"SetUnlockedPokedexFlags does not set FLAG_SYS_POKEDEX_GET either")
|
|
check(s.gcnLinkFlags == 0x31, "SetUnlockedPokedexFlags sets gcnLinkFlags bits 0/4/5 (got " ..
|
|
tostring(s.gcnLinkFlags) .. ")")
|
|
|
|
print("[test] 8. the Route 5 daycare id no longer unlocks the National Dex")
|
|
local ctx8 = newCtx()
|
|
Natives.special(ctx8, 0x179, { log = function() end })
|
|
check(Flags.getFlag(dexStore, nil, 0x840) ~= true, "0x179 leaves FLAG_SYS_NATIONAL_DEX clear")
|
|
Natives.special(ctx8, Std.SPECIAL.EnableNationalPokedex, { log = function() end })
|
|
check(Flags.getFlag(dexStore, nil, 0x840) == true, "0x16F EnableNationalPokedex sets it")
|
|
|
|
print("[test] 9. ChooseMonForMoveTutor opens the MOVE TUTOR party menu and answers FALSE on a cancel")
|
|
-- pokefirered/src/party_menu.c:5793 ChooseMonForMoveTutor
|
|
local PartyMenu9 = require("src.ui.game3.party_menu")
|
|
local ctx9 = newCtx()
|
|
local tutorPicker = false
|
|
Flags.setVar(nil, ctx9, 0x800D, 1)
|
|
Flags.setVar(nil, ctx9, 0x8005, 4)
|
|
local yield9 = Natives.special(ctx9, Std.SPECIAL.ChooseMonForMoveTutor, {
|
|
log = function() end,
|
|
chooseParty = function(_, done) tutorPicker = true; done(0) end,
|
|
})
|
|
check(yield9 == true, "the tutor special holds the script while the picker is up")
|
|
check(PartyMenu9.isOpen() and PartyMenu9.mode == "move_tutor",
|
|
"the party menu is in the MOVE TUTOR action (got " .. tostring(PartyMenu9.mode) .. ")")
|
|
check(not tutorPicker, "the tutor drives the party menu itself, not the chooseParty seam")
|
|
PartyMenu9.close()
|
|
-- pokefirered/src/party_menu.c:4841
|
|
check(Flags.getVar(nil, ctx9, 0x800D) == 0, "VAR_RESULT = FALSE after a cancel (got "
|
|
.. tostring(Flags.getVar(nil, ctx9, 0x800D)) .. ")")
|
|
check(ctx9.nativePoll and ctx9.nativePoll() == true, "the script resumes once the menu closes")
|
|
|
|
print("[test] 10. the nickname keyboard buffers the old nickname in STR_VAR_3")
|
|
local ctx10 = newCtx()
|
|
Flags.setVar(nil, ctx10, 0x8004, 1)
|
|
s.party[2].nickname = "SPIKE"
|
|
Natives.special(ctx10, Std.SPECIAL.ChangePokemonNickname, {
|
|
log = function() end,
|
|
openNaming = function(_, done) done("SPIKE") end,
|
|
})
|
|
check(ctx10.stringVars[3] == "SPIKE", "STR_VAR_3 holds the nickname the rater started from (got "
|
|
.. tostring(ctx10.stringVars[3]) .. ")")
|
|
-- pokefirered/data/maps/LavenderTown_House2/scripts.inc:52
|
|
exec(ctx10, { op = "specialvar", [1] = 0x800D,
|
|
[2] = Std.SPECIAL.NameRaterWasNicknameChanged })
|
|
check(Flags.getVar(nil, ctx10, 0x800D) == 0, "an unchanged nickname answers FALSE (got "
|
|
.. tostring(Flags.getVar(nil, ctx10, 0x800D)) .. ")")
|
|
s.party[2].nickname = "SPARKY"
|
|
exec(ctx10, { op = "specialvar", [1] = 0x800D,
|
|
[2] = Std.SPECIAL.NameRaterWasNicknameChanged })
|
|
check(Flags.getVar(nil, ctx10, 0x800D) == 1, "a new nickname answers TRUE (got "
|
|
.. tostring(Flags.getVar(nil, ctx10, 0x800D)) .. ")")
|
|
check(ctx10.stringVars[1] == "SPARKY", "STR_VAR_1 holds the current nickname (got "
|
|
.. tostring(ctx10.stringVars[1]) .. ")")
|
|
|
|
if failed > 0 then
|
|
print("[test] FAILED " .. failed)
|
|
os.exit(1)
|
|
end
|
|
print("[test] all passed")
|