singe/testScripts/ports/karisPort.singe
2026-09-22 18:32:07 -05:00

101 lines
3.5 KiB
Text

-- The Forge port of a KarisFramework game, driven and traced as the original is.
local here = ((debug.getinfo(1, "S").source:gsub("^@", "")):match("^(.*[/\\])") or "")
QTE_LEVEL_FINISH = 110
local library = os.getenv("SINGE_LIBRARY") or (os.getenv("HOME") .. "/claude/singetest/ported")
local game = os.getenv("PORT_GAME") or "TimeGal"
local name = (os.getenv("PORT_SCRIPT") or "Timegal.singe"):gsub("%.singe$", "")
local stem = name:match("([^/\\]+)$")
dofile("Forge/AuthorCompile.singe")
dofile(here .. "karisDrive.singe")
local realSkip = discSkipToFrame
discSkipToFrame = function(frame)
karisTraceSeek(frame)
return realSkip(frame)
end
dofile(authorBuild(library .. "/" .. game .. "/" .. name .. ".forge", singeGetDataPath() .. stem .. ".port.singe"))
local realUpdate = onOverlayUpdate
local frames = 0
function karisPress(switch, down)
if down then
authorSwitchDown(switch)
else
authorSwitchUp(switch)
end
end
function karisMouse(x, y)
onMouseMoved(x, y, 0, 0, 0)
end
local function view()
local q = authorEntity("game").q
local m = q.move[q.currentMove]
local window = nil
local chosen = nil
if q.timegal then
if (q.currentLevel == 103) and m and (m[2] ~= nil) then
window = { from = m[2], to = m[3], kind = m[7], death = 0, alt = 0, alt2 = 0 }
end
elseif (q.currentLevel == 103) and m and (m[1] ~= nil) then
window = { from = m[1], to = m[2], kind = m[3], death = m[4], alt = m[5], alt2 = m[6] }
end
local zone = (m and (m[3] == q.ACTDOWN) and (m[7] ~= nil)) and { m[7], m[8], m[9], m[10] } or nil
local mouse = q.ratiox and { q.ratiox, q.ratioy, q.ratioxOffset, q.ratioyOffset } or nil
local pairs = nil
if q.rdg and q.ACTUP then
pairs = { [q.ACTUP] = { 5, 1 }, [q.ACTDOWN] = { 5, 2 }, [q.ACTLEFT] = { 5, 3 }, [q.ACTRIGHT] = { 5, 4 }, [q.UPLEFT] = { 1, 3 }, [q.UPRIGHT] = { 1, 4 }, [q.DOWNLEFT] = { 2, 3 }, [q.DOWNRIGHT] = { 2, 4 } }
end
if ((q.lvlState == 19) or (q.rdg and (q.lvlState == 11))) and q.choice then
chosen = {}
for index, c in ipairs(q.choice) do
chosen[index] = { right = c[2] }
end
end
if q.timegal and (q.lvlState == 12) and q.opt then
chosen = {}
for index, c in ipairs(q.opt) do
chosen[index] = { right = c[2] }
end
end
-- Kimmy's new-game menu is a level the framework never numbered (nil there); the port
-- numbers it, and reports it as the original does.
local screen = q.currentLevel
if q.kimmy and (screen == q.levelNG) then
screen = nil
end
-- The map-mode lineage never numbered its finish screen either.
if q.rdg and (screen == QTE_LEVEL_FINISH) then
screen = nil
end
return { screen = screen, step = q.lvlState, level = q.iLevel or q.iCurPos or q.iStageIndex, scene = q.iScene or q.iSegPointer, move = q.currentMove, frame = discGetFrame(), frames = frames, score = q.iScore, lives = q.iLives, window = window, choices = chosen, order = q.optorder, choice = q.iChoice,
kimmy = q.kimmy, rdg = q.rdg, timegal = q.timegal, multi = q.kimmy and q.multi[q.currentMove] or nil, path = q.kimmy and q.path[q.currentMove] or nil, timed = q.kimmy and q.timed or nil,
freeplay = (q.dip_CoinsPerCredit == q.DOPT_FREEPLAY), credits = q.iCredits, zone = zone, mouse = mouse, pairs = pairs, mashKind = q.rdg and q.MASH or nil }
end
function onOverlayUpdate()
frames = frames + 1
if authorEntity("game").q.gameflow == "running" then
karisDrive(view())
end
local r = realUpdate()
if (frames > 100) and karisDone(view()) or (frames > KARIS_FRAMES) then
debugPrint("TRACE end after " .. frames .. " frames")
singeQuit()
end
return r
end