;######################### ;# Kevin's Definitions # ;######################### #define B_CALL(xxxx) rst 28h \ .dw xxxx #define B_JUMP(xxxx) call 50h \ .dw xxxx #define SETPEN(xx,yy) LDHL(xx,yy) \ ld (PenCol),hl #define SETCUR(xx,yy) LDHL(yy,xx) \ ld (currow),hl #define DRAWHL(xx,yy) B_CALL(_SetXXXXOP2) \ B_CALL(_Op2ToOP1) \ SETPEN(xx,yy) \ ld a,5 \ B_CALL(_DispOP1A) #define DRAWINT(int,xx,yy) ld hl,(int) \ DRAWHL(xx,yy) #define DRAWTEXT(text,xx,yy) SETPEN(xx,yy) \ ld hl,text \ B_CALL(_VPutS) #define DRAWIMG(img,xx,yy) ld hl,img \ LDDE(xx,yy) \ B_CALL(_dispimg) #define LDHL(xx,yy) .db 21h \ .db xx \ .db yy #define LDDE(xx,yy) .db 11h \ .db xx \ .db yy #define LINKOUT(xx) ld a,xx \ out (0),a #define LINKIN(xx) in a,(0) \ and $03 \ cp xx #define KEY(xx,yy) ld a,xx \ out (1),a \ in a,(1) \ cp yy #define FIND(xxxx) ld hl,xxxx \ MOV9TOOP1() \ B_CALL(_ChkFindSym) #define PAUSE(time) ld b,time \ halt \ .db $10 \ .db $FD #define QUICKPAUSE(time) ld b,time \ .db $10 \ .db $FE #define OP1TOOP2() rst 08h #define FINDSYM() rst 10h #define PUSHRREALO1() rst 18h #define MOV9TOOP1() rst 20h #define FPADD() rst 30h #define FONTSIZESMALL() res 2,(IY+50) #define FONTSIZELARGE() set 2,(IY+50) ;######################## ;# TI-83+ Definitions # ;######################## ;###### ROM Calls ###### _clrlcdfull =4540h _ClrScrnFull =4546h _getkey =4018h _dispimg =4D9Bh _runindicoff =4570h _GrBufClr =4BD0h _GrBufCpy =486Ah _SetXXXXOP2 =4792h _OP2ToOP1 =4156h _DispOP1A =4BF7h _VPutC =455Eh _VPutS =4561h _CpHLDE =400Ch _CreateAppVar =4E6Ah _ChkFindSym =42f1h _DelVarArc =4fc6h _DispHL =4507h ;###### RAM Locations ###### plotSScreen =9340h currow =844bh curcol =844ch PenRow =86D8h PenCol =86D7h ;###### GetKey Codes ###### keyRt =03h keyLt =02h keyUp =04h keyDn =01h keyQt =0Fh keyEn =09h keyNeg =0Bh key2 =1Ah key3 =12h key6 =13h ;###### DirectKey Codes ###### rowClear =$FD rowNeg36 =$FB rowTwo =$F7 rowQuit =$BF KQuit =$BF KClear =$BF KNeg =$FE KThree =$FD KSix =$FB KTwo =$FD ;###### Linker Codes ###### set00 =$00 set0R =$01 setL0 =$02 setLR =$03 get00 =$03 get0R =$02 getL0 =$01 getLR =$00 linkmask =$03 ;################## ;# User Defined # ;################## STARTINGLEVEL =1 GAMESPEED =35 GAMESPEEDUP1 =24 GAMESPEEDUP2 =14 GARBAGEPERLEVEL =3 AVGBOMBFREQ =40 FLASHES =6 FLASHPAUSESHORT =8 FLASHPAUSELONG =18 FLIPSCREENFLASH =50 SHORTPAUSETIME =8 LONGPAUSETIME =12 GARBAGETIME =28 LEFTWALL =56 RIGHTWALL =16 FLOOR =88 MINBESTCOMBO =11 BESTCOMBOPAUSE =160 ;################### ;# Program Start # ;################### .org 9D95h B_CALL(_runindicoff) B_CALL(_clrlcdfull) ld (v_SaveSP),SP res 0,(IY+20) ;Force fullscreen set 7,(IY+20) ;Text to Buffer set 0,(IY+60) ;Plot to Buffer ld a,r ld (v_RSeed),a ;set random seed xor a ld (v_Mode),a call HighScore2RAM ;Read save file, create if DNE ;########### ;# Menus # ;########### TitleScreen: res 2,(IY+50) ;Small Font B_CALL(_GrBufClr) DRAWIMG(s_Title_Puyo,9,2) DRAWIMG(s_Title_Puyo,48,2) DRAWIMG(s_Title_83,32,26) DRAWIMG(s_Copyright,17,56) DRAWTEXT(txt_s_Copyright,26,57) xor a ld (t_Move),a Flashy83: ld ix,plotSScreen+328 ld hl,s_Title_83_Mask ld e,18 FlashyRow: ld b,4 FlashyRowLoop: ld a,(t_Move) ld c,a ld a,e cp 9 jr nc,FlashyRowMiniSkip neg dec a FlashyRowMiniSkip: and %00000011 cp c jr nz,FlashyRowSkip ld a,(ix+0) xor (hl) ld (ix+0),a FlashyRowSkip: inc ix inc hl djnz FlashyRowLoop ld bc,8 add ix,bc dec e jr nz,FlashyRow ld hl,t_Move ld a,(hl) inc a and %00000011 ld (hl),a B_CALL(_GrBufCpy) call ShortPause B_CALL(_getkey) or a jr z,Flashy83 MainMenuSetup: set 2,(IY+50) ;Large Font call ResetAllRam B_CALL(_GrBufClr) LDDE(%00000000,%00000100) call DrawBarsSetup DRAWIMG(s_Title_Puyo,9,2) DRAWIMG(s_Title_Puyo,48,2) DRAWTEXT(txt_Single,24,24) DRAWTEXT(txt_Two,24,32) DRAWTEXT(txt_Tutorial,24,40) DRAWTEXT(txt_HighScores,24,48) DRAWTEXT(txt_Quit,24,56) B_CALL(_GrBufCpy) ld a,(v_Mode) sla a sla a sla a LDHL(24,14) add a,l ld l,a ld (v_AX),hl ld (v_BX),hl ld a,TYPE1 ld (v_Atype),a ld a,BLANK ld (v_Btype),a MainMenu: ld a,(t_Move) or a call nz,MovePuyos ld d,%00000011 ld a,(v_Rot) ld e,a call DrawBarsSetup ld hl,v_Rot ld a,(hl) inc a and %00000011 ld (hl),a call DrawPuyos B_CALL(_GrBufCpy) call DrawPuyos halt B_CALL(_getkey) cp keyDn jr z,MenuSelectDown cp keyUp jr z,MenuSelectUp cp keyEn jp z,MenuSelectEnter cp keyQt jp z,QuitGame jr MainMenu MenuSelectDown: ld a,(t_Move) or a jr nz,MainMenu ld hl,v_Mode ld a,(hl) cp 4 jr z,MainMenu inc (hl) LDHL(3,0) ld (v_AXdir),hl ld (v_BXdir),hl ld a,MATHMAX ld (t_Move),a jr MainMenu MenuSelectUp: ld a,(t_Move) or a jr nz,MainMenu ld hl,v_Mode ld a,(hl) or a jr z,MainMenu dec (hl) LDHL(4,0) ld (v_AXdir),hl ld (v_BXdir),hl ld a,MATHMAX ld (t_Move),a jr MainMenu MenuSelectEnter: ld a,(v_Mode) cp 2 jp z,TutorialMain cp 3 jp z,HighScores cp 4 jp z,QuitGame jp Initialize HighScores: B_CALL(_GrBufClr) LDDE(%00000000,%00000100) call DrawBarsSetup DRAWTEXT(txt_HighScores2,16,0) DRAWINT(v_HSScores+0,36,16) DRAWINT(v_HSScores+2,36,24) DRAWINT(v_HSScores+4,36,32) DRAWINT(v_HSScores+6,36,40) DRAWINT(v_HSScores+8,36,48) xor a ld (v_Rot),a HighScoresLoop: ld d,%00000011 ld a,(v_Rot) ld e,a call DrawBarsSetup ld hl,v_Rot ld a,(hl) inc a and %00000011 ld (hl),a B_CALL(_GrBufCpy) B_CALL(_getkey) or a jr z,HighScoresLoop HighScoresCombo: ld hl,MainMenuSetup ;We want to return here push hl ld a,(v_HSAtype) or a ret z ld hl,v_HSAtype StealThisCodeForTut: push hl call ResetAllRam pop hl ld a,BLANK ld (v_ANext),a ld (v_BNext),a ld a,(hl) ld (v_Atype),a inc hl ld a,(hl) ld (v_Btype),a inc hl ld a,(hl) ld (v_AX),a ld (v_BX),a inc hl ld a,(hl) push hl ld hl,v_BX or a jp z,HSRotateToRight cp 1 jp z,HSRotateToDown cp 2 jp z,HSRotateToLeft HSRotateToUp: ld hl,v_AY ld a,(hl) add a,8 ld (hl),a jr HighScoreDoneSetup HSRotateToLeft: ld a,(hl) add a,8 ld (hl),a jr HighScoreDoneSetup HSRotateToDown: ld hl,v_BY ld a,(hl) add a,8 ld (hl),a jr HighScoreDoneSetup HSRotateToRight: ld a,(hl) sub 8 ld (hl),a HighScoreDoneSetup: pop hl inc hl ld de,v_GameBoard ld bc,72 ldir ld a,20 ld (v_Speed),a call GameRedraw jp Main FlipScreen: B_CALL(_GrBufClr) ld a,(v_Atype) or a jr z,FlipScreen2 DRAWTEXT(txt_FlipCalc,22,56) FlipScreen2: DRAWIMG(s_Up,2,28) DRAWIMG(s_Dpad,38,8) DRAWIMG(s_PressAnyKey,88,9) B_CALL(_GrBufCpy) ld b,FLIPSCREENFLASH FlipScreenLoop: B_CALL(_getkey) or a jr nz,FlipScreenDone halt djnz FlipScreenLoop ld hl,v_Atype ld a,(hl) cpl ld (hl),a jr FlipScreen FlipScreenDone: ld a,(v_Mode) dec a ret nz call CheckLink ret z DRAWTEXT(txt_Waiting,19,56) B_CALL(_GrBufCpy) xor a call SendByte ret ;##################### ;# Game Initialize # ;##################### Initialize: xor a ld (v_Atype),a call FlipScreen B_CALL(_GrBufClr) call ResetAllRam ld a,GAMESPEED ld (v_Speed),a ld a,STARTINGLEVEL ld (v_Level),a ld a,(v_Mode) dec a call nz,GarbageTimerSet call DrawInfoBar call NextPiece call NextPiece call DrawScore call DrawNewGarbage ;#################### ;# Game Play Loop # ;#################### Main: call DrawPuyos B_CALL(_GrBufCpy) call DrawPuyos ld a,(v_Mode) cp 2 jr nc,DontGetKey LinkStuff: dec a call z,LinkReceiveGarbage GetKey: KEY(rowNeg36,kSix) jp z,MoveRight KEY(rowNeg36,kNeg) jp z,MoveLeft KEY(rowNeg36,kThree) jp z,DropPuyo KEY(rowTwo,kTwo) jp z,RotatePuyo B_CALL(_getkey) cp keyEn call z,GamePaused cp keyQt jr nz,Timers call CheckScore ld a,(v_Mode) dec a ld a,WINBIT call z,SendByte jp MainMenuSetup DontGetKey: B_CALL(_getkey) cp keyQt ret z cp keyEn ret z Timers: ld a,(v_Speed) cp GAMESPEEDUP1 jp c,TimerShort halt TimerShort: cp GAMESPEEDUP2 jp c,TimerInstant halt TimerInstant: ld a,(t_Move) or a call nz,MovePuyos ld hl,t_Delay dec (hl) jp m,MoveDown jp Main ;########################### ;# Current Puyo Movement # ;########################### MovePuyos: MoveAX: ld hl,m_accel+MATHMAX ld a,(v_AXdir) or a jr z,MoveBX dec a call nz,PuyoNegAccel ld a,(t_Move) ld b,a MoveTimerLoopAX: dec hl djnz MoveTimerLoopAX ld a,(hl) ld hl,v_AX add a,(hl) ld (hl),a MoveBX: ld hl,m_accel+MATHMAX ld a,(v_BXdir) or a jr z,MoveAY dec a call nz,PuyoNegAccel ld a,(t_Move) ld b,a MoveTimerLoopBX: dec hl djnz MoveTimerLoopBX ld a,(hl) ld hl,v_BX add a,(hl) ld (hl),a MoveAY: ld hl,m_accel+MATHMAX ld a,(v_AYdir) or a jr z,MoveBY dec a call nz,PuyoNegAccel ld a,(t_Move) ld b,a MoveTimerLoopAY: dec hl djnz MoveTimerLoopAY ld a,(hl) ld hl,v_AY add a,(hl) ld (hl),a MoveBY: ld hl,m_accel+MATHMAX ld a,(v_BYdir) or a jr z,MoveTimerDone dec a call nz,PuyoNegAccel ld a,(t_Move) ld b,a MoveTimerLoopBY: dec hl djnz MoveTimerLoopBY ld a,(hl) ld hl,v_BY add a,(hl) ld (hl),a MoveTimerDone: ld hl,t_Move dec (hl) ret nz ld a,(v_UseLastKey) or a ret z xor a ld (v_UseLastKey),a ld a,(v_LastKey) or a ret z pop hl ;pop out of call cp kNeg jp z,MoveLeft cp kSix jp z,MoveRight jp RotatePuyo PuyoNegAccel: dec a jr nz,PuyoPosDecel ld hl,m_naccel+MATHMAX ret PuyoPosDecel: dec a jr nz,PuyoNegDecel ld hl,m_decel+MATHMAX ret PuyoNegDecel: ld hl,m_ndecel+MATHMAX ret MoveLeft: ld (v_LastKey),a ld a,(t_Move) or a jp nz,timers ;Make sure timer is reset ld a,(v_AX) cp LEFTWALL jp z,timers ;Make Sure A not hits wall ld a,(v_BX) cp LEFTWALL jp z,timers ;Make Sure B not hits wall ld hl,(v_AX) ld a,8 add a,l ld l,a call GetIndex ld a,(hl) or a jp nz,timers ;Make Sure A not hit other puyo ld hl,(v_BX) ld a,8 add a,l ld l,a call GetIndex ld a,(hl) or a jp nz,timers ;Make Sure B not hit other puyo LDHL(1,0) ld (v_AXdir),hl ld (v_BXdir),hl ld a,MATHMAX ld (t_Move),a jp timers MoveRight: ld (v_LastKey),a ld a,(t_Move) or a jp nz,timers ;Make sure timer is reset ld a,(v_AX) cp RIGHTWALL jp z,timers ;Make Sure A not hits wall ld a,(v_BX) cp RIGHTWALL jp z,timers ;Make Sure B not hits wall ld hl,(v_AX) ld a,-8 add a,l ld l,a call GetIndex ld a,(hl) or a jp nz,timers ;Make Sure A not hit other puyo ld hl,(v_BX) ld a,-8 add a,l ld l,a call GetIndex ld a,(hl) or a jp nz,timers ;Make Sure B not hit other puyo LDHL(2,0) ld (v_AXdir),hl ld (v_BXdir),hl ld a,MATHMAX ld (t_Move),a jp timers MoveDown: ld a,(t_Move) or a jp nz,LinkStuff ;Make sure timer is reset ld a,(v_AY) cp FLOOR jp z,MoveDone ;Make Sure A not hits floor ld a,(v_BY) cp FLOOR jp z,MoveDone ;Make Sure B not hits floor ld hl,(v_AX) ld a,8 add a,h ld h,a call GetIndex ld a,(hl) or a jp nz,MoveDone ;Make Sure A not hit other puyo ld hl,(v_BX) ld a,8 add a,h ld h,a call GetIndex ld a,(hl) or a jp nz,MoveDone ;Make Sure B not hit other puyo ld a,(v_Speed) ld (t_Delay),a LDHL(0,1) ld (v_AXdir),hl ld (v_BXdir),hl ld a,MATHMAX ld (t_Move),a xor a ld (v_LastKey),a inc a ld (v_UseLastKey),a jp timers MoveDone: call DrawPuyos ld hl,v_GameBoard ld de,v_GameBackUp ld bc,72 ldir ld hl,(v_BX) call GetIndex ld a,(v_Btype) ld (hl),a ;Store B to Board ld hl,(v_AX) call GetIndex ld a,(v_Atype) ld (hl),a ;Store A to Board cp BOMB call z,BombMain call FallingBlocks ld hl,0 ld (v_CombTot),hl ld (v_CombMul),hl MoveComboLoop: xor a ld (v_CombFlg),a ;Zero out no combo flag call ComboBlocksMain ld a,(v_CombFlg) or a jr z,MoveDoneWithCombo B_CALL(_GrBufCpy) call GarbageCompare call DrawNewGarbage ld a,(v_Mode) dec a jr nz,MoveSkipLinking call LinkReceiveGarbage ld a,(v_OutGarbage) or a call nz,LinkSendGarbage MoveSkipLinking: call FallingBlocks call LongPause jr MoveComboLoop MoveDoneWithCombo: ld a,(v_Mode) or a jr nz,MoveNotOnePlayer call CheckBestCombo call GarbageTimer ;If 1 player then... Take in the trash! xor a ;Make sure we are still one player MoveNotOnePlayer: dec a call z,GarbageMain ;If 2 player then... Take in the trash! call DrawNewGarbage call NextPiece ld ix,v_GameBoard ld a,(ix+24) or a jp nz,GameOver ld a,(ix+36) or a jp nz,GameOver ld a,(v_Mode) cp 2 jr nc,MoveDoneBestCombo call NextLevelCheck jp Main MoveDoneBestCombo: PAUSE(BESTCOMBOPAUSE) ret DropPuyo: ld a,(t_Move) or a jp nz,timers ;Make sure timer is reset ld a,(v_AY) cp FLOOR jp z,MoveDone ;Make Sure A not hits floor ld a,(v_BY) cp FLOOR jp z,MoveDone ;Make Sure B not hits floor ld hl,(v_AX) ld a,8 add a,h ld h,a call GetIndex ld a,(hl) or a jp nz,MoveDone ;Make Sure A not hit other puyo ld hl,(v_BX) ld a,8 add a,h ld h,a call GetIndex ld a,(hl) or a jp nz,MoveDone ;Make Sure B not hit other puyo ld a,(v_AY) add a,8 ld (v_AY),a ld a,(v_BY) add a,8 ld (v_BY),a halt halt halt jp Main ;########################### ;# Current Puyo Rotation # ;########################### RotatePuyo: ld (v_LastKey),a ld a,(t_Move) or a jp nz,timers ;Make sure timer is reset ld a,(v_Atype) cp BOMB jp z,timers ;Can't rotate a bomb LDHL(0,0) ld (v_AXdir),hl ld a,(v_Rot) or a jp z,RotateToDown cp 1 jp z,RotateToLeft cp 2 jp z,RotateToUp RotateRight: LDHL(4,1) ld a,(v_BX) cp RIGHTWALL ;B bounces off right wall jr z,RotateRBounce push hl ld hl,(v_AX) ld a,-8 add a,l ld l,a call GetIndex ld a,(hl) pop hl or a jr z,RotateEnd2 ;B bounces off other puyo RotateRBounce: LDHL(1,0) ld (v_AXdir),hl LDHL(0,1) ld a,(v_BX) cp LEFTWALL ;B flips off left wall jr z,RotateRFlip push hl ld hl,(v_AX) ld a,8 add a,l ld l,a call GetIndex ld a,(hl) pop hl or a jr z,RotateEnd2 ;B flips off other puyo RotateRFlip: ld hl,v_Rot inc (hl) LDHL(0,4) ld (v_AXdir),hl LDHL(0,3) jr RotateEnd2 RotateToDown: LDHL(1,3) ld a,(v_BY) cp FLOOR ;B bounces off floor jr z,RotateDBounce push hl ld hl,(v_AX) ld a,8 add a,h ld h,a call GetIndex ld a,(hl) pop hl or a jr z,RotateEnd2 ;B bounces off other puyo RotateDBounce: LDHL(0,2) ld (v_AXdir),hl LDHL(1,0) ld a,(v_AY) or a jr nz,RotateEnd2 ;B flips off roof RotateDFlip: ld hl,v_Rot inc (hl) LDHL(4,0) ld (v_AXdir),hl LDHL(3,0) RotateEnd2: jr RotateEnd RotateToLeft: LDHL(3,2) ld a,(v_BX) cp LEFTWALL ;B bounces off left wall jr z,RotateLBounce push hl ld hl,(v_AX) ld a,8 add a,l ld l,a call GetIndex ld a,(hl) pop hl or a jr z,RotateEnd ;B bounces off other puyo RotateLBounce: LDHL(2,0) ld (v_AXdir),hl LDHL(0,2) ld a,(v_BX) cp RIGHTWALL ;B flips off right wall jr z,RotateLFlip push hl ld hl,(v_AX) ld a,-8 add a,l ld l,a call GetIndex ld a,(hl) pop hl or a jr z,RotateEnd ;B flips off other puyo RotateLFlip: ld hl,v_Rot inc (hl) LDHL(0,3) ld (v_AXdir),hl LDHL(0,4) jr RotateEnd RotateToUp: LDHL(2,4) ld a,(v_BY) or a ;B bounces off roof jr nz,RotateEnd RotateUBounce: LDHL(0,1) ld (v_AXdir),hl LDHL(2,0) push hl ld hl,(v_AX) ld a,8 add a,h ld h,a call GetIndex ld a,(hl) pop hl or a jr z,RotateEnd ;B flips off roof RotateUFlip: ld hl,v_Rot inc (hl) LDHL(3,0) ld (v_AXdir),hl LDHL(4,0) RotateEnd: ld (v_BXdir),hl ld hl,v_Rot ld a,(hl) inc a and %00000011 ;Mod4 keeps it 0,1,2,3 ld (hl),a ld a,MATHMAX ld (t_Move),a jp timers ;############################# ;# Post-Dropped Operations # ;############################# NextPiece: ld a,(v_ANext) ld (v_Atype),a ld a,(v_BNext) ld (v_Btype),a or a call nz,DrawNextPuyos call GetRand inc a ld (v_ANext),a call GetRand inc a ld (v_BNext),a call BombRand call DrawNextPuyos LDHL(40,0) ld (v_AX),hl LDHL(32,0) ld (v_BX),hl xor a ld (v_Rot),a ld a,(v_Speed) ld (t_Delay),a ld a,(v_Atype) cp BOMB ret nz BombSetup: LDHL(40,0) ld (v_BX),hl ret FallingBlocks: xor a ld (v_FallCnt),a call FallingCheck B_CALL(_GrBufCpy) ld a,(v_UseLastKey) or a ret nz halt halt halt ld a,(v_FallCnt) or a jr nz,FallingBlocks call LongPause ret FallingCheck: ld ix,v_GameBoard+72 ld c,6 FallingNextRow: ld a,c or a ret z dec c ld b,12 FallingScanUp: dec b dec ix ld a,b or a jr z,FallingNextRow ld a,(ix+0) or a jr nz,FallingScanUp FallingShift: ld a,(ix-1) ld (ix+0),a ld (ix-1),0 or a jr z,FallingSkipDraw ld hl,v_FallCnt inc (hl) push ix push bc push af inc c inc c sla c sla c sla c sla b sla b sla b ld d,b ld e,c call DrawSprite pop af pop bc push bc inc c inc c sla c sla c sla c dec b sla b sla b sla b ld d,b ld e,c call DrawSprite pop bc pop ix FallingSkipDraw: dec ix dec b ld a,b or a jr z,FallingNextRow jr FallingShift ComboBlocksMain: ld hl,v_CombMul inc (hl) ld hl,v_CombTyp ld (hl),TYPE1 ComboBlocks: ;Store Near info in ComboTemp ld b,11 ld c,0 ld ix,v_GameBoard ComboCountLoop: ld (ix+72),0 ld a,(ix+0) cp (hl) jr nz,ComboSkipCount call CountNear ld (ix+72),a ComboSkipCount: inc ix ld a,b or a jr nz,ComboSkipIncC ld b,12 inc c ComboSkipIncC: dec b ld a,c cp 6 jp nz,ComboCountLoop NearBlocks: ld b,11 ld c,0 ld ix,v_ComboTemp NearCountLoop: ld a,(ix+0) cp 2 jr nz,NearSkipDelete ld a,1 call CountNear cp 2 jr nz,NearSkipDelete ld (ix+0),0 NearSkipDelete: inc ix ld a,b or a jr nz,NearSkipIncC ld b,12 inc c NearSkipIncC: dec b ld a,c cp 6 jp nz,NearCountLoop NearBlocks2: ld b,11 ld c,0 ld ix,v_ComboTemp NearCountLoop2: ld a,(ix+0) cp 1 jr nz,NearSkipDelete2 call CountNear cp 1 jr nz,NearSkipSingleDel ld (ix+0),0 jr NearSkipDelete2 NearSkipSingleDel: xor a call CountNear cp 4 jr nz,NearSkipDelete2 ld (ix+0),0 NearSkipDelete2: inc ix ld a,b or a jr nz,NearSkipIncC2 ld b,12 inc c NearSkipIncC2: dec b ld a,c cp 6 jp nz,NearCountLoop2 NearFinished: call PopAnimationMain call ScoreMultiply call DrawScore ld hl,v_CombTyp ld a,(hl) cp TYPE6 ret z add a,8 ld (hl),a jp ComboBlocks CountNear: ld d,a ;Input ix = index ld e,0 ;Input a = match ld a,b ;Input b = y-value cp 11 ;Input c = x-value jr nz,CountSkipUp3 ;Output a = count ld a,d or a jr nz,CountSkipUp jr CountSkipUp2 CountSkipUp3: ld a,(ix-1) cp d jr nz,CountSkipUp CountSkipup2: inc e CountSkipUp: ld a,b or a jr nz,CountSkipDown3 ld a,d or a jr nz,CountSkipDown jr CountSkipDown2 CountSkipDown3: ld a,(ix+1) cp d jr nz,CountSkipDown CountSkipDown2: inc e CountSkipDown: ld a,c cp 5 jr nz,CountSkipLeft3 ld a,d or a jr nz,CountSkipLeft jr CountSkipLeft2 CountSkipLeft3: ld a,(ix+12) cp d jr nz,CountSkipLeft CountSkipLeft2: inc e CountSkipLeft: ld a,c or a jr nz,CountSkipRight3 ld a,d or a jr nz,CountSkipRight jr CountSkipRight2 CountSkipRight3: ld a,(ix-12) cp d jr nz,CountSkipRight CountSkipRight2: inc e CountSkipRight: ld a,e ret PopAnimationMain: xor a ld (v_CombCur),a ld a,EXPD1 - 8 ld (v_CombBom),a PopAnimation: ld ix,v_ComboTemp ld d,0 ld e,16 PopLoop: ld a,(ix+0) or a call nz,PopDeath ld a,(ix-72) cp GARBG call z,PopGarbage inc ix ld a,8 add a,d ld d,a cp 96 jr nz,PopLoop ld d,0 ld a,8 add a,e ld e,a cp 64 jr nz,PopLoop ld a,(v_CombCur) or a ret z ld hl,v_CombBom ld a,8 add a,(hl) ld (hl),a cp BLANK ret z halt halt halt B_CALL(_GrBufCpy) jr PopAnimation PopDeath: push ix push de ld a,(v_CombBom) cp EXPD1 - 8 jr z,PopEraseOld PopDeathDraw: call DrawSprite pop de push de ld a,(v_CombBom) add a,8 call DrawSprite pop de pop ix ret PopEraseOld: ld a,(ix-72) cp GARBG jr z,PopSkipPoints ld (ix-72),0 ld hl,v_CombFlg inc (hl) ld hl,v_CombCur inc (hl) PopSkipPoints: jr PopDeathDraw PopGarbage: push de srl d srl d srl d srl e srl e srl e dec e dec e ld a,11 sub d ld b,a ld c,e xor a call CountNear pop de cp 4 ret z ld a,(v_CombBom) cp BLANK - 8 jr nz,PopDeath PopClearGarbage: ld (ix-72),0 jr PopDeath GarbageMain: ld a,(v_InGarbage) or a jr nz,GarbageLoop call FallingBlocks ret GarbageLoop: ld hl,v_GameBoard call GetRand ld e,a srl a ld b,a add a,b add a,b ld b,0 ld c,a add hl,bc call GarbageAdd call GarbageCheckSpace jr nz,GarbageDrop jr GarbageMain GarbageDrop: ld hl,v_UseLastKey inc (hl) call FallingBlocks xor a ld (v_UseLastKey),a call GarbageCheckSpace ret nz jp GarbageMain GarbageAdd: ld a,(hl) or a ret nz ld (hl),GARBG ld a,16 add a,e ld d,0 ld e,a ld a,(hl) call DrawSprite ld hl,v_InGarbage dec (hl) ret GarbageCheckSpace: xor a ld ix,v_GameBoard cp (ix+0) ret z cp (ix+12) ret z cp (ix+24) ret z cp (ix+36) ret z cp (ix+48) ret z cp (ix+60) ret z inc a ret GarbageCompare: ld hl,v_InGarbage ld a,(v_OutGarbage) cp (hl) jr nc,GarbageCancelOut GarbageCancelIn: ld b,a ld a,(hl) sub b ld (hl),a xor a ld (v_OutGarbage),a ret GarbageCancelOut: sub (hl) ld (v_OutGarbage),a ld (hl),0 ret BombRand: ld hl,t_Bomb inc (hl) ld a,(hl) cp AVGBOMBFREQ ret c call GetRand or a ret nz ld (hl),a ld a,BOMB ld (v_Anext),a ld a,BLANK ld (v_Bnext),a ret BombMain: call FlashScreenFast ld hl,v_ComboTemp ld b,72 call ZeroRam ld hl,(v_AX) call GetIndex push hl pop ix ld (ix+72),1 ld a,(V_AY) cp FLOOR jr z,BombExplode inc hl ld a,(hl) cp GARBG jr z,BombExplode ld ix,v_GameBoard ld b,72 BombLoop: ld a,(ix+0) cp (hl) jr nz,BombLoop2 ld (ix+72),1 BombLoop2: inc ix djnz BombLoop BombExplode: call PopAnimationMain call DrawScore B_CALL(_GrBufCpy) ret ;########################## ;# Game Engine Routines # ;########################## DrawPuyos: ld a,(v_Atype) ld de,(v_AX) call DrawSprite ld a,(v_Btype) ld de,(v_BX) call DrawSprite ret DrawAllPuyos: LDDE(2,0) ld hl,v_GameBoard DrawAllPuyosLoop: push hl push de sla d sla d sla d sla e sla e sla e ld a,(hl) or a jr nz,DrawAllPuyosBlank ld a,BLANK DrawAllPuyosBlank: call DrawSprite pop de pop hl inc hl inc d ld a,12 cp d jr nz,DrawAllPuyosLoop ld d,0 inc e ld a,8 cp e jr nz,DrawAllPuyosLoop ret DrawSprite: ld b,0 ;Input a = Sprite Index Shift ld c,a ;Input de = Sprite Position ld ix,s_null add ix,bc ld hl,0 ld (currow),hl ld b,0 ld c,e add hl,bc add hl,bc add hl,bc add hl,hl add hl,hl ld c,d srl c srl c srl c add hl,bc ld bc,plotsscreen add hl,bc ld a,d ld d,8 and %00000111 jr z,DrawSpriteAligned ld (curcol),a DrawSpriteNonAligned: ld b,(ix+0) ld c,0 ld a,(curcol) DrawSpriteorXorShift: srl b rr c dec a jr nz,DrawSpriteorXorShift DrawSpriteEndShift: ld a,(currow) and %00000010 call z,DrawSpritePutSprite ld b,c inc hl ld a,(currow) and %00000001 call z,DrawSpritePutSprite inc ix ld bc,11 add hl,bc dec d jr nz,DrawSpriteNonAligned ret DrawSpriteAligned: ld b,(ix+0) call DrawSpritePutSprite inc ix ld bc,12 add hl,bc dec d jr nz,DrawSpriteAligned ret DrawSpritePutSprite: ld a,(hl) xor b ld (hl),a ret DrawInfoBar: ld hl,s_InfoBar ld de,plotSScreen ld bc,192 ldir ret DrawNextPuyos: ld a,(v_BNext) LDDE(5,16) call DrawSprite ld a,(v_ANext) LDDE(5,8) call DrawSprite ret DrawBarsSetup: ;Input d = What to 'and' with ld b,64 ;Input e = What to 'cp' with ld hl,plotSScreen push de DrawBarsAnimLoop: ld a,b pop de push de and d cp e jr nz,DrawBarsAnimSkip ld a,(hl) cpl ld (hl),a ld de,11 add hl,de ld a,(hl) cpl ld (hl),a inc hl jr DrawBarsLoopEnd DrawBarsAnimSkip: ld de,12 add hl,de DrawBarsLoopEnd: djnz DrawBarsAnimLoop pop de ret WaitForKey: B_CALL(_getkey) or a ret nz jr WaitForKey GetIndex: ;Input (X,Y) = (l,h) srl h ;Output MapIx = hl srl h srl h ld a,l srl l add a,l sub 24 add a,h ld b,0 ld c,a ld hl,v_GameBoard add hl,bc ;index += (L/8 - 2)*12 + H/8 ret GetRand: ld a,(v_RSeed) ;Output: a ld b,a ;Returns random number add a,a ;0, 8, 16, 24, 32, or 40 add a,a add a,b inc a ld (v_RSeed),a ld a,r add a,b and %00111000 cp %00110000 jr nc,GetRand ret DrawScore: DRAWINT(v_Score,55,4) ret ScoreMultiply: ld a,(v_CombCur) ld h,0 ld l,a ld a,(v_CombMul) ld b,a jr ScoreStartOfLoop ScoreLoop: add hl,hl ScoreStartOfLoop: djnz ScoreLoop ld b,h ld c,l ld hl,(v_CombTot) add hl,bc ld (v_CombTot),hl ld hl,(v_Score) add hl,bc ld (v_Score),hl ld hl,v_OutGarbage xor a or b jr nz,ScoreMaxSend ;If points is over 255, send max amount or c ret z ;If points is zero, don't send any dec c srl c dec c ld a,c add a,(hl) jr c,ScoreMaxSend ;If total is over 126, send max amount cp 126 jr nc,ScoreMaxSend ld (hl),a ;(P-1)/2-1 Garbage Blocks get sent ret ScoreMaxSend: ld (hl),126 ret DrawNewGarbage: ld a,(v_InGarbage) call DrawBar ld (plotSScreen+25),hl ld a,(v_OutGarbage) ;If 2 player, draw out call DrawBar ;garbage. ld (plotSScreen+13),hl ld a,(v_Mode) or a ret nz ;If single player, draw ld a,(t_Garbage) ;garbage timer instead. call DrawBar ld (plotSScreen+13),hl ret DrawBar: ld b,16 ld ix,m_logscale LDHL(%00000001,%00000000) DrawBarLoop: cp (ix+0) jr c,DrawBarDone inc ix add hl,hl djnz DrawBarLoop DrawBarDone: dec hl ld a,l ;I hate little endian... ld l,h ld h,a ret GarbageTimer: ld hl,t_Garbage dec (hl) ret nz call GarbageMain GarbageTimerSet: ld a,GARBAGETIME ld (t_Garbage),a ld a,(v_Level) sla a add a,3 ;2*level + 3 = garbage to cancel ld (v_InGarbage),a xor a ld (v_OutGarbage),a ret NextLevelCheck: ld a,(v_Level) cp NUMBOFLEVELS ret nc call CheckCanGoToNext ret c call DrawAllPuyos DRAWIMG(s_NextLevel,32,23) B_CALL(_GrBufCpy) call FlashScreenSlow call GameRedraw NextLevelAdvance: ld hl,v_Level inc (hl) ld hl,v_Speed dec (hl) dec (hl) dec (hl) ld a,(v_Level) cp NUMBOFLEVELS ret nc call CheckCanGoToNext jr nc,NextLevelAdvance ret CheckCanGoToNext: sla a ld b,0 ld c,a ld hl,m_levelpoints-2 add hl,bc ld e,(hl) inc hl ld d,(hl) ld hl,(v_Score) B_CALL(_CpHLDE) ret FlashScreenFast: ld e,FLASHPAUSESHORT ld d,FLASHES jr FlashScreenloop1 FlashScreenSlow: ld e,FLASHPAUSELONG ld d,FLASHES+2 FlashScreenloop1: ld bc,768 ld hl,plotsscreen FlashScreenloop2: ld a,(hl) cpl ld (hl),a inc hl dec bc ld a,b or c jr nz,FlashScreenloop2 push de B_CALL(_GrBufCpy) pop de PAUSE(e) dec d jr nz,FlashScreenloop1 ret LongPause: PAUSE(LONGPAUSETIME) ShortPause: PAUSE(SHORTPAUSETIME) ret ResetAllRam: ld hl,RamStart ld b,RamEnd-RamStart ZeroRam: ld (hl),0 inc hl djnz ZeroRam ret ;################## ;# Multi Player # ;################## WINBIT =%11111111 LinkReceiveGarbage: call CheckLink ret nz cp WINBIT jr z,LinkWeWin ld (v_InGarbage),a call DrawNewGarbage ret LinkWeWin: ld SP,(v_SaveSP) ;Jump out of any subroutines B_CALL(_GrBufClr) DRAWTEXT(txt_Winner,28,22) B_CALL(_GrBufCpy) PAUSE(100) call WaitForKey jp MainMenuSetup LinkSendGarbage: ld a,(v_OutGarbage) ;(P-1)/2-1 Garbage Blocks get sent call SendByte xor a ld (v_OutGarbage),a ret ;######################### ;# EASY LINK ROUTINES! # ;############################################################# ;# I couldn't find an understandable one on the internet, so # ;# I tortured myself literally for months to write this. # ;# Please feel free to use this in your own code. Hopefully # ;# I have saved someone the pain this has caused me. # ;# # ;# 1. All loops will dissolve if the cable is unplugged or # ;# clear is pressed, so it cannot freeze the calculator. # ;# # ;# 2. The routines are fast enough for 99% of applications. # ;# To enhance the speed, there are no byte confirmations, # ;# timeouts, or receiver break keys. You can add those # ;# yourself if you so desire. # ;# # ;# 3. The sender will always wait for the receiver to be # ;# ready before it sends the byte. (no incomplete data) # ;# # ;############################################################# ;INPUT: ;-none- ; ;OUTPUT: ;If a byte was received, z is set ;The 'a' and 'e' register both hold the byte ; ;REGISTERS DESTROYED: ;All but c CheckLink: LINKOUT(set00) ;Make sure we are reset LINKIN(getL0) ;Check to see if sender is ready ret nz ;If not, then go back ***(nz is still set)*** LINKOUT(set0R) ;Relay a confirmation QUICKPAUSE(8) ;Wait so confirmation is read LDDE(0,8) ;Bit counter in d and store received byte in e LINKOUT(set00) ;Reset the ports to receive data GetLinkLoop: LINKIN(get0R) ;Wait until first bit is sent jr z,GetLinkLoop ;Loop until we get it cp get00 jr z,Getzero ;Go here if we get a zero cp getLR jr z,Getone ;Go here if we get a one jr CheckLink ;We should NEVER get a 0L. But just in case something goes terribly wrong... Getone: sla e ;Shift the bits left inc e ;Put a one in the first bit jr GetDoneBit Getzero: sla e ;Shift the bits left, zero is in the first bit GetDoneBit: QUICKPAUSE(10) ;Wait for the sender to change dec d ;Change the bit counter jr nz,GetLinkLoop ;Keep looping if we haven't got all the bits ld a,e ret ;Otherwise, we're done. ***(z is still set)*** ;INPUT: ;'a' is the byte you will send ; ;OUTPUT: ;-none- ; ;REGISTERS DESTROYED: ;All but c SendByte: ld e,a ;Copy the sending byte to e ld d,8 ;Bit counter in d LINKOUT(setL0) ;Indicate we are ready to send SendWaitConfirm: KEY(rowQuit,KQuit) jp z,QuitGame ;Just in case... LINKIN(getLR) ;Wait for confirmation jr nz,SendWaitConfirm ;Keep looping till we get it SendLinkLoop: LINKOUT(set0R) ;This is the waiting state QUICKPAUSE(12) ld a,e and %10000000 ;Check the first bit jr z,SendZero ;Go here if we need to send a zero SendOne: LINKOUT(setLR) ;Send a one jr SendDone SendZero: LINKOUT(set00) ;Send a zero SendDone: QUICKPAUSE(8) ;Wait to make sure they got it sla e ;Get ready for the next bit dec d ;Advance the bit counter jr nz,SendLinkLoop ;Loop if there are more bits to send LINKOUT(set00) ;Reset the port ret ;We're done ;################ ;# High Score # ;################ HighScore2RAM: ld hl,v_HSDataStart ld b,HSSIZE call ZeroRam ld a,MINBESTCOMBO ld (v_HSComboScore),a FIND(txt_AppVar) jr c,CreateAppVar ld a,b or a ret nz inc de inc de ld hl,v_HSDataStart ex de,hl ld bc,HSSIZE ldir ret CreateAppVar: ld hl,HSSIZE B_CALL(_CreateAppVar) jr RAMDataCopy RAM2HighScore: FIND(txt_AppVar) ret c ld a,b or a ret nz RAMDataCopy: inc de inc de ld hl,v_HSDataStart ld bc,HSSIZE ldir ret CheckScore: ld a,(v_Mode) or a ret nz ld b,5 ld ix,v_HSScores CheckScoreLoop: ld hl,(v_Score) ld d,(ix+1) ld e,(ix+0) ex de,hl B_CALL(_CPHLDE) jr c,ShiftScore inc ix inc ix djnz CheckScoreLoop ret ShiftScore: ld ix,v_HSScores+8 djnz ShiftScoreLoop jr ReplaceScore ShiftScoreLoop: ld a,(ix-2) ld (ix+0),a ld a,(ix-1) ld (ix+1),a dec ix dec ix djnz shiftScoreLoop ReplaceScore: ld (ix+1),d ld (ix+0),e B_CALL(_GrBufClr) DRAWTEXT(txt_HighScore,16,20) DRAWINT(v_Score,38,32) B_CALL(_GrBufCpy) call WaitForKey ret CheckBestCombo: ld hl,(v_CombTot) ex de,hl ld hl,(v_HSComboScore) B_CALL(_CPHLDE) ret nc ex de,hl ld (v_HSComboScore),hl ld hl,v_HSAtype ld a,(v_Atype) ld (hl),a inc hl ld a,(v_Btype) ld (hl),a inc hl ld a,(v_AX) ld (hl),a inc hl ld a,(v_Rot) ld (hl),a ld hl,v_GameBackUp ld de,v_HSCombo ld bc,72 ldir call DrawAllPuyos DRAWIMG(s_BestCombo,32,21) B_CALL(_GrBufCpy) call FlashScreenSlow call GameRedraw ret ;############## ;# Tutorial # ;############## TutorialMain: ld hl,tut_goal call TutorialTextDraw ld hl,tut_combos call TutorialTextDraw set 2,(IY+50) ;Big Font ld hl,tut_map_1 call StealThisCodeForTut ld hl,tut_garbage call TutorialTextDraw ld hl,tut_bombs call TutorialTextDraw set 2,(IY+50) ;Big Font ld hl,tut_map_2 call StealThisCodeForTut ld hl,tut_2players call TutorialTextDraw jp MainMenuSetup TutorialTextDraw: push hl B_CALL(_GrBufClr) pop hl xor a ld (PenRow),a ld b,(hl) inc hl set 2,(IY+50) ;Big Font call NextStringPrint res 2,(IY+50) ;Small Font TutorialTextLoop: call NextStringPrint djnz TutorialTextLoop TutorialTextDone: B_CALL(_GrBufCpy) call WaitForKey ret NextStringPrint: xor a ld (PenCol),a B_CALL(_VPutS) ld a,(PenRow) add a,7 ld (PenRow),a ret ;############## ;# End Game # ;############## GamePaused: ld a,(v_Mode) or a ret nz B_CALL(_GrBufClr) DRAWIMG(s_Paused,32,30) call DrawInfoBar B_CALL(_GrBufCpy) call WaitForKey GameRedraw: B_CALL(_GrBufClr) call DrawInfoBar call DrawNewGarbage call DrawNextPuyos call DrawScore call DrawAllPuyos ret GameOver: ld a,(v_Mode) dec a ld a,WINBIT call z,SendByte ld hl,plotSScreen+192 xor a ld (v_AX),a GameOverLoop1: ld c,%00111111 GameOverLoop2: ld b,48 GameOverLoop3: ld a,c and (hl) ld (hl),a ld de,12 add hl,de djnz GameOverLoop3 push bc push hl B_CALL(_GrBufCpy) pop hl pop bc ld de,-576 add hl,de ld a,c srl c srl c or a jr nz,GameOverLoop2 inc hl ld a,(v_AX) inc a ld (v_AX),a cp 12 jr nz,GameOverLoop1 DRAWIMG(s_GameOver,32,23) B_CALL(_GrBufCpy) call WaitForKey ld a,(v_Mode) or a call z,CheckScore jp MainMenuSetup QuitGame: call RAM2HighScore ;Save the high scores LINKOUT(set00) ;Reset the ports res 5,(IY+0) ;Don't display 'Done' res 2,(IY+2) ;Display home screen set 0,(IY+3) ;Graphs need to redraw res 4,(IY+9) ;Clear any [on] interrupts res 7,(IY+20) ;Don't draw text to buffer res 2,(IY+50) ;Keep small fonts small res 0,(IY+60) ;Plots not to buffer SETCUR(0,0) ;Reset cursor B_CALL(_GrBufClr) ;Clear the buffer B_CALL(_ClrScrnFull) ;Clear screens ld SP,(v_SaveSP) ;Jump out of any subroutines ret ;############# ;# Strings # ;############# txt_Single: .db "1 Player",0 txt_Two: .db "2 Player",0 txt_Tutorial: .db "Tutorial",0 txt_HighScores: .db "High Score",0 txt_Quit: .db "Quit",0 txt_s_Copyright: .db "Kevin Horowitz",0 txt_HighScores2: .db "HIGH SCORES",0 txt_FlipCalc: .db "Flip Calc",0 txt_Waiting: .db "Waiting...",0 txt_AppVar: .db 15h,"PuyoData" txt_HighScore: .db "High Score!",0 txt_Winner: .db "Winner!",0 ;###################### ;# Tutorial Related # ;###################### tut_goal: .db 7 .db "GOAL",0 .db "Different blocks fall from",0 .db "the sky. When four or more",0 .db "of the same kind come into",0 .db "contact, they annihilate.",0 .db "Your goal is to prevent the",0 .db "blocks from overflowing",0 .db "the board.",0 tut_combos: .db 4 .db "COMBOS",0 .db "You can maneuver the blocks",0 .db "to make devastating chain",0 .db "reactions for bonus points.",0 .db "For instance...",0 tut_garbage: .db 8 .db "GARBAGE BLOCKS",0 .db "A timer is always set to drop",0 .db "garbage onto the board. You",0 .db "can prevent the garbage",0 .db "only by doing combos. The",0 .db "larger the reaction, the less",0 .db "is dropped. Garbage blocks",0 .db "can only be destroyed by a",0 .db "nearby annihilation.",0 tut_bombs: .db 4 .db "BOMBS",0 .db "Occasionally you will get a",0 .db "bomb. If a bomb is dropped",0 .db "on any block, all similar",0 .db "blocks will be destroyed...",0 tut_2players: .db 7 .db "2 PLAYER",0 .db "When playing against an",0 .db "opponent, there is no timer.",0 .db "Instead, you send the other",0 .db "player garbage each time",0 .db "you do a combo. You can",0 .db "also cancel out incoming",0 .db "garbage with your combos.",0 tut_map_1: .db 1 ;v_HSAtype .db 9 ;v_HSBtype .db 40 ;v_HSAX .db 3 ;v_HSRot .db 0,0,0,0,0,0,0,0,0,17,9,9 .db 0,0,0,0,0,0,0,0,0,0,9,17 .db 0,0,0,0,0,0,0,0,0,9,1,17 .db 0,0,0,0,0,0,0,0,0,1,1,17 .db 0,0,0,0,0,0,0,0,0,0,0,0 .db 0,0,0,0,0,0,0,0,0,0,0,0 tut_map_2: .db BOMB ;v_HSAtype .db BLANK ;v_HSBtype .db 40 ;v_HSAX .db 0 ;v_HSRot .db 0,0,0,0,0,0,1,1,1,25,25,9 .db 0,0,0,0,0,0,0,0,0,1,9,17 .db 0,0,0,0,0,0,0,0,25,9,1,17 .db 0,0,0,0,0,0,0,0,0,1,1,17 .db 0,0,0,0,0,0,0,0,0,25,9,1 .db 0,0,0,0,0,0,0,1,1,17,1,1 ;################### ;# Miscellaneous # ;################### m_logscalereal: ;.db 1 ;Stealing a 1 from end of tut_map_2 .db 2,3,4,6,9,12,15,18,24,30,36,42,54,66,80 m_logscale =m_logscalereal - 1 m_levelpoints: ;Points needed .dw 100,200,300,500,700 ;for next level .dw 900,1200,1500,1800 .dw 2400,3000 m_levelend: NUMBOFLEVELS =(m_levelend - m_levelpoints)/2 m_accel: ;This is a sine wave .db 0,1,2,2,3 ;broken up into 4 m_decel: ;equal parts. (where .db 3,2,2,1,0 ;each sum is 8) m_naccel: .db 0,-1,-2,-2,-3 m_ndecel: .db -3,-2,-2,-1;,0 ;Steal the last zero from s_null MATHMAX =m_decel - m_accel ;############# ;# Sprites # ;############# s_null: .db 0 s_Type1: .db %00111100 .db %01111110 .db %11001111 .db %11011111 .db %11111111 .db %11111111 .db %01111110 .db %00111100 s_Type2: .db %00111100 .db %01000010 .db %10110001 .db %10100001 .db %10000001 .db %10000001 .db %01000010 .db %00111100 s_Type3: .db %00011000 .db %00100100 .db %01100110 .db %10011001 .db %10011001 .db %01100110 .db %00100100 .db %00011000 s_Type4: .db %01111110 .db %10100011 .db %11000101 .db %10001001 .db %10010001 .db %10100011 .db %11000101 .db %01111110 s_Type5: .db %01111000 .db %10101100 .db %11010110 .db %10101011 .db %11010101 .db %01101011 .db %00110101 .db %00011110 s_Type6: .db %00000011 .db %00001101 .db %00110001 .db %11000001 .db %11000001 .db %00110001 .db %00001101 .db %00000011 s_Garbage: .db %00000000 .db %00000000 .db %00011000 .db %00100100 .db %00100100 .db %00011000 .db %00000000 .db %00000000 s_Bomb: .db %00000000 .db %00001100 .db %10010110 .db %10100111 .db %10111111 .db %01011110 .db %00001100 .db %00000000 s_Explode1: .db %00111100 .db %01111110 .db %11111111 .db %11111111 .db %11111111 .db %11111111 .db %01111110 .db %00111100 s_Explode2: .db %00000000 .db %00111100 .db %01111110 .db %01111110 .db %01111110 .db %01111110 .db %00111100 .db %00000000 s_Explode3: .db %00000000 .db %00000000 .db %00011000 .db %00111100 .db %00111100 .db %00011000 .db %00000000 .db %00000000 s_Explode4: .db %00000000 .db %00000000 .db %00000000 .db %00011000 .db %00011000 .db %00000000 .db %00000000 .db %00000000 s_Blank: .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 TYPE1 =s_Type1 - s_null TYPE2 =s_Type2 - s_null TYPE3 =s_Type3 - s_null TYPE4 =s_Type4 - s_null TYPE5 =s_Type5 - s_null TYPE6 =s_Type6 - s_null EXPD1 =s_Explode1 - s_null EXPD2 =s_Explode2 - s_null EXPD3 =s_Explode3 - s_null EXPD4 =s_Explode4 - s_null BLANK =s_Blank - s_null GARBG =s_Garbage - s_null BOMB =s_Bomb - s_null s_InfoBar: .db %10111111,%11111111,%11111111,%11110000,%01000001,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111 .db %10000010,%00000000,%00000000,%01110111,%01011101,%10011000,%11011111,%11111111,%11111111,%11111111,%11111111,%11111111 .db %10111110,%00000000,%00000000,%01110000,%01000001,%00001000,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %11111111,%11111111,%11111111,%11111111,%11111111,%00100010,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %10010010,%00000000,%00000000,%01110000,%01000001,%01110111,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %11101110,%00000000,%00000000,%01111101,%01110101,%00110110,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %10010010,%00000000,%00000000,%01110001,%01000101,%10011100,%11011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %11111110,%00000000,%00000000,%01111111,%11111111,%11111111,%11011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %10101010,%00000000,%00000000,%01110000,%01000001,%11001000,%11011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %10000010,%00000000,%00000000,%01111111,%01111101,%10001000,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %11111110,%00000000,%00000000,%01110000,%01000001,%01110111,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %10000010,%00000000,%00000000,%01111111,%11111111,%01110111,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %11101110,%00000000,%00000000,%01110001,%11000111,%01110111,%01011100,%00000000,%00000000,%00000000,%00000000,%00000011 .db %11011110,%00000000,%00000000,%01110101,%11010111,%10001000,%01011111,%11111111,%11111111,%11111111,%11111111,%11111111 .db %10000011,%11111111,%11111111,%11110000,%01000001,%11001000,%11011111,%11111111,%11111111,%11111111,%11111111,%11111111 .db %11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111,%11111111 s_GameOver: .db 32,8 .db %11110111 .db %10001000 .db %11111111 .db %00000000 .db %10010001 .db %11111111 .db %00000000 .db %11111110 .db %00000001 .db %11111110 .db %00000000 .db %11111111 .db %10000001 .db %11111111 .db %00000000 .db %00000000 .db %10010001 .db %11111111 .db %00000000 .db %11111111 .db %01000000 .db %00111110 .db %01000000 .db %11111111 .db %00000000 .db %11111111 .db %10010000 .db %11111111 .db %00000000 .db %10011111 .db %10000001 .db %11111111 s_Paused: .db 23,8 .db %01111110 .db %10000001 .db %11111111 .db %00000000 .db %10010001 .db %10010001 .db %11111111 .db %00000000 .db %10011111 .db %10010001 .db %11110001 .db %00000000 .db %11111111 .db %00000001 .db %11111111 .db %00000000 .db %11111111 .db %10010000 .db %11111111 .db %00000000 .db %11110000 .db %10010000 .db %11111111 s_NextLevel .db 33,8 .db %00000001 .db %11111111 .db %00000000 .db %10010001 .db %11111111 .db %00000000 .db %11111110 .db %00000001 .db %11111110 .db %00000000 .db %10010001 .db %11111111 .db %00000000 .db %00000001 .db %11111111 .db %00000000 .db %00000000 .db %00000000 .db %10000000 .db %11111111 .db %10000000 .db %00000000 .db %11101111 .db %00010000 .db %11101111 .db %00000000 .db %10010001 .db %11111111 .db %00000000 .db %11111111 .db %00010000 .db %00100000 .db %11111111 s_BestCombo .db 38,8 .db %11111101 .db %00000000 .db %11111111 .db %10000001 .db %11111111 .db %00000000 .db %01101110 .db %10010001 .db %11111111 .db %00000000 .db %11111111 .db %01000000 .db %00111111 .db %01000000 .db %11111111 .db %00000000 .db %11111111 .db %10000001 .db %11111111 .db %00000000 .db %10000001 .db %11111111 .db %00000000 .db %00000000 .db %00000000 .db %10000000 .db %11111111 .db %10000000 .db %00000000 .db %10011111 .db %11110001 .db %00000000 .db %10010001 .db %11111111 .db %00000000 .db %01101110 .db %10010001 .db %11111111 s_Title_Puyo: .db 20,40 .db %00000111,%11000000,%00000000,%00000000,%00000000 .db %00011000,%00111100,%00000000,%00000000,%00000000 .db %01100000,%00000010,%00000000,%00000000,%00000000 .db %01000000,%00000010,%00000000,%00000110,%00000000 .db %10000000,%00000001,%00000000,%00001001,%00000000 .db %10000001,%10000001,%00000011,%10001001,%00000000 .db %10000010,%01000001,%00000100,%01001001,%01110000 .db %01000010,%10000001,%00000100,%00101001,%10001000 .db %01000001,%00000010,%10001110,%00010001,%00000100 .db %01000000,%00000100,%01001001,%00000001,%00000010 .db %01000000,%00011000,%01010001,%00000010,%00000010 .db %00100000,%01101000,%01010001,%10000010,%00100010 .db %00100000,%01001000,%01100001,%10000010,%01010010 .db %00100000,%01101000,%00100001,%01000100,%01010010 .db %00010000,%00101000,%00000001,%01000100,%00100010 .db %00010000,%00100100,%00000011,%10001010,%00000100 .db %00010000,%00100100,%00000010,%10001010,%00000100 .db %00001000,%01100010,%00000100,%10010001,%00001000 .db %00001100,%01000001,%00011000,%01100000,%11110000 .db %00000011,%10000000,%11100000,%00000000,%00000000 s_Title_83: .db 20,32 .db %01111111,%11111100,%00111111,%11111100 .db %10000000,%00000010,%01000000,%00000010 .db %10000111,%11000010,%01000011,%11000010 .db %10001000,%00100010,%01000100,%00100010 .db %11111000,%00111110,%01111100,%00111110 .db %11111000,%00111110,%00011100,%00111110 .db %11111000,%00111110,%00000000,%00111110 .db %11111000,%00111110,%00000000,%00111110 .db %01100111,%11001100,%00000001,%11000100 .db %00010000,%00010000,%00000001,%00001000 .db %00010000,%00010000,%00000001,%00001000 .db %01100111,%11001100,%00000001,%11100110 .db %11111000,%00111110,%00000000,%00011111 .db %11111000,%00111110,%00000000,%00011111 .db %11111000,%00111110,%00011100,%00011111 .db %11111000,%00111110,%01111100,%00011111 .db %10001000,%00100010,%01000100,%00010001 .db %10000111,%11000010,%01000011,%11100001 .db %10000000,%00000010,%01000000,%00000011 .db %01111111,%11111100,%00111111,%11111100 s_Title_83_Mask: .db %01111111,%11111100,%00111111,%11111100 .db %01111000,%00111100,%00111100,%00111100 .db %01110000,%00011100,%00111000,%00011100 .db %01110000,%00011100,%00011000,%00011100 .db %01110000,%00011100,%00000000,%00011100 .db %01110000,%00011100,%00000000,%00011100 .db %01110000,%00011100,%00000000,%00011100 .db %00011000,%00110000,%00000000,%00111000 .db %00001111,%11100000,%00000000,%11110000 .db %00001111,%11100000,%00000000,%11110000 .db %00011000,%00110000,%00000000,%00011000 .db %01110000,%00011100,%00000000,%00001110 .db %01110000,%00011100,%00000000,%00001110 .db %01110000,%00011100,%00000000,%00001110 .db %01110000,%00011100,%00011000,%00001110 .db %01110000,%00011100,%00111000,%00001110 .db %01111000,%00111100,%00111100,%00011110 .db %01111111,%11111100,%00111111,%11111100 s_Copyright: .db 8,8 .db %00000000 .db %00111110 .db %01000001 .db %01011101 .db %01010001 .db %01011101 .db %01000001 .db %00111110 s_Dpad: .db 43,43 .db %00000000,%00000000,%10000000,%00000000,%00000000,%00000000 .db %00000000,%00000000,%11111000,%00000000,%00000000,%00000000 .db %00000000,%00000000,%10000000,%00000000,%00000000,%00000000 .db %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 .db %00000000,%00000000,%11111001,%11111111,%11110000,%00000000 .db %00000000,%00000000,%00100010,%00000000,%00001000,%00000000 .db %00000000,%00000000,%11111010,%00000011,%00001000,%00000000 .db %00000000,%00000000,%00000010,%00000110,%00001000,%00000000 .db %00000000,%00000000,%10111010,%00001100,%00001000,%00000000 .db %00000000,%00000000,%10001010,%00011110,%00001000,%00000000 .db %00000000,%00000000,%11111010,%00011011,%00001000,%00000000 .db %00000000,%00000000,%00000010,%00011011,%00001000,%00000000 .db %10101000,%00000000,%11111010,%00001110,%00001000,%00000000 .db %11111000,%00000000,%00000010,%00000000,%00001000,%00000000 .db %00000000,%00000000,%11011001,%11111111,%11110000,%00000000 .db %10000000,%00000000,%10100000,%00000000,%00000000,%00000000 .db %11111000,%00000000,%11111000,%00000000,%00000011,%10000000 .db %10000000,%00000000,%00000000,%00000000,%00000010,%10000000 .db %00000001,%11111111,%11110001,%11111111,%11110011,%11100000 .db %11111010,%00000000,%00001010,%00000000,%00001000,%00000000 .db %10100010,%00011110,%00001010,%00001110,%00001011,%11100000 .db %11111010,%00011111,%00001010,%00011111,%00001010,%00100000 .db %00000010,%00000011,%00001010,%00010011,%00001011,%11100000 .db %10000010,%00000110,%00001010,%00000110,%00001000,%00000000 .db %11111010,%00001100,%00001010,%00010011,%00001011,%01100000 .db %10000010,%00011111,%00001010,%00011111,%00001010,%10000000 .db %00000010,%00011111,%00001010,%00001110,%00001011,%11100000 .db %11111010,%00000000,%00001010,%00000000,%00001000,%00000000 .db %10001001,%11111111,%11110001,%11111111,%11110001,%11000000 .db %11111000,%00000000,%00000000,%00000000,%00000010,%00100000 .db %00000000,%00000000,%00000000,%00000000,%00000011,%11100000 .db %11011000,%00000000,%10000000,%00000000,%00000000,%00000000 .db %10100000,%00000000,%11111001,%11111111,%11110000,%00000000 .db %11111000,%00000000,%10000010,%00000000,%00001000,%00000000 .db %00000000,%00000000,%00000010,%00000000,%00001000,%00000000 .db %00000000,%00000000,%10100010,%00010001,%00001000,%00000000 .db %00000000,%00000000,%11111010,%00100000,%10001000,%00000000 .db %00000000,%00000000,%00000010,%00101110,%10001000,%00000000 .db %00000000,%00000000,%10101010,%00100000,%10001000,%00000000 .db %00000000,%00000000,%11111010,%00010001,%00001000,%00000000 .db %00000000,%00000000,%00000010,%00000000,%00001000,%00000000 .db %00000000,%00000000,%00001010,%00000000,%00001000,%00000000 .db %00000000,%00000000,%11111001,%11111111,%11110000,%00000000 s_PressAnyKey: .db 45,5 .db %11100000 .db %00011000 .db %11100000 .db %00000000 .db %10101000 .db %11111000 .db %00000000 .db %11011000 .db %00100000 .db %11111000 .db %00000000 .db %00000000 .db %00000000 .db %11100000 .db %00011000 .db %11100000 .db %00000000 .db %11111000 .db %00100000 .db %01000000 .db %11111000 .db %00000000 .db %11111000 .db %10100000 .db %11111000 .db %00000000 .db %00000000 .db %00000000 .db %00000000 .db %10111000 .db %11101000 .db %00000000 .db %10111000 .db %11101000 .db %00000000 .db %10101000 .db %11111000 .db %00000000 .db %11011000 .db %10100000 .db %11111000 .db %00000000 .db %11100000 .db %10100000 .db %11111000 s_Up: .db 7,8 .db %00011000 .db %00110000 .db %01100000 .db %11111111 .db %01100000 .db %00110000 .db %00011000 ;############## ;# Game Ram # ;############## RamStart =9872h ;###### TIMERS ###### t_Delay =RamStart ; .db 0 t_Move =t_Delay+1 ; .db 0 t_Bomb =t_Move+1 ; .db 0 t_Garbage =t_Bomb+1 ; .db 0 ;###### CURRENT PUYO ###### v_AX =t_Garbage+1 ; .db 0 v_AY =v_AX+1 ; .db 0 v_Atype =v_AY+1 ; .db 0 v_AXdir =v_Atype+1 ; .db 0 v_AYdir =v_AXdir+1 ; .db 0 v_BX =v_AYdir+1 ; .db 0 v_BY =v_BX+1 ; .db 0 v_BXdir =v_BY+1 ; .db 0 v_BYdir =v_BXdir+1 ; .db 0 v_Btype =v_BYdir+1 ; .db 0 v_Rot =v_Btype+1 ; .db 0 ;###### NEXT PUYO ###### v_ANext =v_Rot+1 ; .db 0 v_BNext =v_ANext+1 ; .db 0 ;###### COMBO SCORING ###### v_CombFlg =v_BNext+1 ; .db 0 v_CombCur =v_CombFlg+1 ; .db 0 v_CombMul =v_CombCur+1 ; .db 0 v_CombTot =v_CombMul+1 ; .db 0,0 v_CombTyp =v_CombTot+2 ; .db 0 v_CombBom =v_CombTyp+1 v_FallCnt =v_CombBom ; .db 0 ;###### GAME SETTINGS ###### v_LastKey =v_CombBom+1 ; .db 0 v_UseLastKey =v_LastKey+1 ; .db 0 v_Level =v_UseLastKey+1 ; .db 0 v_Speed =v_Level+1 ; .db 0 v_InGarbage =v_Speed+1 ; .db 0 v_OutGarbage =v_InGarbage+1 ; .db 0 v_Score =v_OutGarbage+1 ; .db 0,0 ;###### GAME BOARD ###### v_GameBoard =v_Score+2 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 v_ComboTemp =v_GameBoard+72 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 v_GameBackUp =v_ComboTemp+72 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 RamEnd =v_GameBackUp+72 ;#################### ;# High Score RAM # ;#################### v_HSDataStart =RamEnd v_HSScores =v_HSDataStart ; .db 0,0 ; .db 0,0 ; .db 0,0 ; .db 0,0 ; .db 0,0 v_HSAtype =v_HSScores+10 ; .db 0 v_HSBtype =v_HSAType+1 ; .db 0 v_HSAX =v_HSBType+1 ; .db 0 v_HSRot =v_HSAX+1 ; .db 0 v_HSCombo =v_HSRot+1 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 ; .db 0,0,0,0,0,0,0,0,0,0,0,0 v_HSComboScore =v_HSCombo+72 ; .db 0,0 v_HSDataEnd =v_HSComboScore+2 HSSIZE =v_HSDataEnd - v_HSDataStart ;################ ;# Global RAM # ;################ v_Mode =v_HSDataEnd ; .db 0 v_SaveSP =v_Mode+1 ; .db 0,0 v_RSeed =v_SaveSP+2 ; .db 0 .end