0,]']±>Sï}WÿÍu§ðp8·dºH‘)6o;]ÉA¦ösï÷ôôô”°ÂVl†3'MMt'mmm G'mmmm € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € € €t'mmmmmmmw'mmmmmmm�(M M M M M M Mu'mmmmmmm € € € € € € € € € € € € € € € €p0m m m m� mm m� mm mM mM mm mM mm mM m``````````````````````````8'l l;'l l Ll L l l llLll L Ll L l l llLll l l l ll ll ll llŒ ll lŒ ŒŒŒŒŒŒ lŒ Mm M m m mmMmm M Mm M m l mmMmm m m m mm mm mm mm� mm m� ������ m�`````````````````mmmm m m m m mmmmmmmmmmmmm m m m m m mm m m m m m m mmmmmmm� m m mm mm���m����m m € € € € € € € € € € € € € € € € € € € € € € € € pp p pp p pp p pp p p p ppp ppp pp p p p p p€€€€€€€€€€€€€€€€€€€€pPpppppPppppppPpppppPpppp€€€€€€€€€€€€€€€€€€ € € € € € € € € € € € € € € € €�0 € € € € € € € € € € € € € € € €0–00@€€(€(Ø1p599 = =âþ`ÀaÀeÀedìþàuàuðuðuàuàu ‚`„`ƒp‡ þ¸¸»»P¼PÀ(@Ž@Ž@–@šÐžÐ¢Ð¦ÿ0Ë0ËPÓPÓ<¸?ðððððððÀ ÀÀÌÌÀ ÀÀÌ ðÀ ÀÀÌÌÀ ÀÀÌ ððÀÌÀÀ À ÀÌÀÌÀÀ À ÀÌððÀÌÌÀÌ ðÌ ÌðÀÌÌÀÌ Ì ÌððÀ ÌÀ Ï ÀÌðÀ ÌÀ À ÀÌÿðÀ ÀÀÌÌÀ ÀÌðÿÿÿÿÿÿÿÀ ÀÀÌÌÀ ÀÌððððÿÿÿÿÿðÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝðÿÿÿÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝð Ð Ð Ðÿÿ Ð Ð Ððð »»º»«»»º»«Ð ""!"Ð 33Ððÿ Ð Ð ÐðÌ Ì »ºº««»ºº««Ð "!!Ð 32Ðÿ Ð Ð Ð ÌÌ ««ººª««ººªÐ !!Ð ##Ðÿ Ð Ð Ðð ÌÍ ªªªªªªªªªªÐ Ð ""Ð Ð Ð ÐððÌ ÜÜ ªªªªªªªªªªÐ Ð ""Ð Ð Ð Ðð ÝÝ Ð """Ð 3323#33Ð Ð Ð Ð ÝÝ Ð "!Ð 322##32Ð Ð Ð ÐðÌ Ð !Ð ##22"##Ð Ð Ð Ððð Ð Ð """""""Ð Ð Ð Ðð Ð Ð """""""Ð Ð Ð Ð Ð Ð Ð Ð Ð ÐðÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝððððððÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝðÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝðÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝàîîîîÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝàîîîîîîÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝàÌÌÌìÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝîÌÌÌÌÌÌîðÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝïÌÌÌìÿÿÿÿÿÿÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÎÌÌÌÌÌÌìðððÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝðàÌÌÌìðÿÿðÿÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝðÎÌÌÌÌÌÌìðððÝÝ ÐÝÝðàÌÌÌìÿÝÝ ÐÝÝÎÌÌÌÌÌÌìðÝÝ ÐÝÝàîÎÌìÿÝÝ ÐÝÝÎÌìîîÎÌìÝÝ ÐÝÝðÎÌìÿÝÝ ÐÝÝÎÌÌÌÌÌÌìðÝÝ ÐÝÝÎÌìÿÝÝ ÐÝÝÎÌÌÌÌÌÌìððÝÝ ÐÝÝÎÌìÿÝÝ ÐÝÝÎÌÌÌÌÌÌìðððÝÝ ÐÝÝÎÌìðÝÝ ÐÝÝîÌÌÌÌÌÌìððÝÝ ÐÝÝÎÌìðÝÝ ÐÝÝîîîîîÎÌìððÝÝ ÐÝÝÎÌìÝÝ ÐÝÝÎÌÌÌÌÌÌìððÝÝ ÐÝÝÎÌìðÝÝ ÐÝÝÎÌÌÌÌÌÌìðÝÝ ÐÝÝÎÌìÝÝ ÐÝÝÎÌÌÌÌÌÌìðÝÝ ÐÝÝÎÌìðÝÝ ÐÝÝÎÌÌÌÌÌÌîððÝÝ ÐÝÝîîîÝÝ ÐÝÝîîîîîîîððÝÝ ÐÝÝðÝÝ ÐÝÝðððÝÝ ÐÝÝÝÝ ÐÝÝðððÝÝ ÐÝÝÌ Ì Ì ÌüÌ ÝÝ ÐÝÝÌ Ì Ì Ì Ì ðððÝÝ ÐÝÝ ÝÝ ÐÝÝ ððÝÝ ÐÝÝÌ ÌÌÝÝ ÀÌ ÀÌ ÀÌÌÌÌÌÌÌ ÐÝÝÌ  ÌÌðÝÝ ÐÝÝ ü ÝÝ À ÀÀ ÀÀ ÀÌÀÌÀ ÀÐÝÝ ü ðÝÝ ÐÝÝÌ Ì Ì Ì ÿÿÿÿÝÝ À ÀÀ ÀÀÌ Ì Ì À ÀÐÝÝÌ ÌüÌ Ì ÝÝ ÐÝÝðÿðÿÝÝ ÀÌ ÀÌ À ÀÌÀÌÀÌÌÐÝÝðÝÝ ÐÝÝÌÌ ÌüÌÌ ÿÿÝÝ À À ÀÀÌÌÀÌ ÀÌ À ÀÐÝÝÌ ÝÝ ÐÝÝÀ üÀ ðÝÝ ÐÝÝ ÝÝ ÐÝÝÀ À ðÝÝ ÀÌ ÀÌÀÌ ÌÌÌ ÀÌ ÀÌ ÐÝÝ ÝÝ ÐÝÝÀÌ Ì ÀÌ ÝÝ ÌÌ Ì À À ÀÀ ÀÌÐÝÝ ðÝÝ ÐÝÝÀ ð À ðÝÝ ÌÌ ÀÌÀ À ÀÀ ÀÌÐÝÝ ðÝÝ ÐÝÝÀ ü À ÝÝ ÌÌ Ì À ÀÌÌÀÌ ÌÐÝÝ ððÝÝ ÐÝÝÌ Ì Ì Ì Ì ðÝÝ ÌÀÌÌÌÀ À ÀÀ ÀÌÐÝÝÌ ððÝÝ ÐÝÝÝÝ ÐÝÝððÝÝ ÐÝÝÌÌÌÌÌÌÌÌÌ ÝÝ ÐÝÝÌÌÌÌÌ ðÝÝ ÐÝÝððÝÝ ÐÝÝððÝÝ UUÐÝÝÌ ü Ì Ì ÝÝ ÐÝÝ Ì Ì ÝÝ UVÐÝÝÀ ü ÝÝ ÐÝÝ ÝÝ eeÐÝÝÀ ü ÝÝ ÐÝÝ ÝÝ ffÐÝÝÀÌüÌ ðÝÝ ÐÝÝÌ ÝÝ ffÐÝÝÀ ðÝÝ ÐÝÝ ÝÝ UUVUeÐÝÝÀ ðÝÝ ÐÝÝ ÝÝ UVVeeÐÝÝÌ Ì Ì ÝÝ ÐÝÝ Ì Ì ÝÝ eeVVfÐÝÝÝÝ ÐÝÝÝÝ fffffÐÝÝðÿÝÝ ÐÝÝÝÝ fffffÐÝÝÝÝ ÐÝÝÝÝ PUeÐÝÝÝÝ ÐÝÝÝÝ PeeÐÝÝÝÝ ÐÝÝÝÝ PVfÐÝÝðÿÝÝ ÐÝÝÝÝ `ffÐÝÝÝÝ ÐÝÝÝÝ `ffÐÝÝÝÝ ÐÝÝÝÝ ÐÝÝðÝÝ ÐÝÝÝÝ ÐÝÝðÝÝ ÐÝÝÝÝ ÐÝÝððÝÝ ÐÝÝÝÝ ÐÝÝðÝÝ ÐÝÝÝÝ ÐÝÝðÝÝ ÐÝÝÝÝ ÐÝÝðÝÝ ÐÝÝðÝÝ ÐÝÝððÝÝ ÐÝÝððÝÝ ÐÝÝÝÝ ÐÝÝððÝÝ ÐÝÝÝÝ ÐÝÝððÝÝ ÐÝÝðÝÝ ÐÝÝððÝÝ ÐÝÝðÝÝ ÐÝÝððÝÝ ÐÝÝððÝÝ ÐÝÝðÝÝ ÐÝÝÝÝ ÐÝÝðÝÝ ÐÝÝðÝÝ ÐÝÝÝÝ ÐÝÝððÝÝ ÐÝÝÝÝ ÐÝÝðÿÿÝÝ ÐÝÝÝÝ ÐÝÝðÿðÿÝÝ ÐÝÝðÝÝ ÐÝÝÿÿÿÿÝÝ ÐÝÝðÝÝ ÐÝÝðÝÝ ÐÝÝððÝÝÝÝÝ ÐÝÝÝÝ ÐÝÝððÝÝ=3# îîÐÝÝÝÝ ÐÝÝðððÝÝ=## îïÐÝÝðÝÝ ÐÝÝðððÝÝ=2" þþÐÝÝÝÝ ÐÝÝðððÝÝ-"" ÿÿÐÝÝðÝÝ ÐÝÝðððÝÝ-"" ÿÿÐÝÝÝÝÝ ÐÝÝÝÝ ÐÝÝððÝÝ=3# îîïîþDDCD4 ÐÝÝðÝÝ ÐÝÝðÝÝ=## îïïþþDCC44 ÐÝÝÝÝ ÐÝÝðÝÝ=2" þþïïÿ44CC3 ÐÝÝ Ì Ì ðÝÝ ÐÝÝ ðÌ Ì ððÝÝ-"" ÿÿÿÿÿ33333 ÐÝÝ ÝÝ ÐÝÝ ð ðððÝÝ-""ÝÝÝÝÝÝÝÝÝÝÿÿÿÿÿ33333 ÐÝÝ Ì Ì ðÝÝ ÐÝÝ ðÌ Ì ððÝÝ=3#33RUeUU&"™™èîþDDCD4 ÐÝÝ ðÝÝ ÐÝÝ  ððÝÝ=##32ReeUV&™˜èþþDCC44 ÐÝÝÌ Ì ÀÌ Ì ÿÝÝ ÐÝÝÌ Ì ÀÌ Ì ððÝÝ=2"##RVfee&!‰‰èïÿ44CC3 ÐÝÝÿÝÝ ÐÝÝððÝÝ-""""bffffˆˆøÿÿ33333 ÐÝÝðÌ Ì ÿÝÝ ÐÝÝÌ ðÝÝ-""""bffffˆˆøÿÿ33333 ÐÝÝ ÿÝÝ ÐÝÝ ðÝÝ�™‰UUVUe""!"™™˜™‰™™xw ÐÝÝü ÿÝÝ ÐÝÝ ððÝÝ�‰‰UVVee"!!™˜˜‰‰™˜x ÐÝÝÌ Ì ðÿÿðÿÝÝ ÐÝÝð ðððÝÝ�˜ˆeeVVf!!‰‰˜˜ˆ‰‰xq ÐÝÝ ÿÿÿÿÿÿÝÝ ÐÝÝ ððÝÝ�ˆˆfffffˆˆˆˆˆˆˆ ÐÝÝ ü ÝÝ ÐÝÝ ÝÝ�ˆˆfffffˆˆˆˆˆˆˆ ÐÝÝÌ Ì ÝÝ ÐÝÝÌ ðÝÝ�™‰™™˜™‰""qwwwqwwwqw ÐÝÝðÝÝ ÐÝÝððÝÝ�‰‰™˜˜‰‰"!qwqqwqq ÐÝÝÝÝ ÐÝÝðððÝÝ�˜ˆ‰‰˜˜ˆqqqqqq ÐÝÝðÝÝ ÐÝÝððÝÝ�ˆˆˆˆˆˆˆ ÐÝÝðÝÝ ÐÝÝÝÝ�ˆˆˆˆˆˆˆ ÐÝÝÝÝ ÐÝÝððÝÝ=3#33BD4DD“™‰ww!"""qw ÐÝÝÌ ÌüÌ Ì ÝÝ ÐÝÝÌ Ì Ì ðððÝÝ=##32B44DC“‰‰wq!"!q ÐÝÝ ü ÝÝ ÐÝÝÀÀÌ ðÝÝ=2"##BC344“˜ˆ!!qq ÐÝÝÌ ÿÌÌ ÝÝ ÐÝÝÀÀÌ ÌÝÝ-""""23333ƒˆˆ ÐÝÝ ÝÝ ÐÝÝÀÀ ðÝÝ-""""23333ƒˆˆ ÐÝÝÌÌ Ì Ì ü Ì ÝÝ ÐÝÝÀÌ ÌüðÝݽ»«33BD4DD“™‰™™˜™‰""!" ÐÝÝðÝÝ ÐÝÝðÝݽ««32B44DC“‰‰™˜˜‰‰"!! ÐÝÝÌ Ì ðÝÝ ÐÝÝÌ Ì ÌüÌ Ì Ì Ýݽºª##BC344“˜ˆ‰‰˜˜ˆ!! ÐÝÝ ðÝÝ ÐÝÝ ü ÝÝ­ªª""23333ƒˆˆˆˆˆˆˆ ÐÝÝ ðÿÝÝ ÐÝÝ ðÝÝ­ªª""23333ƒˆˆˆˆˆˆˆ ÐÝÝ Ì ÿÝÝ ÐÝÝ ü ðÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ ðÿÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ ðÿÿÿÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ Ì ðÿÿÿÿÿÿÿÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÌ Ì ðÌ Ì Ì Ì ðÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝðððððððÿððððð/} ll l l€ ll l€l l lll l€l l l lll l l l ll``````````````````` l l ll€ l l l€ l lll l l€ l ll l lŒl ll l l l l ll€ l l l€ l lll l l€ l ll l lŒl ll llm mm m mm mm mm m mm m m mmmM mm mm mm� mm m m p p p p p p p p p p p p p p p p p p p p p p p p pp p p p pÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ€b€b€b€b €b€‚ €b€€€€b€b€B€€b €b€€b €b€b€b €B€€b€€ €b€€€B€€ €b€b€b€b€b€‚`````````````````````€‚ €b€€b€ €b€€b€ €b€‚€b€ €b€€€b€€b€€€b€€b€€b€€B€€€€€€€b€€€b€ €B€€b€b €b€€b€ €b€€b€ €b€‚€b€ €b€€€b€€b€€€b€€b€€b€€B€€€€€€€b€€€b€ €B€€.™   <p€p€� �  ,À,À48âÿ;ù-- title: Master of Blocks 5-X: Devastation -- author: Phoenix Flare -- desc: Go for top rank one last time... -- script: lua -- input: gamepad -- saveid: MoB Devastation -- Copyright 2021-2022 Phoenix Flare -- 5-X Revision 2D function loadcfg() local c=pmem(200) local ver=pmem(255) if c&0x80==0 or ver<100 then cfg={ timer=false, joe=false, pause=true, bga=true, free=true, coin=0, vol={ snd=15, bgm=15, }, } pmem(200, 0xFFCC) pmem(255, 100) initHSTable() return end cfg={ timer=(c&0x1)==1, joe=(c&0x2)==2, pause=(c&0x4)==4, bga=(c&0x8)==8, free=(c&0x40)==0x40, coin=(c&0x30)>>4, vol={ snd=(c&0xF00)>>8, bgm=(c&0xF000)>>12, }, } end function savecfg() pmem(200, (cfg.vol.bgm<<12)+ (cfg.vol.snd<<8)+ 0x80+ (cfg.free and 0x40 or 0)+ (cfg.coin<<4)+ (cfg.bga and 0x8 or 0)+ (cfg.pause and 0x4 or 0)+ (cfg.joe and 0x2 or 0)+ (cfg.timer and 0x1 or 0) ) end function initHSTable() local table={ {[0]=45, 500, 15*60*60, 0x0D0F02, 0, 3}, {[0]=36, 400, 15*60*60, 0x0D0F02, 0, 2}, {[0]=27, 300, 15*60*60, 0x0D0F02, 0, 1}, } for x=0,5 do for y=1,3 do for z=0,5 do if x==4 and z==3 then pmem(x*30+y*10+z-10, 0x093A3B) elseif z==4 then pmem(x*30+y*10+z-10, math.random(3)-1) elseif x==5 and z==2 then pmem(x*30+y*10+z-10, 999) else pmem(x*30+y*10+z-10, table[y][z]) end end end end end function loadHSTable() highScore={} highScore.all={} highScore.today={} for spec=0,5 do highScore.all[spec]={} if spec==4 then highScore.today[spec]={ {[0]=27, 300, 15*60*60, 0x093A3B, math.random(3)-1, 2}, {[0]=18, 200, 15*60*60, 0x093A3B, math.random(3)-1, 1}, {[0]=9, 100, 15*60*60, 0x093A3B, math.random(3)-1, 0}, } elseif spec==5 then highScore.today[spec]={ {[0]=27, 300, 999, 0x0D0F02, math.random(3)-1, 2}, {[0]=18, 200, 999, 0x0D0F02, math.random(3)-1, 1}, {[0]=9, 100, 999, 0x0D0F02, math.random(3)-1, 0}, } else highScore.today[spec]={ {[0]=27, 300, 15*60*60, 0x0D0F02, math.random(3)-1, 2}, {[0]=18, 200, 15*60*60, 0x0D0F02, math.random(3)-1, 1}, {[0]=9, 100, 15*60*60, 0x0D0F02, math.random(3)-1, 0}, } end for pos=1,3 do highScore.all[spec][pos]={} for idx=0,5 do highScore.all[spec][pos][idx]=pmem(spec*30+pos*10+idx-10) end end end end function checkHSPosition(p) local hs={ highScore.all[p.special], highScore.today[p.special], } for t=1, 2 do for x=1, 3 do if p.grade>hs[t][x][0] then p.place[t]=x break elseif p.grade==hs[t][x][0] then if p.level>hs[t][x][1] then p.place[t]=x break elseif p.level==hs[t][x][1] then if (p.special==5 and p.blocksUsed or p.timer)14 and #rnd.bag or #rnd.bag+1) if piece>#rnd.bag then initBag(rnd) return randomDraw(pid) end drawn=true for x=1,4 do if rnd.bag[piece]==rnd.history[x] then drawn=false end end rerolls=rerolls-1 if rerolls==0 or drawn then table.remove(rnd.history, 1) rnd.history[4]=table.remove(rnd.bag, piece) return rnd.history[4] end end end function initQueue(pid) player[pid].next={} for x=1,3 do player[pid].next[x]=randomDraw(pid)+player[pid].rule*7 end end function initGame(pid) initGrid(pid) local p=player[pid] --Block Data initRandomizer(pid) initQueue(pid) p.currentBlock=nil p.heldBlock=nil p.held=false p.slow=0 p.slowActive=false p.amulet=0 p.amuletActive=0 p.emergencyAmuletTimer=0 p.are=30 p.lcf=0 p.ldas=0 p.rdas=0 --UI elements p.timer=0 p.score=0 p.level=0 p.grade=0 p.rollLines=0 p.canIntoTopRank=false --Scoring p.combo=1 p.markedLines={} --Cools p.cools=0 p.ctimer=0 p.cquads=0 p.cspins=0 --Music p.track=-1 end player={} cheats={{}, {}} initPlayer(1) initPlayer(2) menu=-1 idle=600 idle2=0 credits=0 splash=0 function TIC() vbank(0) if splash<315 then cls() vbank(1) cls() vbank(0) splash=splash+1 local fade=math.max(math.min(math.min(splash, 300-splash), 45), 0) poke(0x3FD2, 0x1E*fade/45+0x1A) poke(0x3FD3, 0x9B*fade/45+0x1C) poke(0x3FD4, 0x38*fade/45+0x2C) spr(384, 86, 26, 8, 1, 0, 0, 8, 8) printCenter("GREEN ALPACA", 94, 6) printCenter("SOFT", 100, 6) if splash==315 then poke(0x3FD2, 0x38) poke(0x3FD3, 0xB7) poke(0x3FD4, 0x64) cls() end return end update() drawBackground() if idle<600 and menu==-1 then drawFieldBorder(player[1]) drawFieldBorder(player[2]) end vbank(1) cls(0) for x=0, 2 do poke(0x3FC0+1*3+x, ({0x5D, 0x27, 0x5D})[x+1]) poke(0x3FC0+2*3+x, ({0xB1, 0x3E, 0x53})[x+1]) poke(0x3FC0+3*3+x, ({0xEF, 0x7D, 0x57})[x+1]) poke(0x3FC0+12*3+x, 0xF4) poke(0x3FC0+14*3+x, ({0x56, 0x6C, 0x86})[x+1]) end draw() vbank(0) end function SCN(ln) local t=time() local l=0.5-math.abs((68-ln)/136) for x=0, 2 do poke(0x3FC0+1*3+x, math.floor(l*(math.sin(math.rad(t/18+120*x))+1)*0xFF)) if ln==0 then if (menu~=-1 or idle>=1200) then poke(0x3FC0+12*3+x, (0xCF*peek(0x3FC0+8*3+x))//0xFF) poke(0x3FC0+14*3+x, (0x7F*peek(0x3FC0+8*3+x))//0xFF) else poke(0x3FC0+12*3+x, basePalette[12][x+1]) poke(0x3FC0+14*3+x, basePalette[14][x+1]) end end end for x=1, 2 do local l if player[x].difficulty==4 then l=12 elseif player[x].state=="Versus" or player[x].state=="VersusStart" then l=11 else l=(player[x].level//100+player[x].cools//100)//math.min(4, player[x].difficulty+1)+1 end if l<10 then if ln==0 then local c={ {0x94, 0xB0, 0xC2}, {0x41, 0xA6, 0xF6}, {0xA7, 0xF0, 0x70}, {0xFF, 0xCD, 0x75}, {0xEF, 0x7D, 0x57}, {0xB1, 0x3E, 0x53}, {0xBA, 0x48, 0x91}, {0x1A, 0x1C, 0x2C}, {0xF4, 0xF4, 0xF4}, } for y=0, 2 do poke(0x3FC0+(x+1)*3+y, c[l][y+1]) end end elseif l==10 then if ln>=24 and ln<132 then for y=0, 2 do poke(0x3FC0+(x+1)*3+y, (math.sin(math.rad(180+ln-t/6))*0xFF+0xFF)//2) end end elseif l==11 then if ln>=24 and ln<132 then for y=0, 2 do poke(0x3FC0+(x+1)*3+y, (math.sin(math.rad(120*y+180+ln-t/6))*0xFF+0xFF)//2) end end elseif l==12 then if ln>=24 and ln<132 then poke(0x3FC0+(x+1)*3, math.random(255)) for y=1, 2 do poke(0x3FC0+(x+1)*3+y, 0) end end end end end --Update and Game Logic functions function update() for x=0,3 do local vol=x<2 and cfg.vol.snd or cfg.vol.bgm if peek(0xFF9D+18*x)&0xF0~=0 then poke(0xFF9D+18*x, (peek(0xFF9D+18*x)&0x0F)+((((peek(0xFF9D+18*x)&0xF0)*vol)//15)&0xF0)) end end if not cfg.free then if btnp(20) then credits=credits+({1, 2, 1})[cfg.coin+1] sfx(20, nil, -1, 2) if idle<600 then idle=0 else idle=600 end end if btnp(21) then credits=credits+({1, 2, 1})[cfg.coin+1] sfx(20, nil, -1, 2) if idle<600 then idle=0 else idle=600 end end end if menu~=-1 then return menuUpdate() end if idle>=600 then cheats={{}, {}} if btnp(6) and idle<1200 then idle=1200 end end if idle>=1200 then idle2=idle2+1 if btnp(2) then idle=idle-(idle%300)+(cfg.joe and 1500 or 1200) idle2=0 end if btnp(3) then idle=idle-(idle%300)+300 idle2=0 end end if player[1].state=="Idle" and player[2].state=="Idle" then if (btnp(7, 300, 0) and btnp(15, 300, 0)) or btnp(23) then menu=0 return end idle=idle+1 else idle=0 end if idle>=1500 then if btnp(4) or btnp(12) or idle2==(cfg.joe and 1800 or 1500) then idle=600 idle2=0 end return end for pid=1, 2 do local p=player[pid] local opponent=player[3-pid] local boffset=pid*8-8 if p.state=="Idle" then p.codeTime=p.codeTime+1 for x=0,7 do if btnp(x+boffset) then p.code=((p.code<<3)&0x7FFFFFF)+x p.codeTime=0 end end if p.codeTime==30 then p.code=4 end if p.code==0x124924D then idle=0 cheats[pid][1]=true end if p.code&0x7FFF==0x100D then idle=0 cheats[pid][2]=true end if p.code&0x3FFFF==0x1248D then idle=0 cheats[pid][3]=true end end if p.state=="Idle" then if (cfg.free or credits>=math.max(cfg.coin, 1)) and btnp(4+boffset) and opponent.state~="Config" and opponent.state~="Start" and opponent.state~="Win" then if not cfg.free then credits=credits-math.max(cfg.coin, 1) end initPlayer(pid, true) p=player[pid] p.cheat=cheats[pid] cheats[pid]={} p.state="Config" p.menu=-1 p.menutimer=900 end elseif p.state=="Config" then p.menutimer=p.menutimer-1 if btnp(2+boffset) or btnp(3+boffset) then if p.menu==-1 then p.special=(p.special+5)%10 p.denyversus=not p.denyversus elseif p.menu==0 then p.special=(p.special+(btnp(2+boffset) and -1 or 1))%(cfg.joe and 5 or 4) elseif p.menu==1 then p.reverse=not p.reverse elseif p.menu==2 then p.sonic=not p.sonic elseif p.menu==3 then p.denyversus=not p.denyversus end end if btnp(0+boffset) or btnp(1+boffset) then if p.menu==4 then p.rule=(p.rule+(btnp(0+boffset) and -1 or 1))%3 end if p.menu==5 then if btnp(1+boffset) then p.unlock=p.unlock+1 elseif btnp(0+boffset) then p.unlock=0 end p.difficulty=(p.difficulty+(btnp(0+boffset) and -1 or 1))%(p.unlock<13 and 4 or 5) end end if (p.menutimer==0 and cfg.timer) or btnp(4+boffset) then if p.menu==5 then p.state="Start" initGame(pid) p.menutimer=90 if p.special<5 and opponent.state=="InGame" and not (opponent.denyversus or p.denyversus) then p.state="Challenge" p.menutimer=600 p.menu=0 else sfx(15, nil, -1, pid-1) end else p.menu=p.menu+1 if (p.menu==3 or p.menu==0) and p.special==5 then p.menu=p.menu+1 end p.menutimer=900 end end elseif p.state=="Challenge" then p.menutimer=p.menutimer-1 if btnp(0+boffset) or btnp(1+boffset) then p.menu=(p.menu+1)%2 end if opponent.state=="Start" or opponent.state=="Curtain" then sfx(15, nil, -1, pid-1) p.state="Start" initGame(pid) p.menutimer=90 elseif (p.menutimer==0 and cfg.timer) or btnp(4+boffset) then p.state="Start" p.menutimer=90 if p.menu==1 then sfx(17, nil, -1, pid-1) music() playingMusic=false p.state="VersusWarn" p.menutimer=120 p.cheat=opponent.cheat opponent.state="VersusWarn" opponent.pause=false opponent.menutimer=120 else sfx(15, nil, -1, pid-1) end end elseif p.state=="Start" then p.lineData=nil p.menutimer=p.menutimer-1 p.versus=false if p.menutimer==0 then if p.difficulty<4 then p.track=0 if opponent.track==-1 then music(0) playingMusic=true end else p.track=20 if opponent.track<20 then sync(16, 1) music(0) playingMusic=true end end p.state="InGame" end elseif p.state=="InGame" then gameUpdate(p) elseif p.state=="RollStart" then p.menutimer=p.menutimer-1 p.versus=false if p.menutimer==0 then if not playingMusic then music(p.difficulty<4 and 6 or 2) playingMusic=true end p.rollTimer=2700 p.rollBlocks=100 initGrid(pid) p.state="Roll" end elseif p.state=="Roll" then gameUpdate(p) if (p.special==5 and p.rollBlocks or p.rollTimer)==0 then gameOver(p) p.canIntoTopRank=p.cools>=3000 and p.rollLines>=30 getGrade(p) end elseif p.state=="Curtain" then p.menutimer=p.menutimer+(btn(4+boffset) and 2 or 1) if p.menutimer>99 then if p.wins~=-1 and not (p.cheat[1] or p.cheat[2] or p.cheat[3]) then checkHSPosition(p) if p.place[2]<4 then if opponent.state=="NameEntry" and opponent.special==p.special then p.state="NameWait" return end p.state="NameEntry" p.menutimer=3600 p.menu=1 return end end p.state="GameOver" end elseif p.state=="VersusWarn" then p.menutimer=p.menutimer-1 if p.menutimer==0 then initGame(pid) p.versus=true p.state="VersusStart" p.menutimer=90 end elseif p.state=="VersusStart" then p.menutimer=p.menutimer-1 if p.menutimer==0 then p.state="Versus" music(7) playingMusic=true end elseif p.state=="Versus" then gameUpdate(p) elseif p.state=="Win" then p.menutimer=p.menutimer-1 if p.menutimer==0 then p.state="Start" p.menutimer=90 end elseif p.state=="NameWait" then if opponent.state=="NameEntry" then return end checkHSPosition(p) if p.place[2]<4 then p.state="NameEntry" p.menutimer=3600 p.menu=1 else p.state="GameOver" end elseif p.state=="NameEntry" then p.menutimer=p.menutimer-1 if cfg.timer and p.menu~=6 and p.menutimer==0 then p.menu=6 p.menutimer=300 end if p.menu==6 and p.menutimer==0 then p.state="GameOver" end if p.menu==6 then return end if btnp(2+boffset, 20, 4) then if p.menu<4 then p.name[p.menu]=(p.name[p.menu]-1)%62 else p.menu=(p.menu-3)%2+4 end elseif btnp(3+boffset, 20, 4) then if p.menu<4 then p.name[p.menu]=(p.name[p.menu]+1)%62 else p.menu=(p.menu-3)%2+4 end end if btnp(4+boffset) then if p.menu==4 then p.menu=6 p.menutimer=300 return saveName(p) elseif p.menu==5 then p.menu=3 else if p.name[p.menu]<60 then p.menu=p.menu+1 p.name[p.menu]=p.name[p.menu-1] end if p.name[p.menu]==61 then p.name[p.menu]=0 p.menu=6 p.menutimer=300 return saveName(p) end if p.name[p.menu]==60 then p.name[p.menu]=0 p.menu=math.max(1, p.menu-1) end end end if btnp(5+boffset) then p.name[p.menu]=0 p.menu=math.max(1, p.menu-1) end elseif p.state=="GameOver" then p.lineData=nil p.menutimer=p.menutimer+1 if p.menutimer==400 or btnp(4+boffset) then p.wins=0 p.state="Idle" if p.versus then p.versus=false initGame(pid) end end end end end function menuUpdate() if btnp(0) then menu=(menu-1)%10 end if btnp(1) then menu=(menu+1)%10 end if menu==0 then if btnp(2) or btnp(3) then cfg.vol.snd=math.max(0, math.min(15, cfg.vol.snd+(btnp(2) and -1 or 1))) end elseif menu==1 then if btnp(2) or btnp(3) then cfg.vol.bgm=math.max(0, math.min(15, cfg.vol.bgm+(btnp(2) and -1 or 1))) end elseif menu==2 then if btnp(4) then cfg.timer=not cfg.timer end elseif menu==3 then if btnp(4) then cfg.pause=not cfg.pause end elseif menu==4 then if btnp(4) then cfg.bga=not cfg.bga end elseif menu==5 then if btnp(4) then cfg.free=not cfg.free end elseif menu==6 then if btnp(2) or btnp(3) then cfg.coin=(cfg.coin+(btnp(2) and -1 or 1))%3 end elseif menu==9 then if btnp(4) then cfg.joe=not cfg.joe end end if menu==7 and btnp(4) or btnp(7) then savecfg() reset() end if menu==8 and btnp(4, 300, 0) and btnp(5, 300, 0) and not btnp(4) then pmem(200, 0) reset() end end function gameUpdate(p) for x=0, 209 do local b=p.gridAge[x//10][x%10+1] if b<0 then p.gridAge[x//10][x%10+1]=b+1 end end local boffset=p.id*8-8 if cfg.pause and btnp(7+boffset) then p.pause=not p.pause end if p.pause then if p.state=="Versus" then p.pause=false else return end end if btnp(6+boffset) and p.special==2 and (p.slow>=300 or p.slowActive) then p.slowActive=not p.slowActive end if btn(6+boffset) and p.amulet>4 and p.are<=0 then p.amuletActive=p.amulet//5 p.amulet=p.amulet%5 end if p.slow==0 then p.slowActive=false end if p.slowActive then p.slow=p.slow-1 else if p.state~="Roll" then p.timer=p.timer+1 p.ctimer=p.ctimer+1 else p.rollTimer=p.rollTimer-1 end end p.are=p.are-1 p.lcf=p.lcf-1 p.emergencyAmuletTimer=p.emergencyAmuletTimer-1 if p.lineData then p.lineData[#p.lineData]=p.lineData[#p.lineData]-1 if p.lineData[#p.lineData]==0 then p.lineData=nil end end if btn(2+boffset) then p.ldas=p.ldas+1 else p.ldas=0 end if btn(3+boffset) then p.rdas=p.rdas+1 else p.rdas=0 end if p.lcf==0 or p.emergencyAmuletTimer==0 then clearLines(p) if p.amuletActive>0 and p.emergencyAmuletTimer~=0 then amulet(p) end end if p.emergencyAmuletTimer>0 then return end if p.are==0 then if p.amuletActive>0 then clearLines(p) end spawnBlock(p) if p.level~=1000 and p.state~="Versus" then if p.timer>30 and (p.level%100<99 or p.state=="Versus") then p.level=p.level+1 checkCool(p) end if p.level%100==99 and p.state~="Versus" and not p.levelstopped then p.levelstopped=true sfx(9, nil, -1, p.id-1) end end end if p.currentBlock and p.state~="Curtain" then updateBlock(p) end end function spawnBlock(p) if p.special==5 then if p.blocks==0 then return gameOver(p) end p.blocks=p.blocks-1 end local boffset=p.id*8-8 local nextBlock=table.remove(p.next, 1) p.next[3]=randomDraw(p.id)+p.rule*7 local hold=p.special==1 and btn(6+boffset) local irot=(btn((p.reverse and 5 or 4)+boffset) and 3) or (btn((p.reverse and 4 or 5)+boffset) and 1) or ((btn(6+boffset) and p.special==0) and 2) or 0 if p.heldBlock or not hold then p.currentBlock={ block=(hold and p.heldBlock or nextBlock)+(p.cheat[3] and 21 or 0), rotation=irot, x=5, y=2, gravity=0, resetVal=pieceStartingLD*(p.state=="Versus" and 8 or 15), lifeVal=pieceStartingLD, dropped=0, age=0, idle=0, } local cb=p.currentBlock if not checkPosition(p, 0, 0) then cb.rotation=0 if not checkPosition(p, 0, 0) then cb.block=nextBlock+(p.cheat[3] and 21 or 0) hold=false cb.rotation=irot if not checkPosition(p, 0, 0) then cb.rotation=0 if not checkPosition(p, 0, 0) then return gameOver(p) end end end end if hold then p.heldBlock=nextBlock end else p.currentBlock={ block=p.next[1]+(p.cheat[3] and 21 or 0), rotation=irot, x=5, y=2, gravity=0, resetVal=pieceStartingLD*(p.state=="Versus" and 8 or 15), lifeVal=pieceStartingLD, dropped=0, age=0, idle=0, } if not checkPosition(p, 0, 0) then cb.rotation=0 if not checkPosition(p, 0, 0) then cb.block=nextBlock+(p.cheat[3] and 21 or 0) hold=false cb.rotation=irot if not checkPosition(p, 0, 0) then cb.rotation=0 if not checkPosition(p, 0, 0) then return gameOver(p) end end end end if hold then p.heldBlock=nextBlock table.remove(p.next, 1) p.next[3]=randomDraw(p.id)+p.rule*7 end end sfx((p.next[1]-1)%7+1, nil, -1, p.id-1) p.held=hold end function gameOver(p) if p.amulet>9 then p.amuletActive=p.amulet//10 p.amulet=0 return amulet(p, true) end o=player[3-p.id] p.state="Curtain" if o.track==-1 then sync() music() playingMusic=false elseif playingMusic and o.track1200 and cfg.timer and not cfg.pause then return lock(p) end if btnp(0+boffset) or btnp(1+boffset) or (p.level+(p.cools//100)*100)//(p.slowActive and 2 or 1)<(p.difficulty==4 and 0 or 500) then cb.unsafe=true end if not checkPosition(p, 0, 1) then cb.lifeVal=cb.lifeVal-(pieceStartingLD//getSpeedValue(p, "lockDelay")) if cb.lifeVal<1 or (p.sonic and btn(1+boffset) and (cb.unsafe or btnp(1+boffset))) then return lock(p) end end cb.gravity=cb.gravity+getSpeedValue(p, "gravity") if cb.gravity<256 and btn(1+boffset) then cb.gravity=256 end if btnp(0+boffset) then cb.gravity=5120 end while cb.gravity>=256 do if tryMove(p, 0, 1) and (btn(1+boffset) or btnp(0+boffset)) then cb.dropped=cb.dropped+1 if btnp(0+boffset) then cb.dropped=cb.dropped+1 end end cb.gravity=cb.gravity-256 end if btnp(0+boffset) and not p.sonic then return lock(p) end local dasKicked=false if cb.age>0 then if btnp((p.reverse and 5 or 4)+boffset) then dasKicked=rotate(p, -1) elseif btnp((p.reverse and 4 or 5)+boffset) then dasKicked=rotate(p, 1) elseif btnp(6+boffset) and p.special==0 then dasKicked=rotate(p, 2) elseif btnp(6+boffset) and p.special==1 and not p.held then local irot=(btn((p.reverse and 5 or 4)+boffset) and 3) or (btn((p.reverse and 4 or 5)+boffset) and 1) or ((btn(6+boffset) and not p.special==1) and 2) or 0 local held=p.heldBlock if not held then held=table.remove(p.next, 1) p.next[3]=randomDraw(p.id)+p.rule*7 end p.heldBlock=(p.currentBlock.block-1)%21+1 p.currentBlock={ block=held+(p.cheat[3] and 21 or 0), rotation=irot, x=5, y=2, gravity=0, resetVal=pieceStartingLD*(p.state=="Versus" and 8 or 15), lifeVal=pieceStartingLD, dropped=0, age=0, idle=0, } p.held=true if not checkPosition(p, 0, 0) then gameOver(p) end return end end if dasKicked then return end local big=p.cheat[3] and 2 or 1 if btnp(2+boffset) or p.ldas>getSpeedValue(p, "DAS") and (p.rdas>p.ldas or p.rdas==0) then tryMove(p, -big, 0) end if btnp(3+boffset) or p.rdas>getSpeedValue(p, "DAS") and (p.rdas=speed[type][x][1] then g=speed[type][x][2] else return g end end return g end function tryMove(p, x, y) local cb=p.currentBlock if checkPosition(p, x, y) then cb.x=cb.x+x cb.y=cb.y+y if y>0 then cb.lifeVal=pieceStartingLD else if cb.resetVal+cb.lifeVal>=cb.resetVal then cb.resetVal=cb.resetVal-(pieceStartingLD-cb.lifeVal) cb.lifeVal=pieceStartingLD else cb.lifeVal=cb.lifeVal+cb.resetVal cb.resetVal=0 end end cb.idle=0 return true end return false end function checkPosition(p, x, y) local cb=p.currentBlock for z=1, #blockoffsets[cb.block][cb.rotation+1] do b=blockoffsets[cb.block][cb.rotation+1][z] if b[2]+y+cb.y<-1 then if b[1]+x+cb.x<1 or b[1]+x+cb.x>10 then return false end else if b[2]+y+cb.y>20 or b[1]+x+cb.x<1 or b[1]+x+cb.x>10 or p.grid[b[2]+y+cb.y][b[1]+x+cb.x]>0 then return false end end end return true end function lock(p) for x=0, 209 do p.gridAge[x//10][x%10+1]=p.gridAge[x//10][x%10+1]+1 end sfx(0, nil, -1, p.id-1) local cb=p.currentBlock local immobile=not (checkPosition(p, -1, 0) or checkPosition(p, 1, 0) or checkPosition(p, 0, -1)) for z=1, #blockoffsets[cb.block][cb.rotation+1] do b=blockoffsets[cb.block][cb.rotation+1][z] if b[2]+cb.y>-1 then p.grid[b[2]+cb.y][b[1]+cb.x]=colormap[p.rule+1][(cb.block-1)%7+1] p.gridAge[b[2]+cb.y][b[1]+cb.x]=-4 end end p.are=getSpeedValue(p, "ARE") checkLines(p) if p.level<1000 then p.blocksUsed=p.blocksUsed+1 else p.rollBlocks=p.rollBlocks-1 end calculateScore(p, immobile) if #p.markedLines==0 and p.amuletActive>0 then amulet(p) end p.currentBlock=nil end function checkLines(p) for y=0, 20 do local count=0 for x=1, 10 do if p.grid[y][x]>0 then count=count+1 end end if count==10 then p.markedLines[#p.markedLines+1]=y end end local lines=math.ceil(#p.markedLines/(p.cheat[3] and 2 or 1)) if #p.markedLines>0 then if p.state=="Roll" then p.rollLines=p.rollLines+lines getGrade(p) end if p.special==2 and not p.slowActive then p.slow=math.min(1200, p.slow+60*lines) end if p.special==3 then p.amulet=math.min(20, p.amulet+lines) end p.are=getSpeedValue(p, "LARE") p.lcf=getSpeedValue(p, "LCF") end end function clearLines(p) if p.lcf~=0 then p.amuletActive=0 end while #p.markedLines>0 do for y=p.markedLines[1], 1, -1 do for x=1, 10 do p.grid[y][x]=p.grid[y-1][x] p.gridAge[y][x]=p.gridAge[y-1][x] end end for x=1, 10 do p.grid[0][x]=0 p.gridAge[0][x]=0 end table.remove(p.markedLines, 1) end if p.currentBlock and not checkPosition(p, 0, 0) then gameOver(p) end end function amulet(p, emergency) if emergency then p.emergencyAmuletTimer=20 end local big=p.cheat[3] and 2 or 1 for x=1, p.amuletActive*big do p.markedLines[x]=20+x-p.amuletActive*big end sfx(19, nil, math.max(p.are, p.emergencyAmuletTimer), p.id-1) end function checkBravo(p) for y=0, 20-#p.markedLines do local count=0 for x=1, 10 do if p.grid[y][x]>0 then count=count+1 end end if count~=0 then return false end end return true end function calculateScore(p, immobile) local lines=math.ceil(#p.markedLines/(p.cheat[3] and 2 or 1)) local lineData={60} local joe = p.special==4 and 1 or 0 if immobile then table.insert(lineData, #lineData, ({"j", "i", "z", "l", "o", "t", "s"})[(p.currentBlock.block-1)%7+1].."-SPIN") end if lines>0 then table.insert(lineData, #lineData, ({"SINGLE", "DOUBLE", "TRIPLE", "JAFTAW"})[lines]) end if checkBravo(p) then table.insert(lineData, #lineData, "bravo") end if immobile and p.level%100<90 then p.cspins=p.cspins+({1, 3, 6, 10, 15})[lines+1] end if lines==0 then p.combo=1 if #lineData>1 then p.lineData=lineData end return elseif lines==4 and p.level%100<90 then p.cquads=p.cquads+1 end local multi=({1, 1.2, 1.5, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 40, 50, 60, 80, 100, 120, 150, 200, 300, 400, 500, 600, 800, 1000, 1200})[math.min(p.cools, (math.min(p.difficulty, 3)*900))//100+1+joe] if immobile and p.special~=1 then p.combo=p.combo+({1, 5, 9, 13})[lines] elseif immobile then p.combo=p.combo+({0, 3, 5, 7})[lines] elseif p.special~=1 then p.combo=p.combo+({1, 4, 7, 10})[lines] else p.combo=p.combo+({0, 2, 3, 4})[lines] end local added=(math.ceil(p.level/4+lines)+p.currentBlock.dropped)*lines*p.combo*(checkBravo(p) and 4 or 1) if p.state~="Versus" then table.insert(lineData, #lineData, "+"..added..(multi>1 and "*"..multi or "")..(p.slowActive and "*0.5" or "")) end p.lineData=lineData p.score=p.score+math.ceil(added*multi/(p.slowActive and 2 or 1)) if p.special==5 then p.blocks=p.blocks+math.ceil(({1, 3, 6, 10})[lines]*(2-p.level/1000)*(immobile and 1.5 or 1)) end local lineTable={ {1, 2, 3, 4}, {1, 2, 3, 5}, {1, 2, 4, 6}, {1, 2, 4, 7}, {1, 3, 5, 7}, } local olevel=p.level if p.state~="Roll" then p.level=p.level+lineTable[p.state=="Versus" and 1 or math.min(5, (p.level//100+p.cools//100)//(2*(p.difficulty+1))+1)][lines] end p.maxBlocks=100-p.cools//100-p.level//20 while p.blocks>p.maxBlocks and p.special==5 do p.blocks=p.blocks-1 p.level=p.level+1 p.maxBlocks=100-p.cools//100-p.level//20 end checkCool(p) p.maxBlocks=100-p.cools//100-p.level//20 while p.blocks>p.maxBlocks and p.special==5 do p.blocks=p.blocks-1 p.level=p.level+1 p.maxBlocks=100-p.cools//100-p.level//20 end if p.state~="Versus" and p.level-p.level%100>olevel then nextSection(p) end if p.state=="Versus" then local attack=lines*math.floor(({1+p.cools//800+joe, 2+p.cools//400+joe, 3+p.cools//200+joe, 4+p.cools//100+joe})[lines]*(immobile and (p.special==0 and ({1, 1.5, 2, 3}) or ({1, 1, 1.5, 2}))[lines] or 1)) player[3-p.id].level=player[3-p.id].level+attack table.insert(lineData, #lineData, "#+"..attack) p.cools=p.cools+({5, 10, 25, 50})[lines] p.cools=p.cools+(immobile and ({0, 0, 15, 50})[lines] or 0) end getGrade(p) end function nextSection(p) p.ctimer=0 p.cquads=0 p.cspins=0 p.cools=p.cools+(p.pendingCools or 0) p.coolsChecked=false p.levelstopped=false local section=(p.level+10)//100+p.pendingCools//100 if p.level>999 then p.level=1000 p.state="RollStart" p.blocks=p.maxBlocks p.menutimer=100 p.track=6 else if p.track>=player[3-p.id].track and not playingMusic then music(p.track%20) playingMusic=true end end end function getGrade(p) local g=0 while grades[g+2] and p.score//100>=grades[g+2]*(p.special==5 and 2 or 1) do g=g+1 end if p.level<1000 then g=math.min(g, 104) elseif p.cools<3000 then g=math.min(g, 106) elseif not p.canIntoTopRank then g=math.min(g, 107+math.min(p.rollLines, 30)//3) end p.grade=g end function rotate(p, dir) local cb=p.currentBlock local big=p.cheat[3] and 2 or 1 local boffset=p.id*8-8 local offsets={{0, 0}, {0, 0}, {0, 0}, {0, 0}} if p.rule==0 then if btnp(2+boffset) or p.ldas>getSpeedValue(p, "DAS") and (p.ldasgetSpeedValue(p, "DAS") and (p.rdas3000 and p.track<5) or (testLevel>2400 and p.track<4) or (testLevel>1800 and p.track<3) or (testLevel>1200 and p.track<2) or (testLevel>600 and p.track<1) or p.difficulty==4 and (p.level>400 and p.track<21) or p.level>900) and p.track>=player[3-p.id].track then p.track=p.track+1 music() playingMusic=false end end --Graphical functions function draw() if menu~=-1 then return drawMenu() end if idle>=1200 then return drawHighScoreList((idle//300-4)%(cfg.joe and 6 or 5)) end if idle>=600 then return drawTitleScreen() end drawPlayer(1) drawPlayer(2) end function printCenter(string, y, color, smallfont) width=print(string, 0, -10, 0, false, 1, smallfont) return print(string, (240-width)/2, y, color, false, 1, smallfont) end function printCenterField(pid, string, y, color, smallfont) width=print(string, 0, -10, 0, false, 1, smallfont) return print(string, 16+120*(pid-1)+(50-width)/2, y, color, false, 1, smallfont) end function drawTitleScreen() printCenter("Master of Blocks 5-X: Devastation", 10, 12) printCenter("PROGRAM & MUSIC - Phoenix Flare", 18, 12) printCenter("GRAPHICS - MarkGamed7794", 26, 12) printCenter("SPECIAL THANKS TO:", 38, 12) printCenter("TAP Discord Server", 46, 12) printCenter("Badger eSports", 54, 12) printCenter("BETA TESTERS:", 66, 12) printCenter("UnderRay - Trixciel - Mizu", 74, 12) printCenter("NOT_A_ROBOT - nothing", 82, 12) if time()%1000>500 then printCenter((cfg.free or credits>=math.max(cfg.coin, 1)) and "PRESS A BUTTON TO START" or "INSERT COIN", 96, 12) end printCenter("Revision 2D", 110, 12) printCenter("", 116, 12) --For use in the event of any major revisions. --Feel free to use this to denote a modified version as well. if cfg.coin<2 then printCenter(cfg.free and "FREE" or (credits.." CREDIT"), 128, 12) else printCenter(cfg.free and "FREE" or ((credits//2)..(credits%2==1 and " 1/2" or "").." CREDIT"), 128, 12) end end function drawHighScoreList(hsdisp) if hsdisp==4 and not cfg.joe then hsdisp=5 end printCenter("HIGH SCORES", 10, 12) printCenter(({[0]="180-ROTATE","HOLD BOX","SLOW MODE","AMULET","Joe","STRATEGY MODE"})[hsdisp], 20, 12) if hsdisp==4 then spr(132, 70, 10, 8, 1, 0, 0, 3, 3) end print("ALL-TIME BEST", 5, 50, 12) print("TODAY'S BEST", 125, 50, 12) for x=1, 3 do font(({"1ST", "2ND", "3RD"})[x], 5, 40+20*x) local hs=highScore.all[hsdisp][x] pal(14, ({[0]=6, 10, 2, 7, 15})[hs[5]]) if hs[5]==4 then pal(12, 14) end drawGrade(hs[0], 20, 40+20*x) pal() if hs[1]<1000 then font("#"..hs[1], 40, 50+20*x) else font("cdefg", 40, 50+20*x) end font(hsdisp==5 and hs[2].."h" or formatTime(hs[2]), 65, 50+20*x) drawName(hs[3], 32, 40+20*x) spr(94+16*hs[4], 65, 40+20*x, 0, 1, 0, 0, 2, 1) end for x=1, 3 do font(({"1ST", "2ND", "3RD"})[x], 125, 40+20*x) local hs=highScore.today[hsdisp][x] pal(14, ({[0]=6, 10, 2, 7, 15})[hs[5]]) if hs[5]==4 then pal(12, 14) end drawGrade(hs[0], 140, 40+20*x) pal() if hs[1]<1000 then font("#"..hs[1], 160, 50+20*x) else font("cdefg", 160, 50+20*x) end font(hsdisp==5 and hs[2].."h" or formatTime(hs[2]), 185, 50+20*x) drawName(hs[3], 152, 40+20*x) spr(94+16*hs[4], 185, 40+20*x, 0, 1, 0, 0, 2, 1) end printCenter(cfg.free and "FREE" or (credits>0 and (credits.." CREDIT") or "INSERT COIN"), 128, 12) end function drawMenu() printCenter("SETTINGS MENU", 10, 12) print("SOUND", 60, 20, menu==0 and 4 or 12) print(cfg.vol.snd, 180-print(cfg.vol.snd, 0, -6), 20, 12) print("MUSIC", 60, 28, menu==1 and 4 or 12) print(cfg.vol.bgm, 180-print(cfg.vol.bgm, 0, -6), 28, 12) print("MENU TIMER", 60, 36, menu==2 and 4 or 12) print(cfg.timer and "ENABLED" or "DISABLED", cfg.timer and 138 or 133, 36, 12) print("PAUSE", 60, 44, menu==3 and 4 or 12) print(cfg.pause and "ENABLED" or "DISABLED", cfg.pause and 138 or 133, 44, 12) print("BGA", 60, 52, menu==4 and 4 or 12) print(cfg.bga and "ENABLED" or "DISABLED", cfg.bga and 138 or 133, 52, 12) print("FREE PLAY", 60, 60, menu==5 and 4 or 12) print(cfg.free and "ENABLED" or "DISABLED", cfg.free and 138 or 133, 60, 12) print("COIN MODE", 60, 68, menu==6 and 4 or 12) print(({"1 CR/COIN", "2 CR/COIN", "2 COIN/CR"})[cfg.coin+1], cfg.coin==0 and 130 or 129, 68, 12) print("RETURN TO GAME", 60, 76, menu==7 and 4 or 12) print("RESET ALL DATA", 60, 84, menu==8 and 4 or 12) if menu<2 then print("PRESS LEFT AND RIGHT TO DECREASE AND INCREASE", 37, 96, 12, false, 1, true) elseif menu<6 then print("PRESS P1 A TO TOGGLE", 84, 96, 12, false, 1, true) elseif menu<7 then print("PRESS LEFT AND RIGHT TO DECREASE AND INCREASE", 37, 96, 12, false, 1, true) elseif menu==7 then print("PRESS P1 A TO EXIT", 88, 96, 12, false, 1, true) elseif menu==8 then print("TO RESET DATA, HOLD P1 A AND B FOR 5 SECONDS", 39, 96, 12, false, 1, true) end print("Joe", 60, 120, menu==9 and 4 or 12) spr(132, 80, 110, 8, 1, 0, 0, 3, 3) print(cfg.joe and "ENABLED" or "", 138, 120, 12) end function drawPlayer(pid) local p=player[pid] local offset=(pid-1)*120 vbank(0) --Draw Field rectb(10+offset, 23, 60, 110, 13) rect(14+offset, 27, 52, 102, 13) rect(15+offset, 28, 50, 100, 0) vbank(1) --Draw Wins if p.wins>0 then print(p.wins.." WINS", 55+offset, 1, 4) elseif p.denyversus and p.special~=5 then print("NO VS", 55+offset, 1, 2) end --Draw Next Boxes vbank(0) print("NEXT", 29+offset, 2, 12) for x=1, 3 do rect(4+x*24+offset, 8, 24, 14, 0) rectb(4+x*24+offset, 8, 24, 14, 13) end --Draw Hold Box if p.special==1 then print("HOLD", 2+offset, 2, 12) rect(2+offset, 8, 24, 14, 0) rectb(2+offset, 8, 24, 14, 13) end --Draw Slow Meter if p.special==2 then local c=p.slowActive and p.slow%2==1 and 4 or (p.slow<300 and 2 or 12) print("SLOW", 2+offset, 2, 12) rect(3+offset, 8, 22, 7, 13) rect(4+offset, 9, 20, 5, 0) rect(4+offset, 9, p.slow/60, 5, c) end --Draw Amulet Meter if p.special==3 then local c=p.amulet<5 and 12 or 10 print("WARD", 2+offset, 2, 12) rect(3+offset, 8, 22, 7, 13) rect(4+offset, 9, 20, 5, 0) rect(4+offset, 9, p.amulet, 5, c) end --Draw Joe if p.special==4 then vbank(1) if p.id==1 then print("Joe", 10+offset, 1, 12) else pal(5, 7) pal(6, 1) end spr(132, 8+offset, 7, 8, 1, 0, 0, 3, 2) pal() vbank(0) end --Draw Block Counter if p.special==5 then font(p.blocks, 20+offset-#(""..p.blocks)*4, 11) pal(14, 12) pal(15, 13) spr(1, 20+offset, 12, 0) pal() end vbank(1) if not p.versus then vbank(0) --Draw Grade if p.difficulty==4 then pal(14, 15) pal(12, 14) end drawGrade(p.grade, 72+offset, 24) pal() vbank(1) --Draw Score font("SCORE", 72+offset, 42) font(p.score, 72+offset, 48) line(72+offset, 56, 70+offset+4*#(p.score..""), 56, 12) if p.grade>=104 and p.level<1000 then font("???", 72+offset, 58) elseif p.grade<107 then local testscore=grades[p.grade+2]*(p.special==5 and 2 or 1) font(testscore.."00", 72+offset, 58) line(72+offset, 56, 70+offset+4*#(testscore.."00"), 56, 12) end end --Draw LineData if p.lineData then for x=1, 7 do pal(blockpalette[x][1], blockpalette[colormap[p.rule+1][x]][1]) end for x=1,#p.lineData-1 do font(p.lineData[x], 72+offset, 62+6*x) end pal() end --Draw Level font("LEVEL", 72+offset, 100) font(p.level, 72+offset, 106) --Draw Timer/Block Counter if p.special~=5 then font("TIME", 72+offset, 118) font(formatTime(p.timer), 72+offset, 124) else font("BLOCKS", 72+offset, 118) font(p.blocksUsed, 72+offset, 124) end --Main per-player draw function if p.state=="Idle" then if player[3-pid].state=="Config" or player[3-pid].state=="Start" or player[3-pid].state=="Win" then printCenterField(pid, "WAIT", 44, 12) else if cfg.free or credits>=math.max(cfg.coin, 1) then printCenterField(pid, "PRESS A", 44, 12) printCenterField(pid, "TO START", 50, 12) else printCenterField(pid, "INSERT", 44, 12) if credits==1 or cfg.coin<2 then printCenterField(pid, "COIN", 50, 12) else printCenterField(pid, "2 COIN", 50, 12) end end end if cheats[pid][1] then printCenterField(pid, "20G MODE", 100, 4) end if cheats[pid][2] then printCenterField(pid, "TLS MODE", 110, 4) end if cheats[pid][3] then printCenterField(pid, "BIG MODE", 120, 4) end elseif p.state=="Config" then if cfg.timer then font((p.menutimer<541 and "0" or "")..(p.menutimer+59)//60, 36+offset, 11) end if p.menu==-1 then printCenterField(pid, "GAMEMODE", 44, 12) printCenterField(pid, p.special==5 and "STRATEGY" or "SPEED", 56, 4+p.special, true) print("Joe", 47+offset, 70, 12) spr(132, 36+offset, 70, 8, 1, 0, 0, 3, 3) if p.special<5 then print("!", 40+offset, 64, 5) spr(162, 16+offset, 70, 0, 1, 0, 0, 2, 2) local a=(time()/100) line(24+offset, 80, 24+offset-math.sin(a)*4, 80+math.cos(a)*4, 2) else print("?", 39+offset, 64, 5) spr(160, 16+offset, 70, 0, 1, 0, 0, 2, 2) end elseif p.menu==0 then printCenterField(pid, "SPECIAL", 44, 12) if p.special==0 then spr(144, 40+offset, 64, 0, 1, 0, 3) spr(145, 32+offset, 64, 0, 1, 0, 1) spr(144, 32+offset, 56, 0, 1, 0, 1) spr(145, 40+offset, 56, 0, 1, 0, 3) spr(146, 36+offset, 60, 0) printCenterField(pid, "180-SPIN", 50, 12) elseif p.special==1 then rectb(28+offset, 57, 24, 14, 13) spr(146, 36+offset, 60, 0) printCenterField(pid, "HOLD", 50, 12) elseif p.special==2 then spr(137, 33+offset, 56, 0, 1, 0, 0, 2, 2) spr(146, 36+offset, 65, 0) printCenterField(pid, "SLOW", 50, 12) elseif p.special==3 then spr(135, 32+offset, 56, 0, 1, 0, 0, 2, 2) spr(146, 25+offset, 60, 0) printCenterField(pid, "AMULET", 50, 12) elseif p.special==4 then if p.id==1 then print("Joe", 40+offset, 50, 12) else pal(5, 7) pal(6, 1) end spr(132, 28+offset, 50, 8, 1, 0, 0, 3, 3) pal() end print(({"Rotate 180\ndegrees by\npressing X\nbutton!", "Hold the\nblock until\nyou need by\npressing X\nbutton!", "Slow the\nblocks for\nlimited time\nwith X press!", "Magic amulet\nfrom before;\npress X to\nuse!", ({"Joe, the\nGreen Alpaca", "Frank, the\nPurple Llama"})[p.id]})[p.special+1], offset+17, 80, 12, false, 1, true) elseif p.menu==1 then printCenterField(pid, "ROTATION", 50, 12) if p.reverse then spr(128, 22+offset, 56, 0, 1, 1, 0, 2, 2) spr(128, 42+offset, 56, 0, 1, 0, 0, 2, 2) printCenterField(pid, "REVERSE", 44, 12) print("Rotation\nbuttons\nare reversed.", offset+17, 80, 12, false, 1, true) else spr(128, 22+offset, 56, 0, 1, 0, 0, 2, 2) spr(128, 42+offset, 56, 0, 1, 1, 0, 2, 2) printCenterField(pid, "STANDARD", 44, 12) print("Rotation\nbuttons\nare standard.", offset+17, 80, 12, false, 1, true) end spr(130, 26+offset, 60, 0) spr(131, 46+offset, 60, 0) elseif p.menu==2 then printCenterField(pid, "DROP TYPE", 44, 12) if p.sonic then printCenterField(pid, "SONIC", 50, 12) spr(9, 24+offset, 65, 0) spr(9, 29+offset, 65, 0, 1, 1) print("Fast drop\ndoesn't lock.\nFor classic\nplayers.", offset+17, 80, 12, false, 1, true) else printCenterField(pid, "HARD", 50, 12) spr(9, 44+offset, 65, 0) spr(9, 49+offset, 65, 0, 1, 1) print("Fast drop\nlocks.\nFor typical\nplayers.", offset+17, 80, 12, false, 1, true) end spr(1, 28+offset, 64, 0) spr(11, 27+offset, 56, 0) spr(1, 48+offset, 64, 0) spr(10, 47+offset, 56, 0) elseif p.menu==3 then printCenterField(pid, "VERSUS", 44, 12) if p.denyversus then printCenterField(pid, "DENY", 50, 12) print("Opponent\nis not able\ninterrupt\nyour game\nto attack.", offset+17, 80, 12, false, 1, true) else printCenterField(pid, "ALLOW", 50, 12) print("Opponent\nis able to\ninterrupt\nyour game\nto attack.", offset+17, 80, 12, false, 1, true) end elseif p.menu==4 then local c={7, 10, 3} if time()%200<100 then c[p.rule+1]=4 end printCenterField(pid, "SELECT", 34, 12) printCenterField(pid, "RULE", 40, 12) printCenterField(pid, "KRS+", 54, c[1], true) printCenterField(pid, "SRS-X", 60, c[2], true) printCenterField(pid, "DRS-H", 66, c[3], true) print(({[0]="Original MoB5\nblock rules.", "Common rule\nused in most\ngames.", "Classic rule\nused by\nexperts.", "Challenge of\nlegendary.\nOnly way to\ngo for top\nrank!"})[p.rule], offset+17, 80, 12, false, 1, true) elseif p.menu==5 then local c={6, 10, 2, 7, 13} if time()%200<100 then c[p.difficulty+1]=4 end printCenterField(pid, "SELECT", 34, 12) printCenterField(pid, "LEVEL", 40, 12) printCenterField(pid, "INNOCENCE", 48, c[1], true) printCenterField(pid, "AWARENESS", 54, c[2], true) printCenterField(pid, "RESOLVE", 60, c[3], true) printCenterField(pid, "DESPERATION", 66, c[4], true) if p.unlock>=13 then printCenterField(pid, "DEVASTATION", 72, c[5], true) end pal() print(({[0]="Easiest mode.\nEveryone\nstarts place.", "Light level.\nFor casual\nplayers.", "Harder level.\nFor used to\ngame players.", "Challenge of\nlegendary.\nOnly way to\ngo for top\nrank!"})[p.difficulty], offset+17, 80, 12, false, 1, true) end if time()%3000<1500 then if p.menu<4 then spr(139, offset+16, 120, 0) spr(140, offset+24, 120, 0) else spr(141, offset+16, 117, 0) spr(157, offset+16, 125, 0) end print("CHANGE", offset+27, 121, 13, false, 1, true) else spr(130, offset+17, 119) print("ACCEPT", offset+27, 121, 13, false, 1, true) end elseif p.state=="Challenge" then if cfg.timer then font((p.menutimer<541 and "0" or "")..(p.menutimer+59)//60, 36+offset, 11) end printCenterField(pid, "ATTACK?", 50, 12) printCenterField(pid, "NO", 60, p.menu==0 and 4 or 12) printCenterField(pid, "YES", 66, p.menu==1 and 4 or 12) elseif p.state=="VersusWarn" then drawGame(pid) rect(p.menutimer*5-480, 62, 1200-p.menutimer*10, 10, 2) if p.menutimer<100 then font("A FIGHT BROKEN OUT!", 77, 65) end elseif p.state=="Start" or p.state=="VersusStart" then if p.menutimer>45 then printCenterField(pid, "READY", 50, 12) else printCenterField(pid, "GO", 50, 12) end drawQueue(pid) elseif p.state=="InGame" or p.state=="Versus" or p.state=="Roll" then drawGame(pid) elseif p.state=="Curtain" then drawGame(pid) rect(15+offset, 128-p.menutimer, 50, p.menutimer, 0) elseif p.state=="NameWait" then printCenterField(pid, "WAIT", 44, 12) elseif p.state=="NameEntry" then if cfg.timer and p.menu~=6 then font((p.menutimer<541 and "0" or "")..(p.menutimer+59)//60, 36+offset, 11) end drawName(p.name, 21+offset, 95) if p.menu>3 and p.menu<6 then spr(257-p.menu, 53+offset, 95, 0) end font("OVERALL", 27+offset, 30) font(({"1ST", "2ND", "3RD", "OUT"})[p.place[1]], 35+offset, 40) font("TODAY", 31+offset, 55) font(({"1ST", "2ND", "3RD"})[p.place[2]], 35+offset, 65) printCenterField(pid, "NAME", 80, 12) printCenterField(pid, "ENTRY", 86, 12) elseif p.state=="GameOver" then printCenterField(pid, "GAME", 74, 2) printCenterField(pid, "OVER", 80, 2) elseif p.state=="Win" then printCenterField(pid, "YOU'RE", 74, 4) printCenterField(pid, "WINNER!", 80, 4) end if p.pause then rect(30+offset, 60, 21, 7, 15) font("PAUSE", 31+offset, 61) end end function drawQueue(pid) local offset=(pid-1)*120 local p=player[pid] for x=1,3 do if p.special==5 and p.difficulty==4 and p.level//100>9-x then break end drawBlock(player[pid].next[x], 0, 11+x*24+offset, 15) end end function drawGame(pid) local p=player[pid] local offset=(pid-1)*120 drawQueue(pid) drawGrid(pid) rectb(14+offset, 27, 52, 102, 13) if #p.markedLines>0 then if p.lcf>0 then for x=1, #p.markedLines do if p.markedLines[x]~=0 and p.lcf%2==0 then rect(15+offset, 23+5*p.markedLines[x], 50, 5, 12) end end elseif p.amuletActive>0 then rect(15+offset, 128-5*#p.markedLines, 50, 5*#p.markedLines, 10) for x=1, p.amuletActive+math.random(p.amuletActive)-1 do local y=128-math.random(5*#p.markedLines) line(15+offset, y, 65+offset, y, 11) end end end if p.currentBlock then if (p.cheat[2] or p.level<100) and gameState~="Curtain" and p.difficulty~=4 then local o=0 while checkPosition(p, 0, o+1) do o=o+1 end drawBlock(42+pid, p.currentBlock.rotation, 10+offset+p.currentBlock.x*5, 23+(p.currentBlock.y+o)*5) end if p.special~=5 or p.level<900 or p.difficulty<4 or p.currentBlock.age<15 then drawBlock(p.currentBlock.block, p.currentBlock.rotation, 10+offset+p.currentBlock.x*5, 23+p.currentBlock.y*5) end end if p.heldBlock then drawBlock(p.heldBlock, 0, 9+offset, 15) end end function drawGrid(pid) local p=player[pid] local offset=(pid-1)*120 local invis=1e50 if p.special==5 and p.difficulty>0 and p.level>499 then invis=55-p.difficulty*5-p.level//25 if p.difficulty==4 then invis=0 end end for y=1,20 do for x=1,10 do if p.grid[y][x]>0 and p.gridAge[y][x]0 and p.gridAge[y][x]<0 then rect(9+offset+5*x, 22+5*y, 7, 7, 12) end end end for y=1,20 do for x=1,10 do if p.grid[y][x]>0 then if p.pause or p.gridAge[y][x]>=invis or invis==0 then rect(10+offset+5*x, 23+5*y, 5, 5, 0) else local b=p.grid[y][x] local bc=blockpalette[b] pal(14, bc[1]) pal(15, bc[2]) spr(1, 10+offset+5*x, 23+5*y, 0) end end end end pal() end function drawBlock(block, rotation, x, y) local blockColor=block>42 and 8 or (block-1)%7+1 local rule=((block-1)//7)%3+1 if block>42 then block=player[block-42].currentBlock.block end for z=1,#blockoffsets[block][rotation+1] do local b=blockoffsets[block][rotation+1][z] local bc=blockpalette[colormap[rule][blockColor]] pal(14, bc[1]) pal(15, bc[2]) spr(1, b[1]*5+x, b[2]*5+y, 0) pal() end end function drawGrade(grade, x, y) grade=math.max(math.min(grade, 118), 0) if grade<8 then spr(16+grade*2, x, y, 0, 1, 0, 0, 2, 2) elseif grade==8 then spr(48, x, y, 0, 1, 0, 0, 2, 2) elseif grade<72 then spr(48+grade//9*2, x, y, 0, 1, 0, 0, 2, 2) spr(112+(grade%9), x+10, y+10, 0) elseif grade<99 then spr(64+grade//9*2, x, y, 0, 1, 0, 0, 2, 2) spr(112+(grade%9), x+10, y+10, 0) elseif grade==99 then spr(86, x, y, 0, 1, 0, 0, 2, 2) elseif grade<105 then spr(86, x, y, 0, 1, 0, 0, 2, 2) spr(21+grade, x+10, y+10, 0) elseif grade<108 then spr(({88, 82, 84})[grade-104], x, y, 0, 1, 0, 0, 2, 2) spr(125, x+10, y+10, 0) elseif grade<117 then spr(90, x, y, 0, 1, 0, 0, 2, 2) spr(grade+4, x+10, y+10, 0) elseif grade==117 then spr(90, x, y, 0, 1, 0, 0, 2, 2) spr(125, x+10, y+10, 0) else spr(92, x, y, 0, 1, 0, 0, 2, 2) end end function drawName(name, x, y) if type(name)=="number" then name={ (name&0xFF0000)>>16, (name&0xFF00)>>8, name&0xFF, } end for z=1, 3 do spr(192+name[z], x+8*z, y, name[z]~=59 and 0 or 8) end end function drawBackground() cls(0) if menu~=-1 or idle>=1200 then cls(8) for x=-2, 6 do for y=-2, 6 do local ex={[0]=-1, 1} spr(86, ex[y%2]*(time()//100)%76+x*76+(y%2)*38, (time()//100)%40+y*20, 0, 1, 0, 0, 2, 2) spr(56, ex[y%2]*(time()//100)%76+x*76+(y%2)*38+16, (time()//100)%40+y*20, 0, 1, 0, 0, 2, 2) spr(24, ex[y%2]*(time()//100)%76+x*76+(y%2)*38+32, (time()//100)%40+y*20, 0, 1, 0, 0, 2, 2) spr(142, ex[y%2]*(time()//100)%76+x*76+(y%2)*38+42, (time()//100)%40+y*20, 0, 1, 0, 0, 2, 2) spr(62, ex[y%2]*(time()//100)%76+x*76+(y%2)*38+52, (time()//100)%40+y*20, 0, 1, 0, 0, 2, 2) spr(124, ex[y%2]*(time()//100)%76+x*76+(y%2)*38+12, (time()//100)%40+y*20+4, 0) end end return end if not cfg.bga then return end local p1=player[1].state=="Idle" and 0 or player[1].level local p2=player[2].state=="Idle" and 0 or player[2].level local level=math.max(p1, p2) if level<100 then for x=0, 6 do circb(120, 68, 20*x+(time()/40)%20, 15) end elseif level<200 then for x=1, 10 do local a={ math.sin(math.rad(x*36+((time()/20)%72<36 and (time()/20) or 0))), math.cos(math.rad(x*36+((time()/20)%72<36 and (time()/20) or 0))), } line(120, 68, 120-a[1]*144, 68+a[2]*144, 12) end elseif level<300 then tri( 120+60*(math.cos(math.rad(90))*math.sin(time()/600)), 68+60*math.sin(math.rad(90)), 120+60*(math.cos(math.rad(210))*math.sin(time()/600)), 68+60*math.sin(math.rad(210)), 120+60*(math.cos(math.rad(330))*math.sin(time()/600)), 68+60*math.sin(math.rad(330)), 14 ) tri( 120+50*(math.cos(math.rad(90))*math.sin(time()/600)), 68+50*math.sin(math.rad(90)), 120+50*(math.cos(math.rad(210))*math.sin(time()/600)), 68+50*math.sin(math.rad(210)), 120+50*(math.cos(math.rad(330))*math.sin(time()/600)), 68+50*math.sin(math.rad(330)), 15 ) elseif level<400 then for x=-1,15 do local h=x*16+(80*(math.cos(math.rad(time()/30))))%16 rect(h, 0, 2, 136, 14) end for y=-1,9 do local h=y*16+(80*(math.sin(math.rad(time()/30))))%16 rect(0, h, 240, 2, 14) end elseif level<500 then for x=1,8 do local y={68+68*math.sin(math.rad(45*x)+time()/700), 68+68*math.sin(math.rad(45*x+80)+time()/700)} line(0, y[1], 240, y[2], 14) end elseif level<600 then h={math.rad(time()/30),math.rad(time()/30+20)} for x=1, 9 do tri( 120, 68, 120+200*math.cos(h[1]+math.rad(40*x)), 68+200*math.sin(h[1]+math.rad(40*x)), 120+200*math.cos(h[2]+math.rad(40*x)), 68+200*math.sin(h[2]+math.rad(40*x)), 15 ) end elseif level<700 then circ(120, 68, 60, 15) for x=1,3 do ellib(120, 68, 60, math.abs(60*math.sin(time()/450+math.rad(60*x))), 12) ellib(120, 68, math.abs(60*math.sin(time()/450+math.rad(90+60*x))), 60, 12) end circb(120, 68, 60, 12) elseif level<800 then local c=(time()/10)%720<360 and 14 or 13 for x=1, 10 do local a={ math.sin(math.rad(x*36+((time()/10)%720<360 and (time()/10) or -(time()/10)))), math.cos(math.rad(x*36+((time()/10)%720<360 and (time()/10) or -(time()/10)))), } line(120, 68, 120-a[1]*144, 68+a[2]*144, c) end circb(120, 68, 720-(time()/10)%360*2, 27-c) circb(120, 68, 1080-(time()/10)%360*3, 27-c) circb(120, 68, 1440-(time()/10)%360*4, 27-c) elseif level<900 then cls(15) for x=0,67 do local v=math.random(5)-3 rect(0, 2*x, 81+60*math.sin(time()/200+x/50)+v, 2, 0) rect(160+v+60*math.sin(time()/200+x/50), 2*x, 140-v, 2, 0) end else cls(1) line(0, 135, 240, 135, 0) end end function drawFieldBorder(p) rect(11+(p.id-1)*120, 24, 58, 108, p.id+1) end --Miscellaneous functions function formatTime(t) local m=t//3600 local s=t//60-m*60 local ms=((t-s*60-m*3600)*100)//60 if m<10 then m="0"..m end if s<10 then s="0"..s end if ms<10 then ms="0"..ms end return m..":"..s..":"..ms end function pal(p1, p2) local addr=0x7FE0 if p1 then p2=p2 or p1 poke4(addr+p1, p2) else for x=0, 15 do poke4(addr+x, x) end end end