mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-29 07:00:55 -04:00
166 lines
6.5 KiB
Lua
166 lines
6.5 KiB
Lua
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
|
|
local Rtc = require("src.core.game3.rtc")
|
|
local TimeEvents = require("src.core.game3.time_events")
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local Constants = require("src.core.game3.constants")
|
|
|
|
local C = Constants.of("emerald")
|
|
local CLOCK_SET = C:require("flags", "FLAG_SYS_CLOCK_SET")
|
|
local VAR_DAYS = C:require("vars", "VAR_DAYS")
|
|
local DAILY_LO = C:require("flags", "DAILY_FLAGS_START")
|
|
|
|
local function fresh(spec)
|
|
Rtc.reset()
|
|
if spec then Rtc.setFixed(spec) end
|
|
end
|
|
|
|
local function session()
|
|
return { version = "emerald", store = { flags = {}, vars = {} } }
|
|
end
|
|
|
|
eq(Rtc.dayCount(0, 1, 1), 1, "2000-01-01 is day 1 (pret ConvertDateToDayCount adds the day)")
|
|
eq(Rtc.dayCount(0, 3, 1), 31 + 29 + 1, "2000 is a leap year")
|
|
eq(Rtc.dayCount(1, 1, 1), 367, "2001-01-01 after leap 2000")
|
|
eq(Rtc.dayCount(4, 3, 1), 4 * 365 + 1 + 31 + 29 + 1, "2004 leap day counted")
|
|
check(Rtc.isLeapYear(0), "year 0 (2000) leap")
|
|
check(not Rtc.isLeapYear(100), "2100 not leap")
|
|
check(Rtc.isLeapYear(400), "2400 leap")
|
|
|
|
local d = Rtc.calcTimeDifference(Rtc.newTime(0, 10, 30, 30), Rtc.newTime(1, 9, 20, 10))
|
|
eq(d.days, 0, "borrow days")
|
|
eq(d.hours, 22, "borrow hours")
|
|
eq(d.minutes, 49, "borrow minutes")
|
|
eq(d.seconds, 40, "borrow seconds")
|
|
d = Rtc.calcTimeDifference(Rtc.newTime(5, 0, 0, 0), Rtc.newTime(2, 0, 0, 0))
|
|
eq(d.days, -3, "negative days stay negative")
|
|
eq(Rtc.newTime(40000, 0, 0, 0).days, 40000 - 65536, "days wrap as s16")
|
|
eq(Rtc.newTime(0, 200, 0, 0).hours, 200 - 256, "hours wrap as s8")
|
|
|
|
fresh("2004-03-01T10:15:20")
|
|
local info = Rtc.getInfo(nil)
|
|
eq(info.year, 4, "fixed clock year")
|
|
eq(info.month, 3, "fixed clock month")
|
|
eq(info.hour, 10, "fixed clock hour")
|
|
eq(Rtc.errorStatus(), 0, "no RTC error in range")
|
|
|
|
local s = session()
|
|
local off = Rtc.initLocalTimeOffset(s, 7, 45)
|
|
local lt = Rtc.calcLocalTime(s)
|
|
eq(lt.days, 0, "local day 0 right after setting")
|
|
eq(lt.hours, 7, "local hour after setting")
|
|
eq(lt.minutes, 45, "local minute after setting")
|
|
eq(lt.seconds, 0, "offset absorbs RTC seconds")
|
|
check(s.localTimeOffset == off or s.localTimeOffset.days == off.days, "offset stored on session")
|
|
Rtc.advance(60 * 24 + 30)
|
|
lt = Rtc.calcLocalTime(s)
|
|
eq(lt.days, 1, "a day later")
|
|
eq(lt.hours, 8, "hour after +1d30m")
|
|
eq(lt.minutes, 15, "minute after +1d30m")
|
|
|
|
fresh("2004-03-01T00:00:00")
|
|
eq(Rtc.minuteCount(nil), 24 * 60 * Rtc.dayCount(4, 3, 1), "minute count at midnight")
|
|
Rtc.setFixed("2004-03-01T12:34:00")
|
|
eq(Rtc.minuteCount(nil), 24 * 60 * Rtc.dayCount(4, 3, 1) + 60 * 0x12 + 0x34,
|
|
"RtcGetMinuteCount reads BCD hour/minute (pret quirk)")
|
|
|
|
fresh("2100-01-01T00:00:00")
|
|
check(bit.band(Rtc.errorStatus(), Rtc.ERR.FLAG_MASK) ~= 0, "year out of BCD range is an RTC error")
|
|
eq(Rtc.getInfo(nil).year, 0, "error returns the 2000-01-01 dummy")
|
|
|
|
fresh()
|
|
Rtc.setHostClock(function() return { year = 2026, month = 9, day = 27, hour = 23, minute = 59, second = 59 } end)
|
|
info = Rtc.getInfo(nil)
|
|
eq(info.year, 26, "host clock year")
|
|
Rtc.advance(0, 1)
|
|
info = Rtc.getInfo(nil)
|
|
eq(info.day, 28, "rollover to next day")
|
|
eq(info.hour, 0, "rollover hour")
|
|
Rtc.reset()
|
|
Rtc.setHostClock(function() return { year = 2004, month = 2, day = 28, hour = 23, minute = 0, second = 0 } end)
|
|
Rtc.advance(60)
|
|
eq(Rtc.getInfo(nil).day, 29, "2004-02-29 exists")
|
|
Rtc.advance(60 * 24)
|
|
eq(Rtc.getInfo(nil).month, 3, "leap day rolls to March")
|
|
|
|
fresh("2005-06-01T10:00:00")
|
|
s = session()
|
|
Rtc.initLocalTimeOffset(s, 10, 0)
|
|
s.lastBerryTreeUpdate = Rtc.newTime(0, 10, 0, 0)
|
|
Rtc.setFixed("2005-06-20T18:00:00")
|
|
Rtc.anchorToLastUpdate(s)
|
|
lt = Rtc.calcLocalTime(s)
|
|
eq(lt.days, 0, "import anchor resumes at lastBerryTreeUpdate day")
|
|
eq(lt.hours, 10, "import anchor resumes at lastBerryTreeUpdate hour")
|
|
|
|
TimeEvents.reset()
|
|
TimeEvents.setPokemonCenterCheck(function() return false end)
|
|
fresh("2005-06-01T10:00:00")
|
|
s = session()
|
|
local ran = TimeEvents.run(s)
|
|
check(not ran, "no events before FLAG_SYS_CLOCK_SET")
|
|
Rtc.initLocalTimeOffset(s, 9, 0)
|
|
TimeEvents.init(s)
|
|
check(Flags.getFlag(s.store, nil, CLOCK_SET), "init sets FLAG_SYS_CLOCK_SET")
|
|
eq(Flags.getVar(s.store, nil, VAR_DAYS), 0, "init stores VAR_DAYS")
|
|
local dayCalls, minuteCalls, order = {}, {}, {}
|
|
TimeEvents.onDay("UpdateTVShowsPerDay", function(_, n) dayCalls[#dayCalls + 1] = n; order[#order + 1] = "tv" end)
|
|
TimeEvents.onDay("UpdateDewfordTrendPerDay", function() order[#order + 1] = "dewford" end)
|
|
TimeEvents.onMinute("BerryTreeTimeUpdate", function(_, n) minuteCalls[#minuteCalls + 1] = n end)
|
|
Flags.setFlag(s.store, nil, DAILY_LO + 3, true)
|
|
ran = TimeEvents.run(s)
|
|
check(ran, "runs once clock set")
|
|
eq(#dayCalls, 0, "no per-day before a day passes")
|
|
eq(#minuteCalls, 0, "no per-minute when 0 minutes passed")
|
|
Rtc.advance(125)
|
|
TimeEvents.run(s)
|
|
eq(minuteCalls[1], 125, "per-minute gets elapsed minutes")
|
|
eq(#dayCalls, 0, "still same day")
|
|
Rtc.advance(60 * 24 * 2)
|
|
TimeEvents.run(s)
|
|
eq(dayCalls[1], 2, "per-day gets days since")
|
|
eq(order[1], "dewford", "pret order: Dewford before TV")
|
|
check(not Flags.getFlag(s.store, nil, DAILY_LO + 3), "ClearDailyFlags cleared a daily flag")
|
|
eq(Flags.getVar(s.store, nil, VAR_DAYS), 2, "VAR_DAYS advanced")
|
|
TimeEvents.run(s)
|
|
eq(#dayCalls, 1, "per-day fires once per day change")
|
|
TimeEvents.setPokemonCenterCheck(function() return true end)
|
|
Rtc.advance(60 * 24)
|
|
check(not TimeEvents.run(s), "skipped inside a Pokemon Center")
|
|
TimeEvents.setPokemonCenterCheck(function() return false end)
|
|
s.lastBerryTreeUpdate = Rtc.newTime(99, 0, 0, 0)
|
|
minuteCalls = {}
|
|
TimeEvents.run(s)
|
|
eq(#minuteCalls, 0, "negative minute delta ignored (pret minutes >= 0)")
|
|
|
|
local fr = { version = "firered", store = { flags = {}, vars = {} } }
|
|
check(not Rtc.enabled(fr), "FireRed has no RTC")
|
|
check(Rtc.enabled(s), "Emerald has an RTC")
|
|
check(not TimeEvents.run(fr), "time events never run on FireRed")
|
|
|
|
-- pokeemerald/src/field_tasks.c:150
|
|
TimeEvents.reset()
|
|
TimeEvents.setPokemonCenterCheck(function() return false end)
|
|
fresh("2005-06-01T10:00:00")
|
|
s = session()
|
|
Rtc.initLocalTimeOffset(s, 10, 0)
|
|
TimeEvents.init(s)
|
|
local ticks = 0
|
|
TimeEvents.onMinute("BerryTreeTimeUpdate", function() ticks = ticks + 1 end)
|
|
Rtc.advance(5)
|
|
check(not TimeEvents.tick(s, 100), "no run while bit 12 is clear")
|
|
check(TimeEvents.tick(s, 4096), "runs when bit 12 rises")
|
|
Rtc.advance(5)
|
|
check(not TimeEvents.tick(s, 4097), "only once while bit 12 stays set")
|
|
check(not TimeEvents.tick(s, 8192), "re-arms when bit 12 clears")
|
|
check(TimeEvents.tick(s, 12288), "runs again on the next rise")
|
|
eq(ticks, 2, "per-minute handler ran twice")
|
|
|
|
TimeEvents.reset()
|
|
TimeEvents.setPokemonCenterCheck(function() return false end)
|
|
Rtc.reset()
|
|
T.finish("game3 rtc")
|