//------------------------------- // Snakes of Atari Island // // Author: Jakub "JKR" Krzak // Katowice, April 2012 //------------------------------- GameOver .proc mva #0 NMIEN lda clckMinutes pha lda clckSeconds pha mwa #DLI_Proc1A VDSLST mva #192 NMIEN PRINT_AT 2, 0 dta 38, c' +++ GAME OVER +++ ' dta 0 mvza _msgFlags mvza _sfx_ptr mvza RTCLOCK #if .byte _mute = #0 ldx #22 jsr CMC_PlaySongFrom #end #while .byte RTCLOCK <= #190 jsr Rainbow lda RTCLOCK and #8 sta __b #if .byte __b = #0 mva #cMaxMsgBrtnss _msgBrUpper #else mvza _msgBrUpper #end #end mva #cMaxMsgBrtnss _msgBrUpper mvza CH loop jsr Rainbow jsr CheckTrigger jcc loop jsr CMC_Stop mva #0 NMIEN mwa #DLI_Proc1 VDSLST mva #192 NMIEN pla sta __a pla sta __b #if .byte _selectedMode = #0 .or .byte _selectedMode = #1 ; time malus mvza RTCLOCK #while .byte RTCLOCK <= #30 #end #while .byte __b <> #255 ;minutes #while .byte __a > #0 ;seconds dec __a jsr PrintTime2 #if .byte _selectedMode = #0 lda SnW_Score ora SnW_Score+1 jeq l1 sbw SnW_Score #1 PrintScoreW #else lda SnB_Score ora SnB_Score+1 jeq l1 sbw SnB_Score #1 PrintScoreB #end l1 lda _mute jne l2 lda #1 ; channel ldy #2 ; instrument ldx #16 jsr CMC_PlayNote l2 mvza RTCLOCK #while .byte RTCLOCK < #4 #end #end mva #60 __a dec __b #end mvza CH loop2 jsr CheckTrigger jcc loop2 #end #if .word SnW_Score > #0 #if .word HiScore = #$FFFF .OR .word HiScore < SnW_Score mwa SnW_Score HiScore #end #end #if .word SnB_Score > #0 #if .word HiScore = #$FFFF .OR .word HiScore < SnB_Score mwa SnB_Score HiScore #end #end jsr ClearMsg rts .endp ;------------------------------------------------------------ ResurectW .proc checkFlag SnW_State cSSt_Dead scs rts changeMemory (_scr + 40) \ (_scr + 40*24) \ clearSnakeWhite clearFldW clearFlag _msgFlags cMsgUp_Blink writeTitle mva #cMaxMsgBrtnss _msgBrUpper mvza SnW_State mva #cRight SnW_Dir mva #cRight SnW_tmpDir mva #7 __a ; initial length clc jsr DrawSnakeAtRandomPos mwa #0 SnW_Score PRINT_AT 26 24 dta 14, c'SCORE W: 0 ', 0 mvza _sfx_tmr ;sound mva #21 _sfx_ptr rts .endp ;------------------------------------------------------------ ResurectB .proc checkFlag SnB_State cSSt_Dead scs rts changeMemory (_scr + 40) \ (_scr + 40*24) \ clearSnakeBlack clearFldB clearFlag _msgFlags cMsgUp_Blink writeTitle mva #cMaxMsgBrtnss _msgBrUpper mvza SnB_State mva #cLeft SnB_Dir mva #cLeft SnB_tmpDir mva #7 __a ; initial length sec jsr DrawSnakeAtRandomPos mwa #0 SnB_Score PRINT_AT 11 24 dta 14, c'SCORE B: 0 ', 0 mvza _sfx_tmr ;sound mva #21 _sfx_ptr rts .endp ;------------------------------------------------------------------------- CheckKeysInGame .proc lda CH cmp #62 ;S jne l1 ; mute/unmute lda _mute jne l2 mva #1 _mute mva #'d' _scr mva #'e' _scr+1 mvza CH rts l2: mvza _mute mva #" " _scr mva #" " _scr+1 mvza CH rts l1: cmp #18 ;C jne l3 jsr IncrementBgrndColorPtr ;PM_COLS0 = ColorSchemes(1, _bgrndColorPtr) ldy #1 lda (_arr),y sta PM_COLS0 ;PM_COLS1 = ColorSchemes(2, _bgrndColorPtr) ldy #2 lda (_arr),y sta PM_COLS1 mvza CH rts l3: cmp #47 ;Q jne l4 mva #cUp __a mvza CH rts l4: cmp #63 ;A jne l5 mva #cDown __a mvza CH rts l5: cmp #8 ;O jne l6 mva #cLeft __a mvza CH rts l6: cmp #10 ;P jne l7 mva #cRight __a mvza CH rts l7: cmp #12 ;Return jne l8 mvza CH checkFlag SnW_State cSSt_Dead scc jmp ResurectW jmp ResurectB l8: cmp #33 ;Space jne l9 lda SKSTAT and #4 jne l9 mva #cTrigger __a rts l9 rts .endp ;------------------------------------------------------------------------- GenerateFruit .proc ; C flag - 0: normal, 1: extra php l1 ; x = <1..38> lda RANDOM and #63 sta __x #if .byte __x > #37 sbb __x #38 #end adb __x #1 ; y = <2..22> lda RANDOM and #31 sta __y #if .byte __y > #20 sbb __y #21 #end adb __y #2 getScrAt __x, __y jne l1 ; again if not empty location plp bcc l2 ; extra mva __x fruitExtra_X mva __y fruitExtra_Y setScrAt fruitExtra_X, fruitExtra_Y, #chrFruitEx ; PM1_XPOS = 48 + 4 * fruitExtra_X lda fruitExtra_X asl asl clc adc #48 sta PM1_XPOS ldy fruitExtra_Y mva #$F0 FHighlightEx,Y mva #80 fruitExtraCntr rts l2 ; normal setScrAt __x, __y, #chrFruit ; PM0_XPOS = 48 + 4 * __x lda __x asl asl clc adc #48 sta PM0_XPOS mva __y fruit_Y ldy fruit_Y mva #$F0 FHighlight,Y rts .endp ;------------------------------------------------------------------------- HideExtraFruit .proc setScrAt fruitExtra_X, fruitExtra_Y, #0 mvza fruitExtraCntr ldy fruitExtra_Y lda #0 sta FHighlightEx,Y mvza fruitExtra_Y rts .endp ;------------------------------------------------------------------------- CheckScoreAndLevel .proc #if .word __x >= #10800 ; + 30 * 80 mva #9 Level mva #8 LevDelay #else #if .word __x >= #8400 ; + 30 * 70 mva #8 Level mva #9 LevDelay #else #if .word __x >= #6300 ; + 30 * 60 mva #7 Level mva #9 LevDelay #else #if .word __x >= #4500 ; + 30 * 50 mva #6 Level mva #10 LevDelay #else #if .word __x >= #3000 ; + 30 * 40 mva #5 Level mva #10 LevDelay #else #if .word __x >= #1800 ; + 30 * 30 mva #4 Level mva #11 LevDelay #else #if .word __x >= #900 ; + 30 * 20 mva #3 Level mva #11 LevDelay #else #if .word __x >= #300 ; + 30 * 10 mva #2 Level mva #12 LevDelay #end #end #end #end #end #end #end #end rts .endp ;------------------------------------------------------------------------- EatFruitB .proc ; C: 0 - normal, 1 - extra jcs l1 ;SnB_Score = SnB_Score + 10 * Level lda Level ldx #10 jsr _sys_mul8 lda SnB_Score clc adc _TW2 sta SnB_Score lda SnB_Score+1 adc _TW2+1 sta SnB_Score+1 mvza _sfx_tmr ;sound mva #1 _sfx_ptr jmp l2 l1 ;SnB_Score = SnB_Score + fruitExtraCntr lda SnB_Score clc adc fruitExtraCntr sta SnB_Score lda SnB_Score+1 adc #0 sta SnB_Score+1 mvza fruitExtraCntr mvza _sfx_tmr ;sound mva #4 _sfx_ptr l2 mwa SnB_Score __x jsr CheckScoreAndLevel jmp PrintScoreB .endp PrintScoreB .proc #if .byte _selectedMode = #1 ;"SCORE: [SnB_Score]" PRINT_AT 28 24 dta 7, c'SCORE: ' dta 130, a(SnB_Score) dta 1, c' ' dta 0 #else ;"SCORE B: [SnB_Score]" PRINT_AT 11 24 dta 9, c'SCORE B: ' dta 130, a(SnB_Score) dta 0 #end rts .endp ;------------------------------------------------------------------------- EatFruitW .proc ; C: 0 - normal, 1 - extra jcs l1 ;SnW_Score = SnW_Score + 10 * Level lda Level ldx #10 jsr _sys_mul8 lda SnW_Score clc adc _TW2 sta SnW_Score lda SnW_Score+1 adc _TW2+1 sta SnW_Score+1 mvza _sfx_tmr ;sound mva #1 _sfx_ptr jmp l2 l1 ;SnW_Score = SnW_Score + fruitExtraCntr lda SnW_Score clc adc fruitExtraCntr sta SnW_Score lda SnW_Score+1 adc #0 sta SnW_Score+1 mvza fruitExtraCntr mvza _sfx_tmr ;sound mva #4 _sfx_ptr l2 mwa SnW_Score __x jsr CheckScoreAndLevel jmp PrintScoreW .endp PrintScoreW .proc #if .byte _selectedMode = #0 ;"SCORE W: [SnW_Score]" PRINT_AT 28 24 dta 7, c'SCORE: ' dta 130, a(SnW_Score) dta 1, c' ' dta 0 #else ;"SCORE W: [SnW_Score]" PRINT_AT 26 24 dta 9, c'SCORE W: ' dta 130, a(SnW_Score) dta 0 #end rts .endp ;------------------------------------------------------------ CheckLevelAndExtraFruit .proc lda LevelTmp cmp Level jeq l1 ; level increased mvza _sfx_tmr ;sound mva #9 _sfx_ptr ; "LEVEL: [Level]" PRINT_AT 1 24 dta 7, c'LEVEL: ' dta 129, a(Level) dta 0 l1 #if .byte _mute = #0 ; snake's moving noise lda #2 ; channel ldx #29 ; note ldy #25 ; instrument jsr CMC_PlayNote #end #if .byte fruitExtraCntr = #0 #if .byte RANDOM = #63 sec jsr GenerateFruit #end #else dec fruitExtraCntr #if .byte fruitExtraCntr = #0 jsr HideExtraFruit #end #end rts .endp ;------------------------------------------------------------ MoveSnakeForwardW .proc mva SnW_tmpDir SnW_Dir checkFlag SnW_State cSSt_Grow scs jsr moveTailW clearFlag SnW_State cSSt_Grow jsr moveHeadW #if .byte __z = #3 ;snake's dead sec rts #else #if .byte __z = #2 ; extra fruit sec jsr EatFruitW #else #if .byte __z = #1 ; fruit clc jsr EatFruitW clc jsr GenerateFruit setFlag SnW_State cSSt_Grow #end #end #end mva SnW_Dir SnW_tmpDir clc rts .endp ;------------------------------------------------------------ MoveSnakeForwardB .proc mva SnB_tmpDir SnB_Dir checkFlag SnB_State cSSt_Grow scs jsr moveTailB clearFlag SnB_State cSSt_Grow jsr moveHeadB #if .byte __z = #3 ; snake's dead sec rts #else #if .byte __z = #2 ; extra fruit sec jsr EatFruitB #else #if .byte __z = #1 ; fruit clc jsr EatFruitB clc jsr GenerateFruit setFlag SnB_State cSSt_Grow #end #end #end mva SnB_Dir SnB_tmpDir clc rts .endp ;------------------------------------------------------------ MoveSnakeB .proc jsr MoveSnakeForwardB scs rts checkFlag SnW_State cSSt_Dead scc rts ; both are dead ; black is dead setFlag SnB_State cSSt_Dead changeMemory (_scr + 40) \ (_scr + 40*24) \ showSnakeBlackDead changeMemory arrSnakeFldB \ arrSnakeFldB_End \ showSnakeBlackDead PRINT_AT 2, 0 dta 38, c' +++ BLACK SNAKE IS DEAD +++ ', 0 setFlag _msgFlags cMsgUp_Blink mvza _sfx_tmr ;sound mva #14 _sfx_ptr clc rts .endp MoveSnakeW .proc jsr MoveSnakeForwardW scs rts checkFlag SnB_State cSSt_Dead scc rts ; both are dead ; white is dead setFlag SnW_State cSSt_Dead changeMemory (_scr + 40) \ (_scr + 40*24) \ showSnakeWhiteDead changeMemory arrSnakeFldW \ arrSnakeFldW_End \ showSnakeWhiteDead PRINT_AT 2, 0 dta 38, c' +++ WHITE SNAKE IS DEAD +++ ', 0 setFlag _msgFlags cMsgUp_Blink mvza _sfx_tmr ;sound mva #14 _sfx_ptr clc rts .endp ;------------------------------------------------------------ PrintTime .proc #if .byte clckSeconds < #10 PRINT_AT 19 24 dta 129, a(clckMinutes), 2, $27, c'0', 129, a(clckSeconds), 2, c'" ', 0 #else PRINT_AT 19 24 dta 129, a(clckMinutes), 1, $27, 129, a(clckSeconds), 2, c'" ', 0 #end rts .endp ;------------------------------------------------------------ PrintTime2 .proc #if .byte __a < #10 PRINT_AT 19 24 dta 129, a(__b), 2, $27, c'0', 129, a(__a), 2, c'" ', 0 #else PRINT_AT 19 24 dta 129, a(__b), 1, $27, 129, a(__a), 2, c'" ', 0 #end rts .endp ;------------------------------------------------------------ GameLoop0 .proc jsr PrintTime mvza RTCLOCK #while .byte RTCLOCK = #0 m_GetStickState SnW_Dir STICK0 jsr CheckKeysInGame clearFlag SnW_State cSSt_Fast #if .byte STRIG0 = #btn_pressed .or .byte __a = #cTrigger ; if we push the trigger, snake goes faster setFlag SnW_State cSSt_Fast #end m_SetDirection SnW_Dir SnW_tmpDir #end mva Level LevelTmp dec GameCntrFast jne l1 ; fast move checkFlag SnW_State cSSt_Fast jcc l11 jsr MoveSnakeForwardW jcs GameOver inc _tmpState l11 mva #2 GameCntrFast l1 dec GameCntr jne l2 ; slow move checkFlag SnW_State cSSt_Fast jcs l21 jsr MoveSnakeForwardW jcs GameOver inc _tmpState l21 mva LevDelay GameCntr l2 lda _tmpState jeq GameLoop0 jsr CheckLevelAndExtraFruit mvza _tmpState jmp GameLoop0 .endp ;------------------------------------------------------------ GameLoop1 .proc jsr PrintTime mvza RTCLOCK #while .byte RTCLOCK = #0 m_GetStickState SnB_Dir STICK0 jsr CheckKeysInGame clearFlag SnB_State cSSt_Fast #if .byte STRIG0 = #btn_pressed .or .byte __a = #cTrigger ; if we push the trigger, snake goes faster setFlag SnB_State cSSt_Fast #end m_SetDirection SnB_Dir SnB_tmpDir #end mva Level LevelTmp dec GameCntrFast jne l1 ; fast move checkFlag SnB_State cSSt_Fast jcc l11 jsr MoveSnakeForwardB jcs GameOver inc _tmpState l11 mva #2 GameCntrFast l1 dec GameCntr jne l2 ; slow move checkFlag SnB_State cSSt_Fast jcs l21 jsr MoveSnakeForwardB jcs GameOver inc _tmpState l21 mva LevDelay GameCntr l2 lda _tmpState jeq GameLoop1 jsr CheckLevelAndExtraFruit mvza _tmpState jmp GameLoop1 .endp ;------------------------------------------------------------ GameLoop2 .proc mvza RTCLOCK #while .byte RTCLOCK = #0 ; black (joy 1 or keys) m_GetStickState SnB_Dir STICK1 jsr CheckKeysInGame clearFlag SnB_State cSSt_Fast #if .byte STRIG1 = #btn_pressed .or .byte __a = #cTrigger ; if we push the trigger, snake goes faster setFlag SnB_State cSSt_Fast #end m_SetDirection SnB_Dir SnB_tmpDir ; white (joy 0) m_GetStickState SnW_Dir STICK0 clearFlag SnW_State cSSt_Fast #if .byte STRIG0 = #btn_pressed ; if we push the trigger, snake goes faster setFlag SnW_State cSSt_Fast #end m_SetDirection SnW_Dir SnW_tmpDir #end mva Level LevelTmp dec GameCntrFast jne l1 ; fast move checkFlag SnB_State cSSt_Dead jcs l11 checkFlag SnB_State cSSt_Fast jcc l11 jsr MoveSnakeB jcs GameOver inc _tmpState l11 checkFlag SnW_State cSSt_Dead jcs l12 checkFlag SnW_State cSSt_Fast jcc l12 jsr MoveSnakeW jcs GameOver inc _tmpState l12 mva #2 GameCntrFast l1 dec GameCntr jne l2 ; slow move checkFlag SnB_State cSSt_Dead jcs l21 checkFlag SnB_State cSSt_Fast jcs l21 jsr MoveSnakeB jcs GameOver inc _tmpState l21 checkFlag SnW_State cSSt_Dead jcs l22 checkFlag SnW_State cSSt_Fast jcs l22 jsr MoveSnakeW jcs GameOver inc _tmpState l22 mva LevDelay GameCntr l2 lda _tmpState jeq GameLoop2 jsr CheckLevelAndExtraFruit mvza _tmpState jmp GameLoop2 .endp ;------------------------------------------------------------ GameLoop3 .proc mvza RTCLOCK #while .byte RTCLOCK = #0 ; white (joy 1 or keys) m_GetStickState SnW_Dir STICK1 jsr CheckKeysInGame clearFlag SnW_State cSSt_Fast #if .byte STRIG1 = #btn_pressed .or .byte __a = #cTrigger ; if we push the trigger, snake goes faster setFlag SnW_State cSSt_Fast #end m_SetDirection SnW_Dir SnW_tmpDir ; black (joy 0) m_GetStickState SnB_Dir STICK0 clearFlag SnB_State cSSt_Fast #if .byte STRIG0 = #btn_pressed ; if we push the trigger, snake goes faster setFlag SnB_State cSSt_Fast #end m_SetDirection SnB_Dir SnB_tmpDir #end mva Level LevelTmp dec GameCntrFast jne l1 ; fast move checkFlag SnB_State cSSt_Dead jcs l11 checkFlag SnB_State cSSt_Fast jcc l11 jsr MoveSnakeB jcs GameOver inc _tmpState l11 checkFlag SnW_State cSSt_Dead jcs l12 checkFlag SnW_State cSSt_Fast jcc l12 jsr MoveSnakeW jcs GameOver inc _tmpState l12 mva #2 GameCntrFast l1 dec GameCntr jne l2 ; slow move checkFlag SnB_State cSSt_Dead jcs l21 checkFlag SnB_State cSSt_Fast jcs l21 jsr MoveSnakeB jcs GameOver inc _tmpState l21 checkFlag SnW_State cSSt_Dead jcs l22 checkFlag SnW_State cSSt_Fast jcs l22 jsr MoveSnakeW jcs GameOver inc _tmpState l22 mva LevDelay GameCntr l2 lda _tmpState jeq GameLoop3 jsr CheckLevelAndExtraFruit mvza _tmpState jmp GameLoop3 .endp ;------------------------------------------------------------------------- GameProcedure .proc jsr ClearMsg mwa #DList SDLSTL jsr writeTitle getColor #1 _bgrndColorPtr sta PM_COLS0 getColor #2 _bgrndColorPtr sta PM_COLS1 mvza PM_WIDTH mvza PM_WIDTH+1 mva #0 NMIEN mwa #DLI_Proc1 VDSLST mva #192 NMIEN #if .byte _selectedArea = #0 jsr drawArea1 #else #if .byte _selectedArea = #1 jsr drawArea2 #else #if .byte _selectedArea = #2 jsr drawArea3 #else jsr drawArea4 #end #end #end PRINT_AT 0 24 dta 40 \ :40 dta c' ' \ dta 0 mwa #0 SnW_Score mwa #0 SnB_Score mva #1 Level mva #13 LevDelay ;initial speed mva #0 fruitExtraCntr mvza SnW_State mvza SnB_State clearFldW clearFldB mva #cRight SnW_Dir mva #cLeft SnB_Dir #if .byte _selectedMode <> #1 mva #7 __a ; initial length clc jsr DrawSnakeAtRandomPos mva SnW_Dir SnW_tmpDir jsr PrintScoreW #else setFlag SnW_State cSSt_Dead #end #if .byte _selectedMode <> #0 mva #7 __a ; initial length sec jsr DrawSnakeAtRandomPos mva SnB_Dir SnB_tmpDir jsr PrintScoreB #else setFlag SnB_State cSSt_Dead #end ;"LEVEL: [Level]" PRINT_AT 1 24 dta 7, c'LEVEL: ' dta 129, a(Level) dta 0 jsr CheckTrigger.Released ; put the first fruit clc jsr GenerateFruit mvza tmrBase mvza clckSeconds mvza clckMinutes mvza _tmpState mva LevDelay GameCntr mva #2 GameCntrFast #if .byte _selectedMode = #0 ;"TIME: " PRINT_AT 13 24 dta 6, c'TIME: ', 0 jmp GameLoop0 #else #if .byte _selectedMode = #1 ;"TIME: " PRINT_AT 13 24 dta 6, c'TIME: ', 0 jmp GameLoop1 #else #if .byte _selectedMode = #2 jmp GameLoop2 #else jmp GameLoop3 #end #end #end .endp