fffffffffffffffffffffffffffffffffffff"ffff"f!fffffffffffffffffff&ff&ffffffffffffffffffff&fffff"!fffaffff!fffffffffffffffffbfffafff!3333wwW4TDE5ETT4DEE3TT3#33#"13331wwG1wTD1GET1TDD1D4313333313W5qwE5qGT3qT53AU3#AD#"133333wGwtDEETTTDEEDDD43433333""""""2##""2""""""2"""2"#"2"""""""""""""fffffffffffff"ffffffff!"ffffffffffffffffffffffffffffVffV3V3333333ffffffffffffffff3333333333333333ffV3f633f33333333333333333333333Sfff3cff33ef33333333333333333333ffffffffffffffffSfff33ef333e333313331wwG1wDD1GDD1uww1tww1Dww1Dww3333wwW4TGE5DDT4wwE5wWE4wUD5WUT4333WwGEwTW5E3#333qwwDGQWAUD3""""2#2"#""2"#"""#"""#"2""""""""ffffffffffffffffffffDDDDDDDDDDDDffffUUUUUUUUUUUUUUUUUUUUffffffff""""""""""""""""""""""""""""""""fffff3""#"""""""""""""""""""""""ffff""3f"""2""""""""""""""""""""ffffffffUUUUUUUUUUUUUUUUffffffffffffffffffffUUUUUUUUUUUUffffffffffffffffffffffffUUUUUUUUffffffffffffffffffffffffffffUUUUffffffff13331wwG1wDD1GDt1EDw1DDw1Dtw1Dtw3333wwW4TGE5EDT4UDD5UDD4UED5UET41Dtw1Dtw1DDw1DDw1DDt1CDD1333UED5UED4UDD4UDD3ED4#D33"3#""3WET5413D1#DD3wwW31UD1D4#3""""""2##""2""""""""2#""#"""""""333333333333333333333333333333333333""""""""""""""""""""3333""""ffff""""""""""""""""""""ffffffff""""""""""""""""#"""f3""ffffffff"""""""""""""""""""2""3fffffffff3333V333ffV3fffVffffffffffffffff33333333333333333333f333f633ffV33333333333333333333333ef3cffSfff3333333e33efSfffffffffffffffffff1Dw71Dw31t731D331DDD1CDD1333SUD53UD43SE433D3DD4#D33"3#""339wGtIITIID443393333WywET9U)AI#"913331wwG1wtD1GWD1uET1WDE1DTD1DDD3333wwW4TGE5ETT4DEE5TTT4DDE5DTT4ffffiifiifffiffffifffgfwofgwfffffoffwfggwwwww"""wtwDwDGDGDDD""""BwwGwGDDDDGDDBCCC"""DDDDDD4DDD444333"""DBwDBG4BDDBD3B3313331wwG1wtD1GWD1uED1WD41DD31D433333wwW4TGE5EDT4CDD53DD43CD533D41DTD1DET1TDE1DTD1DDD1CDD1333DDE5DTT4DEE4DDD3DD4#D33"3#""ff633c#""2""""""2"""2"#"2"""""wvfvwwwwwwgwwfwgwwwwwwwwgwwwwDDD4DDD4BDDB44B33fff&fffff&fff&{fw&K4hffffffhffsffsDhf4f33h")IBBBBB1D331DU31DUU1DUU1DUU1DUU1DUU1DUU33C43sG4swG4uwG4uwG4uwG4uwG4wwG4ffffffffffffffffffffffffffffffffffffffffffffffffjfvvwfwwwfffwffffffffffffffffwwwwgwwwffwffffffffffffffffwwgwwwfwwffgffffffffffffffffffffffffggw"""DBwBBBB9"""DIBBDCfHwfDffHffffffffffff"""K+hwf7hfBff"hfffffhfff"""3331DUw1Dtw1DDw1DDt1DDD1CDD1333wwG5wwT4wGE4wDD3GD4#D33"3#""fffffffffffffffffʬfʬf̪ʬʬ̪̬̪ʬʪʬ̪jfjffffjwwwvwfwwffwwwwwwwwwwwwwwwwwwwwwgwwfwffwgwgfvwffffffffffffffffffff"BBBBD3B33"ID333"""DB"33")IBBBBB")IBBfʪʬfʪfffʪffffffffffgfwffffffggwffffffffffwfgwwwffffffffffffffffffffffffffffffffiffiffffiiififfffffffffffffffff""""ffffaaaaffffffffffffffffffffjiiffffffiffiffifififfffffffffiffiffiiffhffffffiffffffffffffiffifffiffffffffffffffffff6#(2)("ffI92#"))"hffhD39#"")""ffffffffffffffff3fb"f""(ffffffffffff!fff!f!ffffaffffffaff!ffaf!faaa!a!affiffffiffifffffffffffffiffiffifhffifhifiihfffffffffifffffffffffffifi(K)$I()()KI$"()"999##B")""IDB#4B)#"""DI$IB#9"D$)D#44""KB4")DI#4)")ffffffffffffffffafafffafffffaffffffffffffffffffffffffffffffffffffffffffffffffhffiffiffifffffiffiffffffffffffffffffffffffffffffffff(#4#)BB((K($""(""KKD44B#)B")"IB)DB($""""DK$DBI"4""DD$4#3""4B"#("3I#(""("(#4##B"B((((2#K(2"$""(("KKD4B4B#B#B""""KDBD$DB4"$""""DK$DBD#4B4"""DDK$D$D"4"4""4B"#"(#(44B"#"""(KDKDIDK93K33D93C3C93DDDDDDDD33D433DDDDDDDIDI4N4DNDIKD;K43335533S3333333335533S3333333333333333333S3333533#%33BE3#DE33DE3#DD333333333335"2S3D$R"DETDDTTDDTDD33333SS333532333$233D$33DD23DD33(K)$I()()3(ffffff999##B")""ID")#DI$IB#9"3##"hKB4"))"hffffff3䙙3䙙9C34N4NI333CI3333CC9CIDI>INDID>INI3䙙39C93D3CDD4N4N33DD33DDSSCD353D2333$233D$33DD333CDD33DD3"DD3CDD33DD3"DD3DDD3CDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD43DD33D433D$23DD33D433D$33DD2333DD33DE3#TD#BTDBETDDTTDDTDDDDDDDD33DD33DD23DE$2DTD$DTDDDTDDDDDD>N9C49NC3D3D9CD3CD9KKDKDKDDDDDI>IIIIDDDDDD9C3D3DD43DD43DD$3DDD2CDD$3CDD55DDS3DD33DD33CD33DD33CD355C3S3333333333DDDDDEDEDTTDDTTDDTDDCD4333333333DD43DDD3DD43D433D5533S3333333333DDDDDDDDDDDDDDDDDDDDCDDD3DDD33DDDDDDDDDDDDDDDDDDDDD4DD43DD33DD33Zf1ffffffffffffffffffffffcffaacfffffffffffffffffffffffffffffffffff1ffffffffffffffffffffffaff1cffffffffffffffffffffffffffffffffffff1ffffffffffffffffffffffaffaac1fffffffffffffffffffffffffffffffffffffff1f1fffaa1ffffffffffffffffafffaffffffcfffffff1f1ffa1ffffffffffffcfff1ffffffcff1fffffff1f1fffcaa1ffffffffffffffffffffcfffaffffffffffffffffffffffff6ff11f1f6ffaffff1ff1ffffffffffffffffffffffffffffffffffffff6ff1aff1f1f6ffafffffffffffffffffffffffffff6fffffffffffff6ffcff1f1f6ff1ffafffcffffffffffffffffffffffffffofoffkffffffffffffffffffffokffofoffff ̬ fffffooofffffofoffffgffwgfwwfwgwwwffffffffffffffffgfffwwgfwwfffffffffffffffffffffwfwwwwwffwfwvwwwwwwofofovwffgw?    ;<;;  ;  VHduHFXHWFGXHEXGFGEHEFG00000000^_O    ;;  ;;; VFduEHduFGWFGXEdwhheUEUFG/0000000000000000000000000lmno/ -.-.-.   <;  <  VFGteUHthheGWvhuUteFGthheGd000000000000000000000000000000|}~ +,     ; )* <;< VEHFGtheFdhuHEWXGFEGXGFGFEthu/000000000000000000000000000000/ ;; )*  ;; 9:  << VEUEHUdvyFXUHEUEWuFGUFxheFGUdhh000000000000000000000000000000 <;<;<;9:-.-.-. <;<  <HUFdhhyXXEXHFUGUHFGFEGXGthhvuFG000000000000000000000000000000;<; IJ <<;    ;;;  +,;;hhhuEEXXXUXdhheGEGFGUFXFGFduFGF/000000000000000000000000000000ίί/ ;YZ ;<IJ ;;<;<;<; UFGUUFxywvyXUUthhFGdhhuGFGXEGFG ͮͮ ;;ij <; YZ    HdhhedwzzzvweHHHHGFteFGFGFthvheήή ;<;-.<; ij  -.-. hyGEtwwzzzXGXEdeEeGFXGFGFGFduFt//  <;;  ;;    IJ UtedhhhzzzyUthuthuFduFGdheGxeGd  ;<<;; ;<  ;)* YZ  HEXuGHFXHXtheEGEHFGXEdhuFthuXdu/̭̭/  ;;<  ;<9:ij  fUXdhhhyHXGFXUEUgheXUXGFGFGUXthͮͮ -.-.)*  ;< ;< -.  )* ftuFGdudwhhuHUgFxuEXFGFGFEXFG   9:  ;<;<   9:  fFGUXEteEUFGgGXGduGFGFdhuGF//)*)*)*)*)*;)*)*)*)*)*fFduUHXUFGgFthweFGFGXEGFG̭̭9:+,9:9:+,9:9:+;<:9:+,9:9:+,9:fteGHXGHgGFdhuGFdhuUFGF    ;<;;  ;  FGXEGFduGFEGFG/    ;;  ;;; GFXUFGtheGUFGF̭ -.-.-.   <;  <  FGXEGFGFXFEGFGͮ/ +,     ; )* <;<  ;; )*  ;; 9:  <<  <;<;<;9:-.-.-. <;<  <$̭/;<; IJ <<;    ;;;  +,;;$#$"$3$ ;YZ ;<IJ ;;<;<;<; 3"2$#""$""$"ή ;;ij <; YZ    4"3"2432$32"#"214ͮ/ ;<;-.<; ij  -.-. $3$"#$#4#""124ͮ  <;;  ;;    IJ #4#2$"#4#432"2$""4̭/  ;<<;; ;<  ;)* YZ  31243""#2"$3""  ;;<  ;<9:ij  "#2$""4324"" -.-.)*  ;< ;< -.  )* 3243""""/   9:  ;<;<   9:  ""$""$)*)*)*)*)*;)*)*)*)*)*#""""""$#""""$9:+,9:9:+,9:9:+;<:9:+,9:9:+,9:@AcAcBPCCCDCCDCCCCCAAB/ATCCCCQ@AcBpCCSTCCDCCSDCCCCBPCCCCCDCQA@ACCCCAcAB`PCCCqr`abpCCCCCA/PCCCCSTCCQQABCCCCDCCCCRpCSrb@CCCCCCCB@TCCCCCCDCCCQQBACCCCDDCCCCCB@cB`bACCCCDCCCCBCCCCDCCSTCCDQQR@CCCCSSTCCCCCCCAcACCCABABAAcAcCCCSSTCCCCCCAA/PCCCSTCCCDCSCCQrPCCCCCCCCCCCDCCCCCCCCCCCCCApqQCCCCCCCCDCCCCCCCCCC@TCCCCCCSSCCCDCCDBCCCCCSCCCSSTCCCCSCCCDCCRCCCCDB`apCCDCDSTDCDCCDCDDT@DDSCCDCCCCCDSTCDDQ@CCCDCSCDDCCCCCCDCCDCSTDCCBCCCSTR`PTDTDSTCTCDTSTTDpQTSCSSCDCSSTDCQDQQrPCCSTCCSTCDDCCCSTCSTCCSTCQrCCCCCCApSTSqpCSCSTqTSTT`ab`abpTCCCCCSDTCrpCCCSCCCCSTSSSCSSCCCSSSQSrpCCCCDCCAB`aab`b`aab`bpq`aaaaab`ab`aabpCSDQQR`b`aaPSQr`aabpCCSTCCDCA`aaaab`ab@CCCDDTCCCAABACCCSTTCCCDCCBCCCCAACCCSTCCCCDDTCCR@CCTCCDCCC`aabpCCSSTTCCCCAAB`aapCTTCQrpCCCCCCCCCCCCB`aaab000000000000000000000000000000000000000000000000000000000000000856785""8560""6785858565#2$#""5"""324""$$#""#12$#""3#2"24""$3$324"3$43""12$42#"3"21$4""4"3"4#44((((((((((((((((((((((((((((((((((((((((((((('''''''''''''''''''''''''''''''''''''''''''''''''''''&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PCCCDCCDCCCCCAA`abPQQaaab@AAAA`bCCCCDCCCCB@TCCCCCCDCCCQQpDQQaDQCCCCSTR`PTDTDSTCTCDTSTTDCCCSTr@DDSCCDCCCCCDSTCDDQBpCCSTCCDCCCDCCCCB`ab@ATCCCCQBAB@AABAAACCCSSTCCCCCCAA@CCCCDCCSTCCDQQRAA`ab`bpCCCCCCABpSTSTpCSCSTTTSTTSCSTrpQTDCSTCDCSSTDCQDQQr`PCCCDr`abpCCCCCApCCCCCDCQAACCCCCCCSCCCApQQCCCCCCCCDCCCCCCCCCCCCAABPCCCSTCCCDCSCCQr@CCCCCCCB@pCCCCDCCA`aab`b`aab`bpQb`ab`ab`abpTCCCCCQSTCrpCCrb@CCCCCCCBPCCCCSTCCQQAB`pCCCSCCSTCCCCDB`apCCDCDSTDCDCCDCDDTCCCCCB@TCCCCCCSSCCCDCCDB@CCCCCCCCCCCBpCCSTCCDCAB`sasasb`abv-- title: Fallspire -- author: petet and sintel -- desc: demo for botb -- script: lua abs=math.abs min=math.min max=math.max cos=math.cos sin=math.sin rand=math.random rseed=math.randomseed sqrt=math.sqrt function clamp(x,a,b) return max(a,min(b,x)) end function round(v,d) local m=10^(d or 0) return math.floor(v*m+0.5)/m end function smoothmin(a,b,k) --thank you iq for everything you do k=k or 0.1 local h=max(k-abs(a-b),0)/k return min(a,b) - h*h*k/4 end function smootherstep(x) if x<=0 then return 0 elseif x>=1 then return 1 else return 6*x^5 - 15*x^4 + 10*x^3 end end function easeout(x,q) q=q or 100 if x<=-1.570796*q then return -x-0.570796*q elseif x>=0 then return 0 else return -q*(cos(x/q)-1) end end local palette={} for i=0,47 do palette[i]=peek(0x3fc0+i) end local function fade(amt) for i=3,47 do poke(0x3fc0+i,clamp(palette[i]+amt,0,255)) end end local camera={x=0,y=0,z=0,xtilt=0,ytilt=0,ztilt=0} local function scanline_offset(amt) poke(0x3ff9,amt) end local function palette_index(inds) inds=inds or {} for i=1,#inds do poke4(0x03ff0*2 + i,inds[i]) end for i=#inds+1,15 do poke4(0x03ff0*2 + i,i) end end local leaf={} leaf.r={12,3,14,6,12,5,14,5,12,6,14,3,12} leaf.th={0,0.1,1.22,1.57,2.09,2.62,3.14,-2.62,-2.09,-1.57,-1.22,-0.1,0} local function leaf_offset(x,y,ang,xs,ys,off,col,warp) warp = warp or 0 if y - abs(ys)*14 > 136 then return end local r=max(leaf.r[1]+off,0) local a=leaf.th[1]+ang local xp=x+r*cos(a)*xs local yp=y+r*sin(a)*ys-(r/14)^2*warp local xx,yy for i=2,13 do r=max(leaf.r[i]+off,0) a=leaf.th[i]+ang xx=x+r*cos(a)*xs yy=y+r*sin(a)*ys-(r/14)^2*warp tri(x,y,xp,yp,xx,yy,col) rp=r xp=xx yp=yy end end local function maple_leaf(x,y,ang,xs,ys,warp) xs=xs or 1 ys=ys or 1 leaf_offset(x,y,ang,xs,ys,0,9,warp) --leaf_offset(x,y,ang,xs,ys,-2,10) leaf_offset(x,y,ang,xs,ys,-4,11,warp) end local function leaf_ripple(x,y,ang,xs,ys,rad,w,mag,u,v) local rp,a,c,s,x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6 u=u or 0 v=v or 68*8 w=w or 5 rp=max(leaf.r[1]+rad,0) a=leaf.th[1]+ang c=cos(a)*xs s=sin(a)*ys x2=x+rp*c y2=y+rp*s x1=x2+w*c y1=y2+w*s x3=x2-w*c y3=y2-w*s for i=2,13 do rp=max(leaf.r[i]+rad,0) a=leaf.th[i]+ang c=cos(a)*xs s=sin(a)*ys x5=x+rp*c y5=y+rp*s x4=x5+w*c y4=y5+w*s x6=x5-w*c y6=y5-w*s textri(x1,y1,x2,y2,x4,y4, x1+u,y1+v,x2+u+mag//2,y2-mag+v,x4+u,y4+v,true) textri(x2,y2,x4,y4,x5,y5, x2+u+mag//2,y2-mag+v,x4+u,y4+v,x5+u+mag//2,y5-mag+v,true) textri(x3,y3,x2,y2,x6,y6, x3+u,y3+v,x2+u+mag//2,y2-mag+v,x6+u,y6+v,true) textri(x2,y2,x6,y6,x5,y5, x2+u+mag//2,y2-mag+v,x6+u,y6+v,x5+u+mag//2,y5-mag+v,true) --line(x2,y2,x5,y5,6) x1=x4 y1=y4 x2=x5 y2=y5 x3=x6 y3=y6 end end local function tree1(x,y) map(1,1,20,16,x,y,6) end local function tree2(x,y) map(22,1,13,16,x,y,6) end local function tower_repeat(x,y) for i=y-64,-64,-64 do map(58,0,1,8,x,i) end end local function cloud_repeat(x,y) map(60,34,30,17,x%240,y%136,6) map(60,34,30,17,x%240-240,y%136,6) map(60,34,30,17,x%240,y%136-136,6) map(60,34,30,17,x%240-240,y%136-136,6) end local function tower_top(x,y) map(92,1,4,30,x,y,6) end local function bgtree1(x,y) map(0,24,14,10,x,y,6) end local function bgtree2(x,y) map(14,23,12,11,x,y,6) end local function title(x,y,index) x=x or 0 y=y or 0 index=index or 10 palettes={{6,6},{5,6},{4,5},{11,7},{15,15},{7,15},{12,15},{11,7},{10,7},{9,12}} index=clamp(index,1,10) palette_index(palettes[index]) map(31,19,28,11,x+8,y+16,6) palette_index() end local function terrain1(x,y,h) h=h or 8 local xmod=(x%240) map(60,0,30-xmod//8,h,x%240,y,6) map(60+29-xmod//8,0,xmod//8+1,h,x%8-8,y,6) end local function terrain2(x,y,h) h=h or 9 local xmod=(x%240) map(60,8,30-xmod//8,h,x%240,y,6) map(60+29-xmod//8,8,xmod//8+1,h,x%8-8,y,6) end function scene_pond() local s={} local t=0 local ytilt=0.5 local timer=120 local leaves={} local ripples={} local pan1_time=500 --adjust according to scene timing local pan2_time=1000 local title_time=pan2_time+200 function s.leaf(s,x,y) table.insert(leaves,{x=x+camera.y/8,y=y,z=150-camera.y,ang=rand()*3.14,dz=-0.75, warp=5,da=(rand()-0.5)*0.02}) end function s.ripple(s,x,y,ang) leafBloop() table.insert(ripples,{x=x,y=y,ang=ang,t=0}) table.insert(ripples,{x=x,y=y,ang=ang,t=-20}) table.insert(ripples,{x=x,y=y,ang=ang,t=-40}) end function s.TIC(s) cls(6) timer=timer-1 if timer <= 0 and t < title_time-60 then rseed(t) s:leaf(rand(-20,120),rand(80)) timer=sin(t)*50 + max(240-t/5,90) end camera.y=-100*smootherstep((t-pan1_time)/400) -300*smootherstep((t-pan2_time)/400) ytilt=0.7+max(camera.y/200,-0.5) --map() --bgtree1((0+t*0.8)%480-240,64) --bgtree2((192+t)%480-240,64) --tree1((0+t*2.2)%480-240,32) --tree2((192+t*2)%480-240,32) t=t+1 map(0,68,30,17,0,-camera.y) for i=1,#ripples do local r=ripples[i] local rt=r.t r.t=rt+1 if rt>0 then leaf_ripple(r.x,r.y*ytilt-camera.y,r.ang,1,ytilt,rt/2,5,5-rt/40,0,68*8+camera.y) end end for i=#ripples,1,-1 do if ripples[i].t>199 then table.remove(ripples,i) end end for i=#leaves,1,-1 do local l=leaves[i] l.z=l.z+l.dz l.ang=l.ang+l.da l.x=l.x+0.1 l.y=l.y+0.05 if l.z<=1 then l.z=1 if l.dz ~= 0 then l.dz=0 s:ripple(l.x,l.y,l.ang) end if l.warp>1 then l.warp=l.warp*0.95 end else l.warp=l.warp+sin(t)*0.3 l.z=l.z l.x=l.x+cos(t/60)/3+0.1 l.y=l.y+sin(t/70)/5 if l.y < 5 then l.y = l.y+(5-l.y)*0.2 end end leaf_offset(l.x,l.y*ytilt+l.z-camera.y,-l.ang,1,-ytilt,0,8,-l.warp) if l.x>280 then table.remove(leaves,i) end end end function s.SCN(s,row) if row>=camera.y then scanline_offset(sin((row+camera.y)/3+time()/200)*2) else scanline_offset(0) end end function s.OVR(s) local yy=-camera.y*0.6-ytilt*150 terrain1(0,yy,(-yy-camera.y)//8-1) yy=-camera.y*0.8-ytilt*50 bgtree1(0,-80+yy) bgtree2(14*8,-88+yy) rect(0,yy,240,-yy-camera.y-2,2) tree1(8,-136-camera.y) rect(0,-8-camera.y,240,8,1) line(0,-camera.y-1,240,-camera.y-1,2) for i=1,#leaves do local l=leaves[i] maple_leaf(l.x,l.y*ytilt-l.z-camera.y,l.ang,1,ytilt,l.warp) end if t>title_time then title(0,0,(t-title_time)//5) end end return s end function scene_forest() local s={} local t=0 local pan_duration=1100 local title_vanish_time=340 function s.TIC(s) cls(6) camera.x=400-3*easeout((t-pan_duration),200) camera.y=-easeout(t-400,200) palette_index({1,2,3,4,5,6,7,8,9,10,7,7,13,14,7}) map(21,35,26,12,-camera.x//8+t//20,20-camera.y//8,6) palette_index({1,3,4}) map(0,34,20,12,120-camera.x//7-t//10,30-camera.y//7,6) tower_repeat(120-camera.x//6,120-camera.y//6) map(21,35,26,12,-camera.x//6+t//8,45-camera.y//6,6) palette_index({1,2,4,4,11}) terrain1(-camera.x//4+100,80-camera.y//4) palette_index({1,2,3,4,4}) terrain1(-camera.x//2,95-camera.y//2) palette_index() local xp,yp xp=-(2*camera.x)//3 yp=-(2*camera.y)//3 if camera.x<0 then bgtree1(xp%360 - 120, 56+yp) bgtree2((xp+100)%360 - 120, 44+yp) bgtree1((xp+230)%360 - 120, 52+yp) else bgtree1(xp - 120, 56+yp) bgtree2(xp +100 - 120, 44+yp) bgtree1(xp +230 - 120, 52+yp) end spr(257+((t//15)%3)*3,600-camera.x,120-24-camera.y,6,1,0,0,3,3) terrain2(-camera.x,120-camera.y) palette_index({1,1}) xp=-camera.x yp=-camera.y if camera.x<0 then tree1(xp%700 - 200, 8+yp) tree2((xp+240)%700 - 200, 8+yp) tree1((xp+370)%700 - 200, 16+yp) --tree3((-camera.x+230)%360 - 120, 52) else tree1(xp - 200, 8+yp) tree2((xp+240) - 200, 8+yp) tree1((xp+370) - 200, 16+yp) --tree3((-camera.x+230) - 120, 52) end palette_index() t=t+1 end function s.SCN(s,row) end function s.OVR(s) if t=camera.ytilt+10 then scanline_offset(sin(50*math.log(row-camera.ytilt)-time()/20)*(40+row-camera.ytilt)/60) else scanline_offset(0) end end function s.OVR(s) palette_index() local ty,u,v,z local horizon=camera.ytilt for i=max(horizon+10,0),136 do z=sf*(camera.y)/(i-horizon) ty=-camera.z - z u=ty*0.2+sin(ty/100)*50+120+(((ty//32)*3)%8)*240 v=119*8+ty%32 textri(0,i,240,i,240,i+1, u-z,v,u+z,v,u+z,v,true,14) end end return s end function scene_tower_base() local s={} local t=0 local ascend_time=400 function s.TIC(s) palette_index() camera.x=-easeout(t-500,400) camera.y=-40+30*smootherstep(t/ascend_time)-(2*easeout(ascend_time-t,200))//1 cls(6) palette_index({1,2,3,4,5,6,7,8,9,10,7,7,13,14,7}) cloud_repeat(-camera.x//5,-camera.y//5) palette_index() cloud_repeat(-camera.x//3+100,-camera.y//3+50) terrain1(-camera.x//2,30-camera.y//2) rect(0,64+(-3*camera.y//4),240,80,11) if camera.y>-68 then tri(104-camera.x,68-camera.y,120-camera.x*2,136-camera.y*2,170-camera.x*2,136-camera.y*2,4) tri(136-camera.x,68-camera.y,220-camera.x*2,136-camera.y*2,170-camera.x*2,136-camera.y*2,4) tri(104-camera.x,68-camera.y,136-camera.x,68-camera.y,170-camera.x*2,136-camera.y*2,3) end map(92,25,4,9,104-camera.x,-camera.y,6) local i=-camera.y while i>0 do i=i-56 map(92,18,4,7,104-camera.x,i) end palette_index() t=t+1 end function s.SCN(s,row) scanline_offset(0) end function s.OVR(s) end return s end function scene_tower() local s={} local t=0 local bird={x=100,y=68} local palette_indexes={ {8,8,8,3,4,6,3}, {8,2,3,4,11,6,3}, {8,2,4,4,11,6,4}, {8,2,4,4,11,6,11}, {8,2,4,4,11,6,7}, {8,2,3,11,11,6,7}, {8,2,3,11,4,6,11}, {8,2,3,4,4,6,11}, {8,2,3,4,4,6,11}, {8,2,3,4,4,6,4}, {8,2,3,4,3,6,4}, {8,2,2,3,3,6,4}, {8,2,2,3,2,6,4}, {8,2,8,2,8,6,3}, {8,2,8,8,8,6,3}, {2,2,8,8,8,6,3}, {2,2,8,8,8,6,3}, {2,2,8,8,8,6,3}, {2,2,8,8,8,6,3}, {2,2,8,8,8,6,3}, {2,2,8,8,8,6,3}, {2,2,8,8,8,6,3}, {8,2,8,8,8,6,3}, {8,8,8,8,3,6,3} } function s.TIC(s) t=t+1 bird.x=100 --bird.x=120+sin(t/100)*60 --bird.y=30-cos(t/125)*10 cls(6) --map(120,0) local tx,ptx,as,pp,ang --ang=240+100*sin(t/100)+t/2 --ang=240.1+t/2+20*sin(t/100) ang=240.1+t/2 ptx=0 palette_index({1,2,3,4,5,6,7,8,9,10,7,7,13,14,7}) cloud_repeat(ang*.5+120,t/5) palette_index() cloud_repeat(ang*1+t*0.3,t/2) local rad=76/2 local xoff=120-rad local flicker=0.5 if btn(4) then flicker = 0 end for i=0,rad*2 do as=math.asin(i/rad-1) pp=(i/rad-1) pp=pp*abs(pp) tx = 120*8+(240+rad*as+ang)%240 ty = 136-(t%136) --if (ptx//4 ~= tx//4) then palette_index(palette_indexes[ (((120-bird.x)/20+(t%2)*flicker+5*as)//1 + 6) % #palette_indexes + 1]) --end textri(i+xoff,0,i+xoff+1,136,i+xoff+2,0, tx,ty,tx,ty+136,tx,ty, true) ptx=tx end end function s.SCN(s,row) scanline_offset(0) end function s.OVR(s) palette_index() --enable for bird sprite --spr(464,bird.x-16,bird.y-12,0,1,0,0,4,3) end return s end function scene_tower_top() local s={} local t=0 function s.TIC(s) palette_index() cls(6) local interp=smootherstep((t+400)/800) palette_index({1,2,3,4,5,6,7,8,9,10,7,7,13,14,7}) cloud_repeat(t/4+120,interp*200/5) palette_index() cloud_repeat(t/2+t*0.3,interp*200/2) tower_top(120-16,-160+200*interp) t=t+1 end function s.SCN(s,row) end function s.OVR(s) end return s end local function tree_distance_field(x,y,z) y=(y-20)*1.25 local dist1=sqrt((x+15)^2+y^2+z^2)-45 local dist2=sqrt((x-15)^2+(y-30)^2+(z-10)^2)-25 local dist3=sqrt((x-15)^2+(y-40)^2+(z+15)^2)-20 return smoothmin(smoothmin(dist1,dist2,10),dist3,10) end local function in_trunk(x,y,z) local r=sqrt(x^2+z^2) return r^2+y<160 end local tree_model={} local function model_tree() local dist,grad,xx,yy,zz,res,sp res=12 math.randomseed(1) for x=-60,60,res do for y=-45,0,5 do for z=-60,60,res do r=sqrt(x^2+z^2) xx=(x)*20/(y+60)+rand(-3,3) yy=y+rand(-1,1) zz=(z)*20/(y+60)+rand(-3,3) if in_trunk(x,y+45,z) then table.insert(tree_model,{x=xx-10,y=yy,z=zz,sp=352+rand(0,1)*2}) end end end end for x=-60,60,res do for y=-60,60,res do for z=-60,60,res do xx=x+rand(-5,5) yy=y+rand(-5,5) zz=z+rand(-5,5) dist=tree_distance_field(xx,yy,zz) if dist<0 and dist>-20 then grad=tree_distance_field(xx+1,yy-2,zz+1)-dist sp=324 if grad>0.5+rand()*3 then sp=320 elseif grad<-1-rand()*3 then sp=328 end table.insert(tree_model,{x=xx,y=yy,z=zz,sp=sp+2*rand(0,1)}) end end end end end model_tree() function depthsort(a,b) return a.z>b.z end function scene_tree() local s={} local t=0 local octagon_x={68,28,-28,-68,-68,-28,28,68} local blow_away_time=1300 octagon_x[0]=68 function s.TIC(s) palette_index() cls(6) local points={} local theta,phi,cc,ss,cph,sph,x1,y1,z1,x2,y2,z2,texoffset theta=t/100 phi=sin(t/100)/4+0.5 camera.x=0 camera.y=easeout(t-800,100)/4-easeout(t-400,100) cc=cos(theta) ss=sin(theta) cph=cos(phi) sph=sin(phi) cloud_repeat(-120*theta,-120*phi) local tower_coords={} for i=1,8 do x1=octagon_x[i%8] y1=-45 z1=octagon_x[(i+2)%8] x2=x1*cc-z1*ss z2=x1*ss+z1*cc y2=y1 y1=y2*cph+z2*sph z1=-y2*sph+z2*cph x1=x2 table.insert(tower_coords,{x=120+x1-camera.x,y=67-y1-camera.y,z=z1}) end x1=tower_coords[1].x y1=tower_coords[1].y for i=1,8 do x2=tower_coords[i%8+1].x y2=tower_coords[i%8+1].y texoffset=(i%2)*80 if x1>x2 then textri(x1+1,y1,x2,y2,x1+1,y1+160*cph, 200*8+texoffset,0,207*8+texoffset,0,200*8+texoffset,160,true) textri(x2,y2+160*cph,x2,y2,x1+1,y1+160*cph, 207*8+texoffset,160,207*8+texoffset,0,200*8+texoffset,160,true,6) end x1=x2 y1=y2 end local floorwidth=68 local floorcoords={120-camera.x+floorwidth*cc-floorwidth*ss, 68-camera.y-(floorwidth*cc+floorwidth*ss)*sph + 45*cph, 120-camera.x+floorwidth*cc+floorwidth*ss, 68-camera.y-(-floorwidth*cc+floorwidth*ss)*sph + 45*cph, 120-camera.x-floorwidth*cc+floorwidth*ss, 68-camera.y-(-floorwidth*cc-floorwidth*ss)*sph + 45*cph, 120-camera.x-floorwidth*cc-floorwidth*ss, 68-camera.y-(floorwidth*cc-floorwidth*ss)*sph + 45*cph} textri(floorcoords[1],floorcoords[2], floorcoords[3], floorcoords[4], floorcoords[7], floorcoords[8], 180*8,0,197*8,0,180*8,17*8,true,6) textri(floorcoords[5],floorcoords[6], floorcoords[3],floorcoords[4], floorcoords[7],floorcoords[8], 197*8,17*8,197*8,0,180*8,17*8,true,6) for i=1,#tree_model do p=tree_model[i] x1=p.x y1=p.y z1=p.z --wind if p.sp<350 then x1=x1+cos(x1/30+t/20)*(y1+40)/20+easeout(blow_away_time-10*x1-t,100) z1=z1+sin(x1/40+z1/30+t/30)*(y1+40)/20 end x2=x1*cc-z1*ss z2=x1*ss+z1*cc y2=y1 y1=y2*cph+z2*sph z1=-y2*sph+z2*cph x1=x2 table.insert(points, {x=x1-camera.x, y=y1+camera.y, z=z1, sp=p.sp}) end table.sort(points,depthsort) local p for i=1,#points do p=points[i] spr(p.sp,112+p.x,56-p.y,0,1,0,0,2,2) end t=t+1 end function s.SCN(s,row) end function s.OVR(s) end return s end function scene_tower_top_2() local s={} local t=0 local blow_away_time=-100 local shake_time=300 function s.TIC(s) palette_index() cls(11) local interp=easeout(t-100,100)/2 palette_index({1,2,3,4,5,6,7,8,9,10,7,7,13,14,7}) cloud_repeat(t/4+120,interp/5) palette_index() cloud_repeat(t/2+t*0.3,interp/2) local shake=0 if t>shake_time then shake=(t//4)%2 end map(98,2,4,17,120-16+shake,50+interp,6) local blow for i=1,#tree_model do p=tree_model[i] if p.sp<350 then blow=easeout(blow_away_time-10*p.x-t,100) spr((p.sp-320)//2+306,p.x*0.35+120+blow*(1+0.5*cos(t/60+p.z)), -p.y*0.35+62+interp+blow*(0.2*sin(t/100+5*p.z)),0) end end t=t+1 end function s.SCN(s,row) end function s.OVR(s) end return s end function scene_tower_collapse() local s={} local t=0 local color_change_time=300 local plants={} function s.plant(s) table.insert(plants,{x=rand(240),y=rand(104,128),h=0}) end function s.TIC(s) cls(11) camera.x=400 --camera.y=-easeout(t-400,200) camera.y=0 palette_index({1,2,3,4,5,6,7,8,9,10,7,7,13,14,7}) map(21,35,26,12,-100+t//20,20,6) palette_index({1,3,4}) map(0,34,20,12,120-t//10,30,6) palette_index({1,3,4}) --tower_repeat(120-camera.x//6,120-camera.y//6) local angle=max(-(t//10)/200,-0.2) local towerx,towery,h,cc,ss,x1,y1,x2,y2,x3,y3,x4,y4 towerx=60+(t//4)%2 towery=80+(t*t/2000) h=40*8 cc=-cos(angle) ss=-sin(angle) x1=towerx-ss*h y1=towery+cc*h x2=towerx+cc*8-ss*h y2=towery+ss*8+cc*h x3=towerx y3=towery x4=towerx+cc*8 y4=towery+ss*8 textri(x1,y1,x2,y2,x3,y3, 103*8,0,104*8,0,103*8,h,true,6) textri(x4,y4,x2,y2,x3,y3, 104*8,h,104*8,0,103*8,h,true,6) map(21,35,26,12,t//8,45,6) if t>color_change_time then palette_index({1,2,10,10,10}) else palette_index({1,2,4,4,4}) end terrain1(-camera.x//4+100,80-camera.y//4) if t>color_change_time+20 then palette_index({1,2,9,10,10}) else palette_index({1,2,3,4,4}) end terrain1(-camera.x//2,95-camera.y//2) if t>color_change_time+60 then palette_index() local pl if t%20 == 0 and #plants<500 then s:plant() end for i=1,#plants do pl=plants[i] line(pl.x,pl.y-pl.h,pl.x,pl.y,5) pl.h=min(pl.h+pl.y/10000,16) end end if t>color_change_time+40 then palette_index({8,9,9,10,10}) else palette_index() end spr(257+((t//15)%3)*3,600-camera.x,120-24-camera.y,6,1,0,0,3,3) terrain2(-camera.x,120-camera.y) palette_index() t=t+1 end function s.SCN(s,row) end function s.OVR(s) end return s end function Filter(par) local par = par or {tp = "lp", g = 0.5, r = 0.5, h = 0.5} local state_1_, state_2_ = 0,0 public = { update = function (fr,res) local f = fr if f >= 0.49 then f = 0.49 end if f < 0 then f = 0 end if res < 0.001 then res = 0.001 end par.g = math.tan(math.pi*f) par.r = 1.0 / res par.h = 1.0 / (1.0 + par.r * par.g + par.g * par.g) end; process = function (input) local hp, bp, lp hp = (input - par.r * state_1_ - par.g * state_1_ - state_2_) * par.h bp = par.g * hp + state_1_ state_1_ = par.g * hp + bp lp = par.g * bp + state_2_ state_2_ = par.g * bp + lp if par.tp == "bp" then return bp*par.r elseif par.tp == "hp" then return hp else return lp end end; reset = function() state_1_, state_2_ = 0,0 end; } return public end Voice = {} local exp = math.exp local sin = math.sin function Voice:new(index) local new = {} setmetatable(new,self) self.__index = self new.index = index new.t = 0 new.wave = {} for i = 0,31 do new.wave[i] = 8 end new.volume = 0 new.freq = 0 new.algo = 0 new.decay = 0.02 new.vibd = 0 new.vibs = 0.4 new.filter = Filter() return new end function Voice:init() sfx(0,36+self.index*3,-1,self.index) end function Voice:update() self.volume = self.volume*(1-self.decay) local w = {} self.filter.update(.5,1.0) if self.algo == 0 then self.filter.update(0.15 + 0.1*sin(global_time*0.01),1.0) for i = 0,31 do if self.t == 0 then w[i] = self.wave[i] + (i*2)%32/32 elseif self.t == 7 then w[i] = self.wave[i] + 0.8*((i*3)%32/32) else w[i] =self.wave[i] end end elseif self.algo == 1 then self.filter.update(0.9*exp(-(self.t)*0.06),1.0) for i = 0,31 do w[i] = (i + (i+math.floor(self.index + global_time*0.20))%32 + (i+math.floor(self.index - global_time*0.24))%32)/(3*16) end elseif self.algo == 2 then self.filter.update(200/(self.freq*32)+0.1,1.0) for i = 0,31 do if self.t == 0 then w[i] = math.random()*1.5 else w[i] = self.wave[i]*0.92 + 0.07*(0.5*self.wave[i] + 0.25*self.wave[(i+1)%32] + 0.25*self.wave[(i-1)%32]) + 0.08*(0.5-math.random()) end end elseif self.algo == 3 then for i = 0,31 do self.vibd = 0.02*(1-exp(-(self.t)*0.12)) w[i] = 0.7*sin(2*math.pi*(i/32.0) + 1.2*sin(5*math.pi*(i/32.0))*exp(-(self.t)*0.08)) end elseif self.algo == 4 then self.filter.update(0.1 + 0.05*sin(1+global_time*0.01),1.2) for i = 0,31 do w[i] = 0.5*sin(2*math.pi*(i/32.0) + 2*sin(4*math.pi*(i/32.0))*exp(-(self.t)*0.04)) end elseif self.algo == 5 then self.filter.update(math.min(0.5,0.02+self.t/1000),1.7) local r = math.random() local r2 = math.random() local r3 = math.random() for i = 0,31 do if r3 < 0.1 then w[i] = self.wave[i] +r2*0.1*sin(2*math.pi*r2+(1+math.floor(r*5))*2*math.pi*i/32) else w[i] =self.wave[i]*0.98 end end elseif self.algo == 6 then self.filter.update(0.3 + 0.25*sin(self.index+global_time*0.01),1.2) local v = self.t%(spd*3) for i = 0,31 do self.vibd = 0.02*(1-exp(-(self.t)*0.12)) w[i] = 0.4*sin(2*math.pi*(i/32.0) + 1.2*sin(5*math.pi*(i/32.0))*exp(-(self.t)*0.03))*(0.5+0.5*exp(-(v)*0.08)) end elseif self.algo == 7 then self.filter.update(0.9*exp(-(self.t)*0.007)*(1-self.index*0.2),1.7) for i = 0,31 do self.vibd = 0.02*(1-exp(-(self.t)*0.005)) w[i] = i/48 end end local mean = 0 for i = 0,31 do self.wave[i] = w[i] w[i] = w[i]*self.volume mean = mean + w[i] end local max = 0 for i = 0,31 do w[i] = w[i] - mean/32 w[i] = self.filter.process(w[i]) max = math.max(max,math.abs(w[i])) end for i = 0,31 do local o = math.floor(8+8*w[i]/max) if(o > 15) then o = 15 end if(o < 0) then o = 0 end poke4(0x1FF3C+36*self.index+i,o) end local vol = 1.0 vol = vol * max vol = math.floor(16*vol) if(vol >= 15) then vol = 15 end poke4(0x1FF3B+36*self.index, vol) local f = math.floor(self.freq*(1+self.vibd*sin(global_time*self.vibs+self.index))) poke(0xFF9C+18*self.index,f&0xff) poke4(0x1FF3A+36*self.index,f>>8) self.t = self.t + 1 end function Voice:play(note,algo) self.t = 0 self.volume = 1 self.freq = 440*math.pow(2,(note-10)/12) self.algo = algo self.vibd = 0 self.vibs = 0.4 self.decay = 0.02 if algo == 0 then self.decay = 0.05 self.vibd = 0.01 elseif algo == 1 then self.decay = 0.02 elseif algo == 2 then self.decay = 0.0 self.vibd = 0.007 self.vibs = 0.2 elseif algo == 3 then self.decay = 0.03 self.vibd = 0.02 self.vibs = 0.8 elseif algo == 4 then self.decay = 0.04 self.vibd = 0.01 elseif algo == 5 then self.decay = 0.0 elseif algo == 6 then self.decay = 0.005 self.vibd = 0.02 self.vibs = 0.8 elseif algo == 7 then self.decay = 0.003 end for i = 0,31 do self.wave[i] = 0 end end clock = 0 global_time = 0 spd = 12 bspd = 12 vce = 0 count = 0 width = 240 height = 136 function newSeq(numvc,l,t,spd_) local s = {} s.l = l s.numvc = numvc s.spd = spd_ s.t = t return s end function playSeq() seq = seqs[seqind] if seq then for i=1,seq.numvc do local t = {} tracks[i].transp = seq.t[i][1] or tracks[i].transp tracks[i].ind = seq.t[i][2] or tracks[i].ind tracks[i].instr = seq.t[i][3] or tracks[i].instr tracks[i].div = seq.t[i][4] or tracks[i].div end bspd = seq.spd or bspd else final = true end end function init() math.randomseed(time()*10000) local r = false pattern = {} pattern[1] = {4,7,11,4,7,11,7,14} pattern[2] = {14,7,11,6,r} pattern[3] = {0,r,14,r} pattern[4] = {12,7,11,6,r} pattern[5] = {10,5,3,r,7} pattern[6] = {5,7,10,3,7,10,7,14} pattern[7] = {-12,7,14,16,r,r,r,r} pattern[8] = {-12,7,14,15,r,r,r,r} pattern[9] = {-9,7,14,15,r,r,r,r} pattern[10] = {4,0,-1,-5,-1,0} pattern[11] = {0,4,7,11,7,4} pattern[12] = {3,1,-2,-5,-2,1} pattern[13] = {1,5,7,11,7,5} pattern[14] = {4,2,-1,-5,-1,2} pattern[15] = {7,4,2,-2,2,4} pattern[16] = {0,4,7,14,7,4} pattern[17] = {0,r,r} pattern[18] = {r,2,3,10} pattern[19] = {r,2,4,11} pattern[20] = {r,1,4,11} pattern[21] = {r,1,4,10} pattern[22] = {r,4,11,7,9,11,18,r} pattern[23] = {0,-12,r,r,r} pattern[24] = {-24,0,9,r,r,r,r,r,r,r,r,r,r} pattern[25] = {-24,3,14,22,r,r,r,r,r,r,r,r,r,r,r,r} seqs = {} seqs[-1] = newSeq(1,90,{{-3,24,5,16}}) seqs[0] = newSeq(1,32,{{-3,25,7,2}},8) seqs[1] = newSeq(3,32,{{-12,1,0,1},{0,2,3,4},{-24,3,1,4}},12) seqs[2] = newSeq(3,32,{{},{0,4},{-27}}) seqs[3] = newSeq(3,32,{{-13},{-1},{-28}}) seqs[4] = newSeq(3,32,{{-13,6},{-1,5},{-25}}) seqs[5] = newSeq(3,32,{{-14},{-2},{-26}}) seqs[6] = newSeq(1,16,{{-11,7,2,2}}) seqs[7] = newSeq(1,16,{{-9}}) seqs[8] = newSeq(1,16,{{-7,8}},13) seqs[9] = newSeq(1,16,{{-7,9}},14) seqs[10] = newSeq(2,24,{{13,10,4,1},{-11,11,0,1}},17) seqs[11] = newSeq(2,24,{{13,12},{-11,13}},15) seqs[12] = newSeq(2,24,{{11,14},{-13,11}}) seqs[13] = newSeq(2,24,{{9,15},{-15,16}}) seqs[14] = newSeq(2,16,{{9,18,6,2},{-15,17,6,4}},14) seqs[15] = newSeq(2,16,{{8,19},{-16}}) seqs[16] = newSeq(2,16,{{6},{-18}}) seqs[17] = newSeq(2,16,{{6,20},{-12}},15) seqs[18] = newSeq(2,16,{{6,21},{-24}},16) seqs[19] = newSeq(2,32,{{-7,22,6,4},{-19,23,6,16}},16) seqind = -1 voices = {} for i = 0,3 do voices[i] = Voice:new(i) voices[i]:init() end tracks = {} for i = 1,4 do local t = {} t.transp = 0 t.ind = 1 t.div = 1 t.instr = 0 tracks[i] = t end --seq = seqs[seqind] playSeq() end init() function updateMusic() clock = clock + 1 global_time = global_time+1 if seq then local h = seq.l/2 local s = ((((count)%seq.l)-h)/h)^4 spd = bspd if seqind < 14 then spd = math.floor(bspd + 10*s) end if(clock >= spd) then clock = 0 if count == seq.l then count = 0 seqind = seqind + 1 playSeq() if seqind == 0 or seqind == 3 or seqind == 5 or seqind == 7 or seqind == 9 or seqind == 10 or seqind == 14 or seqind == 16 then nextScene() end end trig() end end for i = 0,3 do voices[i]:update() end end function trig() if seq then for i = 1,seq.numvc do local note = getNote(tracks[i].ind,tracks[i].div) if note then voices[vce%4]:play(note+tracks[i].transp,tracks[i].instr) vce = vce + 1 end end end count = (count + 1) end leafind = 1 function leafBloop() if leafind < 7 then local tb = {-3,4,9,11,13,16} voices[3]:play(tb[leafind]-12,6) leafind = leafind + 1 end end function getNote(n,d) d = d or 1 return pattern[n][(count/d)%(#pattern[n])+1] end local scenes={scene_pond(), scene_forest(), scene_flight(), scene_tower_base(), scene_tower(), scene_tower_top(), scene_tree(),scene_tower_top_2(),scene_tower_collapse()} local scene_number=1 local scene = scenes[1] local fade_amt=0 function nextScene() scene_number=scene_number+1 fade_amt=120 end function TIC() time_start=time() updateMusic() if final then fade_amt=fade_amt-0.5 if fade_amt<-255 then cls(0) trace(" ~fallspire~") trace(" by petet and sintel") trace(" thank you for watching <3") exit() end else scene=scenes[scene_number] fade_amt=max(0,fade_amt-2) end fade(fade_amt) scene=scenes[scene_number] scene:TIC() end function SCN(row) scene:SCN(row) end function OVR() scene:OVR() --print(round(time()-time_start,3),0,0,13) end > 02TvͫgE#2Tv2Tv 0 &!D5Rx`tZ޾_CQ[GňCr9-n, GIF89aw! NETSCAPE2.0!,`t޾&!D5RxH* !C#JHŋ3j@ бɓ(S\qC,cʜIfIIɳϕ8JуAE]ʴ̜ JJ"ԇUj*ׯ`3ٳ6]6[W˾KcܺxJV޿bLXˆN̸-ߠ#VI_<5_B -i+&ͺ5AIָ]oWN\.Μ8rcCnNsߔW>o屹oN;.6<NO4zѹwQ$X%zW~M؝d@&d A(`xbAxۇ!H߈h8hk!(XaD#QhPfX02ie~NF6CW[[)Ꮌ}飘b pJ^w5m aZ[x2|BaBaE"d}W ))DnZ)z'w*3ui*M89'.E+ު(X}+~15lb-xI5F ^ iN}m8i*bS:(Rf":> e\G˝pkvOn_C?N{ġh],Ujg~nk r\9g㉭3kh082D[ t4IRTc@c)COu׾MjQ6 gWuLgMqi)kԾЪ[ jz;KrGv;`P=J|yl;_ Ad87.rzg~x%;cr]˭{֞z'OwqWxk/aj&O778s6S72l;L}E_%tKK8ƿՍusȖ~ק k$ 5}?X/fD8Ⱥyq4 V=mfȺU#C.}HZ; bb;Ɗĸ}l@U%a |[ײ퀆 Ո7n%\RD E6p%]sB `ltEАc CEZqbW'Hz$I"-G͎L'%CΎ$%8,T򖫔%lyXRĥ0s`2oz- -}!c.󚸤⬙MSxͬ'mrS{,$9=hҗ錧2 4y%-h~Ӑ\g:Gn Pl*| mDP#EtEE1rVGMҒkYI%*ΕԟqyLh|k3)$" P T8U:QJPJ)5U&_< ;B5,QVzղ.u $ $y횕Mu񎷸mpKڗծqS+nyK[pX3pi`ΰjaUGLkW\b ,b w8qv`б| H񐗜$;e[d([Ai{*_`>r[/hNLfĚyUpþyxγ 0:eπgyЈNtWF;z>'M5]7N{ӠGMRԨN;