0,]']±>Sï}WÿÍu§ðp8·d%qy)6o;]ÉA¦ösï÷ôôô”°ÂVl†3??????????????? !"$$%'()*+,-/////////////////@4 7à9 ;€=€>€>€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€?€ 012345555555555555555555555555' dd ddd DD‘?1 ""3#"""""#""""""""""""3333"""""""""""""331#""""""313"""""""21#""""""21#2#""""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!2#"""""2!#"""""2!#"""""2!#"""""2!#"""""2!#"""""2!#"""""2#"""""2O-- title: TIC-80 Boom! -- author: jtruk vs Gasman -- desc: Is ToDay the Day? -- script: lua -- Assembled by the RiFT bundler rift_scenesboxopenbad1=function() local M=math local S,C,POW,PI,ABS,MIN=M.sin,M.cos,M.pow,M.pi,M.abs,M.min local TAU=PI*2 local firstEntry=true local tSceneF=0 local firstEntry=true function BDR1(y) if y>=0 and y<136 then local fl=S(tSceneF*PI)*.5+.5 local bgR,bgG,bgB=fl*255,fl*0,fl*0 setRGB(0, bgR,bgG,bgB) fadeColour(1,150,90,220,bgR,bgG,bgB,fl) fadeColour(2,10,70,150,bgR,bgG,bgB,fl) fadeColour(3,0,30,80,bgR,bgG,bgB,fl) end end function doSceneBoxOpenBad1(t) if firstEntry then sfx(2) firstEntry=false end cls() tSceneF=t BDR=BDR1 CAM.y=2 CAM.x=0 CAM.z=CAM_Z_EXPLODE CAM.ry=t*TAU*2 local def=getBoxDef() drawObj(def) for i=0,10 do local x=120+math.random(-30,30) local y=80+math.random(-30,30) local s=math.random(5,30) local c=math.random(2,5) circ(x,y,s,c) end end function printOutline(t,x,y) print(t, x+1,y+1,15, false,2) print(t, x,y,12, false,2) end end rift_scenesintro=function() function doSceneIntro(t) cls() print("TIC-80 BOOM!", 60, 50, 12, false, 2) print("jtruk - code + bad music (\"not the day\")", 13, 110, 12) print("Gasman - good music (\"the day\")", 37, 120, 12) end end rift_sceneswalkup=function() local M=math local S,PI,ABS=M.sin,M.pi,M.abs local TAU=PI*2 local yLastBounce=0 function doSceneWalkUp(t) cls() local bounces=14 local yBounce=ABS(S(t*PI*bounces)*.5) CAM.y=2-yBounce CAM.x=S(t*PI*bounces+PI/2)*.25 CAM.z=CAM_Z_FAR-t*(CAM_Z_FAR-CAM_Z_NEAR) CAM.ry=t*TAU*2 if yBounce > yLastBounce then sfx(0,35,2) end local def=getBoxDef() drawObj(def) yLastBounce = yBounce end end rift_date=function() function daysInYear(yr) return ( yr % 4 == 0 and (yr % 100 ~= 0 or yr % 400 == 0) ) and 366 or 365 end function tab_overflow(seed, table) for i = 1, #table do if seed - table[i] <= 0 then return i, seed end seed = seed - table[i] end end -- https://otland.net/threads/how-convert-timestamp-to-date-type.251657/#post-2442023 function dateFromUnix(unix_time) local year = 1970 local days = math.ceil(unix_time/86400) local month = 0 while days >= daysInYear(year) do days = days - daysInYear(year) year = year + 1 end local month,days=tab_overflow(days, {31,(daysInYear(year) == 366 and 29 or 28),31,30,31,30,31,31,30,31,30,31}) local hours=math.floor(unix_time / 3600 % 24) local minutes=math.floor(unix_time / 60 % 60) local seconds=math.floor(unix_time % 60) return { year=year, month=month, day=days, hour=hours, minute=minutes, second=seconds, } end function keyFromDate(month,day) return string.format("%02d%02d",day,month) end end rift_draw=function() function drawFinger(x,y) local def = getFingerDef() drawObj(def) end function drawButton(i,x,y,w,h,state) local bg,fg=15,13 if state then bg,fg = 14,4 end rect(x,y,w,h,bg) print(i,x+7,y+7,fg,false,5) end function draw(ps) for i,p in ipairs(ps) do rX(p,CAM.rx) rY(p,CAM.ry) rZ(p,CAM.rz) pp(p,CAM) end table.sort(ps, function(a,b) return a.pz>b.pz end) for i,p in ipairs(ps) do circ(p.px,p.py,1,p.c) end end function getFingerDef() return { ps={ {x=-1,y=-1,z=0}, {x=-1,y=0,z=0}, {x=0,y=-1,z=0}, }, quads={}, tris={ {1,2,3}, }, } end function getBoxDef() local t0x0,t0y0,t0x1,t0y1=0,0,32,32 local t1x0,t1y0,t1x1,t1y1=32,0,64,32 return { ps={ {x=-1,y=1,z=-1}, {x=1,y=1,z=-1}, {x=-1,y=-1,z=-1}, {x=1,y=-1,z=-1}, {x=-1,y=1,z=1}, {x=1,y=1,z=1}, {x=-1,y=-1,z=1}, {x=1,y=-1,z=1}, }, quads={ {{p=2, t={x=t0x0, y=t0y0}}, {p=1, t={x=t0x1, y=t0y0}}, {p=3, t={x=t0x1, y=t0y1}}, {p=4, t={x=t0x0, y=t0y1}}}, {{p=5, t={x=t0x0, y=t0y0}}, {p=6, t={x=t0x1, y=t0y0}}, {p=8, t={x=t0x1, y=t0y1}}, {p=7, t={x=t0x0, y=t0y1}}}, {{p=1, t={x=t0x0, y=t0y0}}, {p=5, t={x=t0x1, y=t0y0}}, {p=7, t={x=t0x1, y=t0y1}}, {p=3, t={x=t0x0, y=t0y1}}}, {{p=6, t={x=t0x0, y=t0y0}}, {p=2, t={x=t0x1, y=t0y0}}, {p=4, t={x=t0x1, y=t0y1}}, {p=8, t={x=t0x0, y=t0y1}}}, {{p=1, t={x=t1x0, y=t1y0}}, {p=2, t={x=t1x1, y=t1y0}}, {p=6, t={x=t1x1, y=t1y1}}, {p=5, t={x=t1x0, y=t1y1}}}, {{p=3, t={x=t1x0, y=t1y0}}, {p=4, t={x=t1x1, y=t1y0}}, {p=8, t={x=t1x1, y=t1y1}}, {p=7, t={x=t1x0, y=t1y1}}}, }, tris={ }, } end function getBoxSideDef() local tx0,ty0,tx1,ty1=0,0,31,31 return { ps={ {x=-1,y=0,z=-1}, {x=1,y=0,z=-1}, {x=-1,y=0,z=1}, {x=1,y=0,z=1}, }, quads={ {{p=2, t={x=t0x0, y=t0y0}}, {p=1, t={x=t0x1, y=t0y0}}, {p=3, t={x=t0x1, y=t0y1}}, {p=4, t={x=t0x0, y=t0y1}}}, }, tris={ } } end function drawObj(boxDef) local ps=boxDef.ps for i=1,#ps do local p=ps[i] rX(p, CAM.rx) rY(p, CAM.ry) rZ(p, CAM.rz) pp(p, CAM) end for i,q in ipairs(boxDef.quads) do local p1=ps[q[1].p] local p2=ps[q[2].p] local p3=ps[q[3].p] local p4=ps[q[4].p] drawTri(p1,p2,p3, q[1].t, q[2].t, q[3].t) drawTri(p3,p4,p1, q[3].t, q[4].t, q[1].t) end for i,t in ipairs(boxDef.tris) do local p1=ps[t[1]] local p2=ps[t[2]] local p3=ps[t[3]] tri(p1.x,p1.y, p2.x,p2.y, p3.x,p3.y, 12) end end end rift_scenes=function() I_CURRENT_SCENE = 1 CURRENT_T_IN_SCENE = 0 -- each scene runs 0-t inclusive... SCENES = { {id='intro', t=200}, {id='walk-up', t=300}, {id='pin-entry', t=100}, {id='walk-back', t=150}, {id='box-open', t=200}, {id='in-the-box', t=nil}, } function incT() CURRENT_T_IN_SCENE = CURRENT_T_IN_SCENE + 1 local currentScene = SCENES[I_CURRENT_SCENE] local currentSceneLen = currentScene.t if currentSceneLen ~= nil and CURRENT_T_IN_SCENE > currentSceneLen then CURRENT_T_IN_SCENE = 0 I_CURRENT_SCENE = I_CURRENT_SCENE + 1 end end -- tUnit -> 0 - 1 function getScene() local currentScene = SCENES[I_CURRENT_SCENE] return { id = currentScene.id, t = CURRENT_T_IN_SCENE, tUnit = (currentScene.t ~= nil) and (CURRENT_T_IN_SCENE / currentScene.t) or CURRENT_T_IN_SCENE / 100 } end end rift_scenespinentry=function() local M=math local MIN=M.min local BUTTON_STATE={} local tButtonLast=-1 function doScenePinEntry(t) for i=0,9 do BUTTON_STATE[i+1] = false end local tButton=MIN(1+(t*4)//1,#KEY) if tButton ~= tButtonLast then sfx(1,60,10) end local iButton=KEY:sub(tButton,tButton) if tButton-t*#KEY > .5 then BUTTON_STATE[iButton + 1] = true end for i,state in ipairs(BUTTON_STATE) do local v=i-1 local yButton=v//5 local xButton=v%5 local x=20+xButton*40 local y=20+yButton*40 drawButton(v,x,y,38,38,state) end drawFinger(40,50) tButtonLast=tButton end end rift_scenesboxopengood1=function() local M=math local S,C,POW,PI,ABS,MIN=M.sin,M.cos,M.pow,M.pi,M.abs,M.min local TAU=PI*2 local tSceneF=0 function BDR2(y) local fl=tSceneF if y>=0 and y<136 then fadeColour(0, 255-y,20,60+y, 255,255,255,fl) fadeColour(1,150,90,220,255,255,255,fl) fadeColour(2,10,70,150,255,255,255,fl) fadeColour(3,0,30,80,255,255,255,fl) end end function doSceneBoxOpenGood1(t) cls() tSceneF=t BDR=BDR2 CAM.y=2-2*t CAM.x=0 CAM.z=CAM_Z_EXPLODE-2*t CAM.ry=t*TAU*2 local def=getBoxDef() drawObj(def) end end rift_scenesboxopenbad2=function() local M=math local S,C,POW,PI,ABS,MIN=M.sin,M.cos,M.pow,M.pi,M.abs,M.min local TAU=PI*2 local firstEntry=true function doSceneBoxOpenBad2(t) tMin=math.min(t,1) cls() BDR=BDR0 if firstEntry then music(0,-1,-1,false) firstEntry=false end CAM.y=1-tMin*1 --1+S(t)*2 CAM.x=0 CAM.z=CAM_Z_EXPLODE+tMin*(CAM_Z_NEAR-CAM_Z_EXPLODE) CAM.ry=t*TAU*2 local ps={} -- a little pile of dust local yBase=-1 local nLayers=10 local layerHeight=.05 for iLayer = 1,nLayers do local y = yBase+layerHeight*iLayer local layerDensity = 1 - (iLayer/nLayers) local r = layerDensity * .9 local nPsInLayer = (layerDensity + 1) * 20 for i = 1,nPsInLayer do local a=i/nPsInLayer * TAU local x=S(a)*r local z=C(a)*r table.insert(ps, {x=x, y=y+S(i)*layerHeight*.5, z=z, c=15}) end end local def=getBoxSideDef() trM(def, 0,-1,0) drawObj(def) draw(ps) for i=0,10 do local x=120+S(i*.1+t*5)*5+S(i+t*30)*10 local y=80-(t*200+i*10)%30 circ(x,y,3,15) end local animSpeed=4 local yBase=120 local yLine=yBase-ABS(S(t*animSpeed)*10) local yFlex=yBase-8-ABS(S(t*animSpeed-.2)*10) printOutline("ToDay is not the day!", 10,yLine) printOutline("^", 20,yFlex) end function printOutline(t,x,y) print(t, x+1,y+1,15, false,2) print(t, x,y,12, false,2) end end rift_3d=function() local M=math local S,C,POW=M.sin,M.cos,M.pow function tr(p,x,y,z) p.x,p.y,p.z=p.x+x,p.y+y,p.z+z end -- Translate model function trM(m,x,y,z) for i,p in ipairs(m.ps) do tr(p,x,y,z) end end function rX(p,r) local s,c,y,z=S(r),C(r),p.y,p.z p.y=y*c-z*s p.z=y*s+z*c end function rY(p,r) local s,c,x,z=S(r),C(r),p.x,p.z p.x=x*c-z*s p.z=x*s+z*c end function rZ(p,r) local s,c,x,y=S(r),C(r),p.x,p.y p.x=x*c-y*s p.y=x*s+y*c end function pp(p, cam) local zD=(cam.z-p.z)/10 p.px=120+(p.x-cam.x)/zD*10 p.py=68-(p.y-cam.y)/zD*10 p.pz=zD end function bezier(t, p0, p1, p2, p3) local c = 3 * (p1 - p0) local b = 3 * (p2 - p1) - c local a = p3 - p0 - c - b return ((a * POW(t, 3)) + (b * POW(t, 2)) + (c * t) + p0) end function drawTri(p1,p2,p3, t1,t2,t3) ttri( p1.px,p1.py, p2.px,p2.py, p3.px,p3.py, t1.x,t1.y, t2.x,t2.y, t3.x,t3.y, 0,-1, p1.pz,p2.pz,p3.pz ) end end rift_crapt=function() -- Returns a block (to send into decraptToMem) -- len is in bytes function encraptFromMem(addr,len,key) local encStr="" for i=0,(len-1)*2 do local v=peek4(addr*2+i) local swizzle=getSwizzle(key,i) encStr=encStr..string.format("%x",(v+swizzle)&0xf) end return {a=addr,e=encStr} end -- in: a (addr), e (encoded) function decraptToMem(block,key) local a,enc=block.a,block.e for i=0,#enc-1 do local hex=enc:sub(i+1,i+1) local asc=tonumber(hex,16) local swizzle=getSwizzle(key,i) poke4(a*2+i,(asc-swizzle)&0xf) end end function encraptStr(inStr,key) local outStr="" for i=1,#inStr do local asc=string.byte(inStr,i) local swizzle=getSwizzle(key,i-1) outStr=outStr..string.format("%02x",(asc+swizzle)&0xff) end return outStr end -- TODO: check this works for even and odd length strings function decraptStr(inStr,k) local outStr="" local iSwizzle=1 for i=1,#inStr,2 do local hex=inStr:sub(i,i+1) local asc=tonumber(hex,16) local swizzle=getSwizzle(k,iSwizzle-1) local c=string.char((asc-swizzle)&0xff) outStr=outStr..c iSwizzle=iSwizzle+1 end return outStr end -- Returns the swizzle (a 0-255 number value), using key at pos i function getSwizzle(key,i) local iSwizzle=1+(i%#key) local swizzleCh=key:sub(iSwizzle,iSwizzle) return ((((i&0xffff)^2)+string.byte(swizzleCh)^3)//1)&0xff end end rift_sceneswalkback=function() local M=math local S,PI,ABS=M.sin,M.pi,M.abs local TAU=PI*2 local yLastBounce=0 function doSceneWalkBack(t) cls() local bounces=4 local yBounce=ABS(S(t*PI*bounces)*.5) CAM.y=2-yBounce CAM.x=S(t*PI*bounces+PI/2)*.25 CAM.z=CAM_Z_NEAR+t*(CAM_Z_EXPLODE-CAM_Z_NEAR) CAM.ry=t*TAU*2 if yBounce > yLastBounce then sfx(0,35,2) end local def=getBoxDef() drawObj(def) yLastBounce = yBounce end end rift_scenesboxopengood2=function() local M=math local S,C,POW,PI,ABS,MIN=M.sin,M.cos,M.pow,M.pi,M.abs,M.min local TAU=PI*2 local firstEntry=true function doSceneBoxOpenGood2(t, fn) cls() BDR=BDR0 if firstEntry then music(1) firstEntry=false end CAM.y=C(t*.7)*1 --1+S(t)*2 CAM.x=S(t)*2 CAM.z=CAM_Z_EXPLODE+MIN(t/2,1)*(CAM_Z_NEAR-CAM_Z_EXPLODE) CAM.ry=t*2+S(t)*.5 ARGS={t=t,TAU=TAU,S=S,C=C,ABS=ABS,draw=draw} fn() end end package.path = package.path .. ";/Users/matthew/Development/tic80/2024-fieldfx-tic-80-boom/?.lua" -- gasman KEY=nil PIN_ENTRY_STARTED=false TYPED=false local DATA=nil local FN=nil CAM={x=0,y=0,z=0,rx=0,ry=0,rz=0} CAM_Z_FAR=20 CAM_Z_NEAR=3 CAM_Z_EXPLODE=6 BDR=nil NOT_YET_OPEN=true FN=nil FADE=1 rift_3d() rift_crapt() rift_date() rift_draw() rift_scenes() rift_scenesintro() rift_sceneswalkup() rift_scenespinentry() rift_sceneswalkback() rift_scenesboxopengood1() rift_scenesboxopengood2() rift_scenesboxopenbad1() rift_scenesboxopenbad2() function BDR0(y) if y>=0 and y<136 then local bgR,bgG,bgB=255-y,20,60+y setRGB(0, bgR,bgG,bgB) fadeColour(1,bgR,bgG,bgB,150,90,220,FADE) fadeColour(2,bgR,bgG,bgB,10,70,150,FADE) fadeColour(3,bgR,bgG,bgB,0,30,80,FADE) end end function setRGB(c,r,g,b) local a=16320+c*3 poke(a,r) poke(a+1,g) poke(a+2,b) end function doEncrapt(key) -- patterns (0x11164) [11520] -- pattern = 3 bytes * 64 rows = 192 bytes e=encraptFromMem(0x11164+192, 8*192, key) -- trace(e.e) -- tracks (0x13E64) [408] -- 51 bytes per track e=encraptFromMem(0x13E64+51, 51, key) exit() end function doDecrapt(key) -- patterns (0x11164) -- 3 bytes per row * 64 rows * 8 patterns = 15360 decraptToMem({a=0x11164+192, e="5241624912415a496aa11a9112411a1f7397aa4968411a495132624912411a4912d11a9112411a4912419e5fba411a4912411a4d58411c6912411a4912411a4912411a491281109112411a4912415a496aa11a9112411a2f73979a4968411a495132624912411a4912f11a9112411a491241ae5fba411a4912411a4d58411a4912411a4912411a4912411a4912411a49c241504912411a4912411a4912411a491241aa4958411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912daabab12411a491241ca4974411a4912411a0912a31a4912411a49e2417c4912415a4976411a4912411a8912a57a4976411a4912411ab912a51a4912411a4992417e4912411a4912811aad12411a4912415a4974411a4912411aa912a31a4912b11aab92417c491241aa4974411a4912411ad912a3ca4974411a4912411a0912a31a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a491286acd312411a4912415a49ac411a4912411a4912411a4912411a495241a44912415febac86bcd312411a4912415a49ac411a4912411a4912411a4912411a495241a44912411a4912811ad312411a4912415a49ac411a4912411a4912411a4912411a495241a44912411a4912869cd312411a8ea4db1a4912411a495241a44912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a495241624912415a496a811a9312411abf73995a496a411a49e132b24d58411a4912411a49a247624912411a4912c00b9112411a2f7397a0aa68433a497132b24d58411e8912411a49f24762491241fa496a111a9112411a491241aa496a411a4912411ad912991a4912e11a91c24162491241ae596a411a4912411a4d52411a4912411a4912411a4912411a4912411a49c241504912411a4912411a4912411a491241aa4958411a4912411a4912411a4912411a4912411a4912411a4912411a495241964912415e8a84800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84800bbb12411a4912415a499e411a4956828c8803b31a4912411a495241964912415e8a84411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a49e2417c4912411a4912daabab12411a491241ca4974411a4912411a0912a31a4912411a49e2417c491241fa4974411a4912411a2912a35a4976411a4912411a9912a51a4912411a4972417e4912411a4912811aad12411a4912415a4974411a4912411aa912a31a4912b11aab92417c491241aa4974411a4912411ad912a3ca4974411a4912411a0912a31a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a491285acd312411a4912415a49ac411a4912411a4912411a4912411a495241a44912417dcbac411a4912411aa912db1a4912411a4968d3a44912411a491297acd312411a4912411a491286acd312411a4912415a49ac411a4912411a4912411a4912c49cd312411a4912411a4912869cd312411a8ea4db1a4912411a495241a44912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4"}, key) -- tracks (0x13E64) -- 51 bytes at offset 51 decraptToMem({a=0x13E64+51, e="3e455ba939831a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912411a4912421"}, key) CODE=decraptStr("9bfe7384021644b9441fdf0e41443068f413b0a18f9a53923f76172ed20ab4f99b3ef3440256c46c328d49a35ea87dd99b5e33a482f6844c32ad89f9de4838b99b787313c19361fafdd0b4808a2838ecb196b3212bd3501834e310910297ed88ffa2f3ca0fde17a9fbc22523684d728dd2c7e4cb2a76d3cc322e4494f9c66773ced35668f4d87771320b8ef482a5294bbdf396c874782751322bce540245e92bb1dc8debaa17d1294591547182e8a8d9f36138b590f784f3dab685130d7f3202ff8569131552943cfd82df895e1d1ca5b1ab8164823549f1fda21eae04b4b079f48fb6deca8aae924503463d8628ada704d73635497ad795f13d9c6e04f230390acf318402158991fd02dece8494f019f4ef76fe4a6aee32db0bd11ec14df84bfa42e901abf3186a338e497f8ae8b71e0366ecb194b68464497f8709cd3a7dd6d2644bf4cf7d4cfffba3b65874e818bae65c6c6a503834183af018e4ca83ae87c77ce7c20ccfecb5f11c21347b26649ccea3f63e4a2a6ece3f26443bab06737cf2fe248fe40b92ad3d47d7ce526ae403fd21a7e28d6a526c3270085d064ddd16c202a4eb0d59076a3d4247b28fdeb01ed92f27a28cefac13027056d1ab8673fcf27e240fe796853636bba14251dacee50095a56d4130500a3ee7ecae04bbefbed97cb293d68aaef54005453d415da5a7f5de29135e6dc5d436144e5fd9ba0e7f0004248af3e755753f25c5ff85a6296cb116b3a12b535098346310110217ed2bc040c7420f4e106e44420e7162cc8b0cbf46059641946df3daae931402862411ce5356e8f45877f1328b8e74822828e5f684640b2a36530c32eec4ebde9bd6a0e480c7890293ceec3210483d864c64439ad833334173bda602ee927402086885f6055d4105194453daebd000849b30190aefa7e28caf2c49fc2207520f3ef03ed9f2ae010a43d377148352b58ddfb712b1fccd4a95ebc65536708d1f147f760db98277cdc1a59c06498e848a5e33f0990b6fbe2d412d21da03ffcd91ab63e9c7f5728e6aab73d1b6f10850328e5f64439ad833334173bda602ee92770dfb717eeab26890c1b42d523d51c7f28d5a3d36f413afe6696a0f49346312550d3fccf9bcf2ea4d02570951f14c04ba7aa9b2fffd5331a67aaa8f09ff7344bbaa237008f47370c1026d85370ec3841b2ac330e8f493b021850725fb18d5d2c4c9c3dd84d2a4cbb4cfdecebdfacc1201561a4e429aeae4fe41828494f1037678f4c84741f2d5658fc1d5448a2329b7bf9564f529b1dd64ea7a741752fb66c4fbaae3fef9cef2fe01cc0ae55b187512a449db871aff12ef6162dcab3cffb64ee2d13a2fb9fa6b2ed4ca5488e9db6b6d85821c30debf9bb274863c58d141f5d0911cd2c1d1bd72fd9e1a96c4030e1c10f1843778b6ba92ceca8678c889db279295c1a40d23d2e44b74cf0e96aa480ad4044a5ace029b1eb3e482b6048a3f6b1144113fe93dce06a4eb0d59076a3d425d9382eda9f6c224f4612bf6d34c32ae442aed8372fece8b4602148f510a23a9b73f62fc17a1d2848b544f1d0cea23c9f79f1584e5c7fabfd7d106cf08b2fbd314fa4104b0a8f4d330e19a50d0ce49ff9d73020d6946c9bf4573e8fd528a13358cd273811727e4da85d3689d129dfb63125a0e2df43ef636b10fd313ce3a014b045b91ecad27054139b58df3d24ef9646c12118a7db9e581460a139e8c2d32db85334ddaf7a9bdab906a8f2f0dc9dbf216da0fced3ce05beedcf0692c6e7f3ce0402513270b2d7de29394a", key) FN=load(CODE) end function BOOT() local utime=tstamp() local d=dateFromUnix(utime) KEY=keyFromDate(d.month,d.day) end function fadeColour(i,r0,g0,b0,r1,g1,b1,fade) setRGB(i, r0+(r1-r0)*fade, g0+(g1-g0)*fade, b0+(b1-b0)*fade) end function TIC() poke(0x3ffb,0) -- Remove mouse if not PIN_ENTRY_STARTED then for i=27,36 do if keyp(i) then KEY=KEY:sub(2,4)..string.char(i+21) TYPED=true end end end local scene = getScene() if scene.id == 'intro' then BDR=BDR0 doSceneIntro(scene.tUnit) elseif scene.id == 'walk-up' then BDR=BDR0 doSceneWalkUp(scene.tUnit) elseif scene.id == 'pin-entry' then PIN_ENTRY_STARTED = true BDR=BDR0 doScenePinEntry(scene.tUnit) elseif scene.id == 'walk-back' then BDR=BDR0 doSceneWalkBack(scene.tUnit) elseif scene.id == 'box-open' then if NOT_YET_OPEN then doDecrapt(KEY) NOT_YET_OPEN=false end if FN then doSceneBoxOpenGood1(scene.tUnit) else doSceneBoxOpenBad1(scene.tUnit) end else if FN then doSceneBoxOpenGood2(scene.tUnit, FN) else doSceneBoxOpenBad2(scene.tUnit) end end --]] if (not PIN_ENTRY_STARTED) and TYPED then print(KEY,0,0,12) end incT() end