#include Variables.inc #include Header.inc ;#################### ;# Menu Functions # ;#################### SystemStart: ;System setup ld a,r ld (v_RSeed),a COPY(SMCrom,SMCram,SMCromend-SMCrom) Archive2RAM: FIND(txt_PyoroHS) jr c,CreateAppVar ld a,b or a jr z,SkipUnArchive B_CALL(_Arc_Unarc) FIND(txt_PyoroHS) SkipUnArchive: ld a,(de) cp SaveRamEnd-SaveRam jr nz,InvalidAppVar inc de inc de ld hl,SaveRam ex de,hl ld bc,SaveRamEnd-SaveRam ldir jr FinishArchive2RAM InvalidAppVar: B_CALL(_DelVarNoArc) CreateAppVar: ld hl,SaveRamEnd-SaveRam B_CALL(_CreateAppVar) ZERORAM(SaveRam,SaveRamEnd) FinishArchive2RAM: di ;Grayscale can have NO interrupts! xor a ld (v_Mode),a SplashSetup: ld hl,m_GameStart ld (v_NotePtr),hl call ClearAllBuffers DRAWC(s_Kevin,58,8,5,gbuf1) DRAWC(s_Kevin,58,8,5,gbuf2) DRAWC(s_Title1,4,10,36,gbuf1) DRAWC(s_Title2,4,10,36,gbuf2) DRAWC(s_2ndKey1,45,6,7,gbuf1) DRAWC(s_2ndKey1,45,6,7,gbuf2) DRAWCX(s_2ndKey2,45,6,7,gbuf2) ld a,1 ld (v_FlashTimer),a ld (v_LastKey),a SplashLoop: ld hl,v_FlashTimer dec (hl) jr nz,SplashSkipFlash ld a,c_FlashTimer ld hl,v_Settings bit b_MusicOn,(hl) jr z,SplashNoMusic ld a,c_FlashTimer/3 SplashNoMusic: ld (v_FlashTimer),a DRAWCX(s_2ndKey2,45,6,7,gbuf1) SplashSkipFlash: ld hl,v_Settings bit b_MusicOn,(hl) jr z,SplashNoMusic2 call PlayNote call UpdateScrn call UpdateScrn SplashNoMusic2: call UpdateScrn KEYSKIP(SplashLoop) KEY(k_2nd) jr z,MainMenuSetup KEY(k_Enter) jr z,MainMenuSetup KEY(k_Clear) jp z,SystemExit jr SplashLoop MainMenuSetup: call ClearAllBuffers DRAW(s_Icon1a,6,0,4,28,gbuf1) DRAW(s_Icon1b,6,0,4,28,gbuf2) ld bc,s_IconQ ld hl,s_Icon3b push hl ld hl,s_Icon3a push hl ld a,(v_Settings) bit b_UnlockProj,a call z,DrawLocked ld hl,s_Icon2b push hl ld hl,s_Icon2a push hl bit b_UnlockTng,a call z,DrawLocked pop hl DRAWNOIMG(6,4,4,28,gbuf1) pop hl DRAWNOIMG(6,4,4,28,gbuf2) pop hl DRAWNOIMG(6,8,4,28,gbuf1) pop hl DRAWNOIMG(6,8,4,28,gbuf2) DRAW(s_IconOpt,38,2,4,9,gbuf1) DRAW(s_IconOpt,38,2,4,9,gbuf2) DRAW(s_IconExt,38,6,4,9,gbuf1) DRAW(s_IconExt,38,6,4,9,gbuf2) call UpdateModes ld a,(v_Mode) add a,a add a,a cp 12 jr c,MainMenuBigIcons MainMenuLittleIcons sub 10 ld hl,s_IconL ld b,13 ld de,gbuf1+(36*12) jr MainMenuDrawSelection MainMenuBigIcons: ld hl,s_IconS ld b,32 ld de,gbuf1+(4*12) MainMenuDrawSelection: add a,e ld e,a jr nz,MainMenuNoCarry inc d MainMenuNoCarry: ld c,12-(4) ld a,b call DrawCenteredX ld hl,v_LastKey inc (hl) MainMenuDrawScore: ld ix,s_HighScore LDBC(16,49) call Draw16x16 LDBC(9,53) ld hl,(v_TempHighScore) call DrawScore ld a,1 ld (v_LastKey),a MainMenuLoop: call UpdateScrn KEYSKIP(MainMenuLoop) ld hl,v_Mode KEY(k_Left) jr z,MainMenuLeft KEY(k_Right) jr z,MainMenuRight KEY(k_Up) jr z,MainMenuUp KEY(k_Down) jr z,MainMenuDown KEY(k_Clear) jp z,SystemExit KEY(k_2nd) jr z,MainMenuSelect KEY(k_Enter) jr z,MainMenuSelect MainMenuEndLoop: jr MainMenuLoop MainMenuLeft: ld a,(hl) or a jr z,MainMenuLoop cp 3 jr z,MainMenuLoop dec (hl) HitchToMainMenu: jp MainMenuSetup MainMenuRight: ld a,(hl) cp 2 jr z,MainMenuLoop cp 4 jr z,MainMenuLoop inc (hl) jr HitchToMainMenu MainMenuUp: ld a,(hl) cp 3 jr c,MainMenuEndLoop dec (hl) dec (hl) dec (hl) jr HitchToMainMenu MainMenuDown: ld a,(hl) cp 3 jr nc,MainMenuEndLoop ld (hl),3 jr HitchToMainMenu MainMenuSelect: ld a,(hl) ld hl,v_Settings or a jr z,MainHitchToStart dec a jr z,MainMenuCheckMode2 dec a jr z,MainMenuCheckMode3 dec a jr z,SettingsSetup jr SystemExit MainMenuCheckMode2: bit b_UnlockTng,(hl) jr MainMenuSkpMode3 MainMenuCheckMode3: bit b_UnlockProj,(hl) MainMenuSkpMode3: jr z,MainMenuEndLoop MainHitchToStart: jp MainStart SystemExit: FIND(txt_PyoroHS) ;save high score inc de inc de ld hl,SaveRam ld bc,SaveRamEnd-SaveRam ldir ld a,(v_Settings) bit b_AutoArc,a jr z,SystemDontArchive call ClearAllBuffers DRAWC(s_Saving,29,4,5,gbuf1) DRAWC(s_Saving,29,4,5,gbuf2) call UpdateScrn B_CALL(_Arc_Unarc) SystemDontArchive: ld iy,flags res 5,(iy+0) ;don't display "done" call ClearAllBuffers SETCUR(0,0) ei ;return interrupts B_CALL(_ReloadAppEntry) B_JUMP(_AppEnd) SettingsSetup: xor a ld (v_TempMode),a SettingsBigLoop: call ClearAllBuffers DRAW(s_OptAutoArc,10,2,4,9,gbuf1) DRAW(s_OptAutoArc,10,2,4,9,gbuf2) DRAW(s_OptMusic,25,3,3,4,gbuf1) DRAW(s_OptMusic,25,3,3,4,gbuf2) ld a,(v_Settings) bit b_UnlockPanic,a jr z,SettingsSkipPanic DRAW(s_OptPMode,34,3,3,9,gbuf1) DRAW(s_OptPMode,34,3,3,9,gbuf2) SettingsSkipPanic: ld hl,s_IconOff push hl push hl ld bc,s_IconOn ld a,(v_Settings) add a,a add a,a call c,DrawLocked ld hl,s_IconOff push hl push hl add a,a call c,DrawLocked ld hl,s_IconOff push hl push hl add a,a call c,DrawLocked ld bc,s_IconQmini add a,a add a,a call nc,DrawLocked pop hl DRAWNOIMG(34,6,4,9,gbuf1) pop hl DRAWNOIMG(34,6,4,9,gbuf2) pop hl DRAWNOIMG(22,6,4,9,gbuf1) pop hl DRAWNOIMG(22,6,4,9,gbuf2) pop hl DRAWNOIMG(10,6,4,9,gbuf1) pop hl DRAWNOIMG(10,6,4,9,gbuf2) DRAW(s_IconExt,51,4,4,9,gbuf1) DRAW(s_IconExt,51,4,4,9,gbuf2) ld hl,v_LastKey inc (hl) ld a,(v_TempMode) or a jr z,SettingsSelAutoArc dec a jr z,SettingsSelMusic dec a jr z,SettingsSelPanic DRAW(s_IconL,49,4,4,13,gbuf1) jr SettingsLoop SettingsSelAutoArc: DRAW(s_IconL,8,6,4,13,gbuf1) jr SettingsLoop SettingsSelMusic: DRAW(s_IconL,20,6,4,13,gbuf1) jr SettingsLoop SettingsSelPanic: DRAW(s_IconL,32,6,4,13,gbuf1) SettingsLoop: call UpdateScrn KEYSKIP(SettingsLoop) ld hl,v_TempMode KEY(k_Clear) jp z,MainMenuSetup KEY(k_2nd) jr z,SettingsSelect KEY(k_Enter) jr z,SettingsSelect KEY(k_Up) jr z,SettingsUp KEY(k_Down) jr z,SettingsDown HitchToSettingsLoop: jr SettingsLoop SettingsSelect: ld a,(hl) ld hl,v_Settings or a jr z,SettingsAutoArc dec a jr z,SettingsMusic dec a jr z,SettingsPanic jp MainMenuSetup SettingsAutoArc: ld a,%01000000 xor (hl) ld (hl),a jr HitchToBigLoop SettingsMusic: ld a,%00100000 xor (hl) ld (hl),a jr HitchToBigLoop SettingsPanic: bit b_UnlockPanic,(hl) jr z,SettingsLoop ld a,%00010000 xor (hl) ld (hl),a HitchToBigLoop: jp SettingsBigLoop SettingsUp: ld a,(hl) or a jr z,SettingsLoop dec (hl) jr HitchToBigLoop SettingsDown: ld a,(hl) cp 3 jr z,HitchToSettingsLoop inc (hl) jr HitchToBigLoop HighScoreMenu: call CheckHighScore call ClearScrn ;Clear Buffers call UpdateScrn ;Draw the cleared buffers call CheckUnlock ld ix,s_ScoreR LDBC(24,24) call Draw8x8 ld ix,s_ScoreL LDBC(16,24) call Draw8x8 LDBC(9,22) ld hl,(v_Score) call DrawScore ld a,(v_PyoroX) or a jr z,HighScoreSkipInit DRAWC(s_GotHS1,13,10,7,gbuf1) DRAWC(s_GotHS1,13,10,7,gbuf2) DRAWCX(s_GotHS2,13,10,7,gbuf2) HighScoreSkipInit: ld a,1 ld (v_FlashTimer),a ld (v_LastKey),a HighScoreLoop: ld a,(v_PyoroX) or a jr z,HighScoreSkipFlash ld hl,v_FlashTimer dec (hl) jr nz,HighScoreSkipFlash ld a,c_FlashTimer ld (hl),a DRAWCX(s_GotHS2,13,10,7,gbuf1) HighScoreSkipFlash: call UpdateScrn KEYSKIP(HighScoreLoop) call CheckAllKeys jr z,HighScoreLoop jp MainMenuSetup ClearAllBuffers: ZERORAM(gbuf1,gbuf1+768) ZERORAM(gbuf2,gbuf2+768) ZERORAM(gbuf3,gbuf3+768) ret UpdateModes: ld a,(v_Mode) or a jr z,MainMode1 dec a jr z,MainMode2 MainMode3: ld hl,(v_HighScore3) ld (v_TempHighScore),hl ld a,c_InitDropFreq3 ld hl,d_IncBgnd3 jr FinishMainModes MainMode2: ld hl,(v_HighScore2) ld (v_TempHighScore),hl ld a,c_InitDropFreq2 ld hl,d_IncBgnd2 jr FinishMainModes MainMode1: ld hl,(v_HighScore1) ld (v_TempHighScore),hl ld a,c_InitDropFreq1 ld hl,d_IncBgnd1 FinishMainModes: ld (v_DropFreq),a ld (v_IncBgndPtr),hl ret DrawLocked: pop de pop hl pop hl ld h,b ld l,c push hl push hl push de ret ;#################### ;# Main Functions # ;#################### MainStart: ZERORAM(TempRAM,TempRAMEnd) ld hl,v_Settings bit b_PanicMode,(hl) jr z,NoPanic ld hl,v_DropFreq sla (hl) sla (hl) sla (hl) ld a,3 ld (v_MaxSpeed),a ld a,(v_Mode) dec a jr nz,NoPanic ld a,2 ld (v_MaxSpeed),a NoPanic: call SetupBack ld hl,m_Background ld (v_NotePtr),hl ld (v_LoopPtr),hl LDBC(c_StartX,52-c_GndHeight) ld (v_PyoroXY),bc ld a,1 ld (v_LastKey),a ;a is nonzero call NewFruitForSure LoopMain: call ClearScrn ;Clear the buffers call ReDrawScreen call UpdateScrn call StepQueue ld hl,v_Settings bit b_MusicOn,(hl) call nz,PlayNote call RestoreMain call NewFruit call UpdateScrn call StepProj call StepJump KEYSKIP(ResetPyoro) ld a,(v_HasDied) or a jp nz,DeathAction ;different keys if dead KEY(k_Clear) jp z,HighScoreMenu KEY(k_Enter) call z,PauseGame KEY(k_Left) call z,LeftKey KEY(k_Right) call z,RightKey KEY(k_2nd) call z,SpitKey call StepTng ResetPyoro: xor a ld (v_SpitLast),a ResetPyoroSprite: ld hl,v_PyoroSprite ld a,(hl) and %00000001 ld (hl),a call MakePyoroOpen jp LoopMain ;######################## ;# Gameplay Functions # ;######################## MakePyoroOpen: ld a,(v_PyoroY) cp 52-c_GndHeight ret z ld a,(v_HasDied) or a ret nz ld hl,v_PyoroSprite ld a,(hl) and %00000001 or e_PyoroLOpen ld (hl),a ret LeftKey: ld a,(v_TngSize) or a ret nz ld hl,v_PyoroSprite ld a,(hl) cp e_PyoroL jr z,LeftAnimate xor a jp LeftMove LeftAnimate: ld a,e_PyoroLWalk LeftMove: ld (hl),a ld a,(v_PyoroX) or a jr z,RightLeftEnd ld d,a ld a,(v_Mode) cp 2 ld hl,LeftMoveEnd push hl jp z,ProjCheckFall pop hl call NearestBlock ld a,(hl) or a jr nz,RightLeftEnd LeftMoveEnd: ld hl,v_PyoroX dec (hl) dec (hl) jp RightLeftEnd RightKey: ld a,(v_TngSize) or a ret nz ld hl,v_PyoroSprite ld a,(hl) cp e_PyoroR jr z,RightAnimate ld a,e_PyoroR jp RightMove RightAnimate: ld a,e_PyoroRWalk RightMove: ld (hl),a ld a,(v_PyoroX) cp 84 jr z,RightLeftEnd add a,6 ld d,a ld a,(v_Mode) cp 2 ld hl,RightMoveEnd push hl jp z,ProjCheckFall pop hl call NearestBlock ld a,(hl) or a jr nz,RightLeftEnd RightMoveEnd: ld hl,v_PyoroX inc (hl) inc (hl) RightLeftEnd: ld a,(v_Mode) cp 2 jr nz,HitchToMainLoop ld a,(v_SpitLast) or a jr nz,HitchToMainLoop KEY(k_2nd) jr z,SpitProj HitchToMainLoop: pop af HitchToMainLoop2: jp LoopMain SpitKey: ld a,(v_Mode) dec a jr z,SpitTng dec a jr z,SpitProj SpitSeed: pop af ld hl,v_SpitLast ld a,(hl) cp c_SpitTime jp z,ResetPyoroSprite inc (hl) or a jr nz,HitchToMainLoop2 ld hl,v_PyoroSprite ld a,(hl) and %00000001 or e_PyoroLSpit ld (hl),a call NewSeed call QueueLineDetect jp LoopMain SpitProj: ld hl,v_ProjFire ld a,(hl) or a jr nz,HitchToMainLoop inc (hl) ld bc,(v_PyoroXY) inc b inc b ld a,c add a,8 ld c,a ld (v_ProjXY),bc ld a,(v_PyoroSprite) and %00000001 add a,a add a,a add a,a sub 4 ld b,a ld c,-c_ProjDY ld (v_ProjDXDY),bc xor a ld (v_FruitInARow),a call StepProj ld a,(v_PyoroY) cp 52-c_GndHeight jr c,HitchToMainLoop ld a,-4 ld (v_PyoroDY),a call MakePyoroOpen jp HitchToMainLoop SpitTng: ld hl,v_TngData bit 1,(hl) ret nz set 0,(hl) inc hl ;now on TngSize inc (hl) ld hl,v_PyoroSprite ld a,(hl) and %00000001 or e_PyoroLOpen ld (hl),a jp TngDetect ProjCheckFall: call MakePyoroOpen ld a,(v_PyoroX) ld b,a ld d,a call NearestBlock push de ld d,b inc d inc d call NearestBlock pop af cp d ret nz ld a,(hl) or a ret z ld hl,v_PyoroY ld a,(hl) cp 52-c_GndHeight ret nz inc (hl) ret Rand: ;Returns random number 0-255 ld a,(v_RSeed) ;Output: a ld e,a ;Destroys: e add a,a add a,a add a,e inc a ld (v_RSeed),a ld a,r add a,e ret NearestBlock: ;Input: d X value ld e,15 ;Output: hl pointer to nearest block FindBlockLoop: ; de block number ld a,e ; a block number times 6 add a,a add a,a add a,e add a,e sub 4 cp d jr c,FoundBlock dec e jr nz,FindBlockLoop FoundBlock: ld hl,v_Blocks ld d,0 add hl,de ret DeathAction: ld a,(v_PyoroY) cp c_PyoroFall jr nc,DeathKeys jp LoopMain DeathKeys: call CheckAllKeys jp nz,HighScoreMenu jp LoopMain PauseGame: call ClearScrn ;Clear Buffers call UpdateScrn ;Draw the cleared buffers ld ix,s_ScoreR LDBC(24,32) call Draw8x8 ld ix,s_ScoreL LDBC(16,32) call Draw8x8 LDBC(9,30) ld hl,(v_Score) call DrawScore DRAWC(s_Paused1,20,4,7,gbuf1) DRAWC(s_Paused1,20,4,7,gbuf2) DRAWCX(s_Paused2,20,4,7,gbuf2) ld a,1 ld (v_FlashTimer),a ld (v_LastKey),a PauseGameLoop: ld hl,v_FlashTimer dec (hl) jr nz,PauseGameSkipFlash ld a,c_FlashTimer ld (hl),a DRAWCX(s_Paused2,20,4,7,gbuf1) PauseGameSkipFlash: call UpdateScrn KEYSKIP(PauseGameLoop) call CheckAllKeys jr z,PauseGameLoop ld (v_LastKey),a ;a is nonzero here ret CheckAllKeys: ;Output: z = no keys pressed ld b,7 ; nz = some key is pressed ld c,%11111110 CheckAllKeysLoop: ld a,c out (1),a rlc c in a,(1) inc a ret nz ;returns with z reset djnz CheckAllKeysLoop xor a ret ;returns with z set CheckHighScore: xor a ld (v_PyoroX),a ld hl,(v_Score) ld de,(v_TempHighScore) ld a,h cp d ret c jr nz,BestScore ld a,e cp l ret nc BestScore: ld hl,v_PyoroX inc (hl) ld hl,v_Score ld de,v_HighScore1 ld a,(v_Mode) or a jr z,CheckHSMode1 dec a jr z,CheckHSMode2 CheckHSMode3: inc de inc de CheckHSMode2: inc de inc de CheckHSMode1: ldi ldi ret CheckUnlock: ld de,(v_Score) ;30,000 -> #3000 -> $0BB8 ld a,d cp $0B ret c jr nz,CheckUnlockOkay ld a,e cp $B8 ret c CheckUnlockOkay: ld hl,v_Settings ld a,(v_Mode) dec a jr z,CheckUnlock2 dec a jr z,CheckUnlock3 CheckUnlock1: bit b_UnlockTng,(hl) ret nz inc (hl) jr ActualUnlock CheckUnlock2: bit b_UnlockProj,(hl) ret nz set b_UnlockProj,(hl) jr ActualUnlock CheckUnlock3: bit b_UnlockPanic,(hl) ret nz set b_UnlockPanic,(hl) ActualUnlock: DRAWC(s_Unlocked3,32,4,31,gbuf1) DRAWC(s_Unlocked2,32,4,31,gbuf2) DRAWCX(s_Unlocked1,33,4,29,gbuf1) ret CheckIncBgnd: ld hl,(v_IncBgndPtr) ld e,(hl) inc hl ld d,(hl) ld hl,(v_Score) ld a,h cp d ret c jr nz,IncBgndNext ld a,l cp e ret c IncBgndNext: ld hl,(v_IncBgndPtr) inc hl inc hl ld e,(hl) inc hl ld d,(hl) inc hl ld (v_IncBgndPtr),hl push de pop ix ld a,e or d jr z,NightTime jp DrawOnToBack NightTime: ld hl,gbuf3 ld c,12 NightTimeLoop1: ld b,64 NightTimeLoop2: ld a,(hl) cpl ld (hl),a inc hl djnz NightTimeLoop2 dec c jr nz,NightTimeLoop1 ret StepTng: ld a,(v_TngSize) or a ret z pop hl ld hl,LoopMain push hl ld hl,v_TngData bit 0,(hl) res 0,(hl) ret nz set 1,(hl) inc hl ;now on tounge size dec (hl) jr z,DoneWithTng dec (hl) ret nz DoneWithTng: dec hl ;now on tounge data ld (hl),0 ret StepProj: ld a,(v_ProjDX) or a ret z call ProjDetect ld bc,(v_ProjXY) ld de,(v_ProjDXDY) ld a,b add a,d ld b,a ld a,c add a,e ld c,a inc e ld (v_ProjXY),bc ld a,88 cp b jr nc,StepProjSkipHitWall xor a ld d,a ld e,a StepProjSkipHitWall: ld (v_ProjDXDY),de ret StepJump: ld hl,v_PyoroDY ld a,(v_PyoroY) cp c_PyoroFall ret nc cp 52-c_GndHeight jr nz,StepJumpDo ld b,a ld a,(v_HasDied) or a jr nz,StepJumpBackup bit 7,(hl) ret z StepJumpBackup: ld a,b StepJumpDo: add a,(hl) ld (v_PyoroY),a inc (hl) call ProjCheckFall ld a,(v_PyoroY) cp 52-c_GndHeight ret c jr nz,NotLandOnGnd xor a ld (v_ProjFire),a ret NotLandOnGnd: ld (v_HasDied),a ret RestoreMain: ld hl,v_NewBlocks ld a,(hl) or a ret z cp 16 call nc,PopAllFruit call AddQueue ;now on X push hl ld de,(v_PyoroX-1) ;Loads 'd' with (v_PyoroX) call NearestBlock pop hl ld ix,v_Blocks ld c,e ;e = blocks left ld a,e ;c = blocks right ld (smc_LeftOffset),a jp RestoreSingle ;##################### ;# Queue Functions # ;##################### StepQueue: ld hl,v_QueueSize ;Now on QueueSize ld a,(hl) or a ret z ld b,a inc hl ;Now on EXP/X StepQueueLoop: ld d,(hl) ;d saves X bit 7,(hl) inc hl ;Now on INDEX/SPEED ld c,(hl) ;c saves speed/index jp nz,StepQueueExp inc hl ;Now on SPTTMR/SPDTMR ld a,c cp e_Block|c_BSpeed call nz,CheckDeath bit 3,c jr z,SetFallTimerFast ld a,(hl) and %00001111 jr z,SetFallTimer dec (hl) FallTimerReturn: ld a,(hl) add a,%00100000 ld (hl),a and %11110000 jr z,SetSpriteTimer SpriteTimerReturn: inc hl ;Now on Y inc hl ;Now on Next StepQueueLoopEnd: djnz StepQueueLoop ret SetFallTimerFast: ld a,c and %00000111 inc hl ;Now on Y add a,(hl) inc a ld (hl),a jp SetFallTimerFinish SetFallTimer: ld a,c and %00000111 add a,(hl) ld (hl),a inc hl ;Now on Y inc (hl) ld a,(hl) SetFallTimerFinish: dec hl ;Now on SPTTMR/SPDTMR cp -8 jr nc,FallTimerReturn cp 64 jr nc,DeleteQueue cp 56-c_GndHeight jr c,FallTimerReturn push hl call NearestBlock ld a,c cp e_Block|c_BSpeed jr z,FillInMissing inc d ;d was zero here from "call NearestBlock" FillInMissing: ld a,(hl) ld (hl),d pop hl or a jr nz,FallTimerReturn inc hl ;Now on Y inc (hl) inc (hl) ChangeIntoExp: dec hl ;Now on SPTTMR/SPDTMR dec hl ;Now on INDEX/SPEED dec hl ;Now on Exp/X set 7,(hl) inc hl ;Now on INDEX/SPEED ld (hl),e_Poof3 inc hl ;Now on SPTTMR/SPDTMR ld (hl),4 jp SpriteTimerReturn SetSpriteTimer: ld a,c ;c has speed/index already and %00110000 ld a,c jr nz,SpriteTimerOk add a,%01000000 SpriteTimerOk: sub %00010000 dec hl ;Now on INDEX/SPEED ld (hl),a inc hl ;Now on SPTTMR/SPDTMR jp SpriteTimerReturn DeleteQueue: dec hl ;hl+2 is the index to delete dec hl ld a,(v_QueueSize) dec a ld (v_QueueSize),a ret z add a,a add a,a ld de,v_Queue add a,e ld e,a jr nc,NoIncD inc d NoIncD: push hl push bc ex de,hl ldi ldi ldi ldi pop bc pop hl jp StepQueueLoopEnd StepQueueExp: ld a,c cp e_Poof3+16 jr nc,SkipExpAnimate sub %00010000 ld (hl),a jp m,ChangeToPoints SkipExpAnimate: inc hl ;Now on SPTTMR/SPDTMR dec (hl) jr z,DeleteQueue jp SpriteTimerReturn ChangeToPoints: add a,a add a,a add a,a add a,a ;move bottom 4 bits to top 4 ld (hl),a jp SkipExpAnimate NewFruit: ld bc,(v_DropFreq-1) ;This loads 'b' with (v_DropFreq) call Rand cp b ret nc NewFruitForSure: call AddQueue AddQueueRandomize: call Rand and %01111111 ;number is 0-127 cp 88 ;only numbers 0-87 are valid jr nc,AddQueueRandomize ld (hl),a inc hl ;Now on INDEX/SPEED call Rand ld b,0 cp c_PofWhite jr nc,MakeBlack cp c_PofFlash jr nc,MakeWhite MakeFlash: inc b MakeWhite: inc b MakeBlack: call Rand and %00001011 ;sets speed limits cp %00000100 ;nc set if slow jr nc,MakeFruitLoop ld d,a ld c,d ld a,(v_MaxSpeed) inc c cp c ;c set if faster than max speed ld a,d jr nc,MakeFruitLoop and %00001000 MakeFruitLoop: add a,%01000000 djnz MakeFruitLoop ld (hl),a inc hl ld (hl),0 inc hl ld (hl),c_FallHeight ret NewSeed: ld hl,v_PyoroX and %00000001 jr nz,RightSeed LeftSeed: ld a,8 cp (hl) ret nc ld b,e_SeedL ld c,-8 jp AddNewSeed RightSeed: ld a,76 cp (hl) ret c ld b,e_SeedR ld c,12 AddNewSeed: call AddQueue ld a,(v_PyoroX) add a,c or %10000000 ld (hl),a inc hl ld (hl),b inc hl ld (hl),1 inc hl ld (hl),46-c_GndHeight ret AddQueue: ld hl,v_QueueSize ;Now on QueueSize ld a,(hl) cp c_MaxQueue pop de ret z ;Queue is full, return outside subroutine push de inc (hl) add a,a add a,a ld e,a ld d,0 inc hl add hl,de ;Now on EXP/X ret QueueLineDetect: xor a ld (v_FruitInARow),a ld hl,v_QueueSize ;Now on QueueSize ld b,(hl) ;garenteed to be at least 1 obj in queue (the spit seed) LineDetectLoop: inc hl ;Now on EXP/X ld c,(hl) ;save X in c inc hl ;Now on Speed/Index ld a,(hl) ;save INDEX in a inc hl ;Now on Timers inc hl ;Now on Y bit 7,c jr nz,SkipDetect cp e_Block|c_BSpeed jr z,SkipDetect ld d,(hl) ;save Y in d ld a,(v_PyoroX) sub c ld c,a ;c now holds (Px - X) ld a,(v_PyoroSprite) bit 0,a ld a,c jr nz,LineRight LineLeft: cpl sub 3 LineRight: add a,60-c_GndHeight ;a holds Py +- (Px - X) ld e,9 ;loop 8 times OnLineLoop: cp d jr z,ChangeIntoPoints inc d dec e jr nz,OnLineLoop SkipDetect: djnz LineDetectLoop PutInScores: ld a,(v_FruitInARow) or a ret z ld b,a SnatchPutInScores: MIN_A(4) UpdateScore: ld c,a ld hl,(v_Score) ld de,5 ;(50*1)/10 = +5 Total: 50 add hl,de dec c jr z,ScoreDone ld e,15 ;(100*2)/10 (-5) = +15 Total: 200 add hl,de dec c jr z,ScoreDone ld e,75 ;(300*3)/10 (-15) = +75 Total: 900 add hl,de dec c jr z,ScoreDone ld de,325 ;(1000*4)/10 (-75) = +325 Total: 4000 add hl,de ScoreDone: add a,(e_50>>4)-1 ld c,a call ProcessScore PutInScoreLoop: pop hl ld a,c or (hl) ld (hl),a djnz PutInScoreLoop call CheckIncBgnd ret ProcessScore: ;does not destroy bc ld (v_Score),hl ld de,(v_IncScore) ld a,h cp d ret c jr nz,IncIncScore ld a,l cp e ret c IncIncScore: ld hl,c_LevUpPoints/10 add hl,de ld (v_IncScore),hl ld a,l and %00001111 ;multiple of 80 incs speed (every 6000) jr nz,SkipIncSpeed ld hl,v_MaxSpeed inc (hl) ld a,(v_Mode) dec a jr nz,SkipIncSpeed MIN_HL(2) SkipIncSpeed: ld hl,v_DropFreq inc (hl) ret nz dec (hl) ret ChangeIntoPoints: ;Starts at Y ld ix,v_FruitInARow inc (ix+0) dec hl ;Now on SPTTMR/SPDTMR dec hl ;Now on INDEX/SPEED push hl ;Pushes an extra hl so we can add in points push hl ld a,(hl) and %11000000 ld hl,v_NewBlocks cp e_Fruit2L jr nz,NotFruit2 inc (hl) NotFruit2: cp e_Fruit3L jr nz,NotFruit3 ld (hl),16 NotFruit3: pop hl dec hl ;Now on Exp/X set 7,(hl) inc hl ;Now on INDEX/SPEED ld (hl),e_Poof3 inc hl ;Now on SPTTMR/SPDTMR ld (hl),c_ScoreTimer inc hl ;Now on Y ld a,(v_Mode) or a jp z,SkipDetect ld a,(v_ProjGotFruit) inc a ld (v_ProjGotFruit),a jp SkipProjDetect CheckDeath: ;Starts on SPTTMR/SPDTMR ld a,(v_HasDied) or a ret nz inc hl ;Now on Y ld a,(hl) dec hl ;Now on SPTTMR/SPDTMR ld e,a ld a,(v_PyoroY) add a,2 sub e ret c sub 6 ret nc ld a,(v_PyoroX) sub d cp 8-c_KillRoom jr c,Death cpl cp 12-c_KillRoom-1 ret nc Death: ld a,(v_PyoroSprite) and %00000001 or e_PyoroLDie ld (v_PyoroSprite),a ld a,-2 ld (v_PyoroDY),a ld (v_HasDied),a xor a ld (v_TngSize),a ld de,m_Die ld (v_NotePtr),de ret PopAllFruit: ld de,(v_Score) ld (hl),15 ld hl,v_QueueSize ;Now on QueueSize ld b,(hl) ;garenteed to be at least 1 obj in queue (Fruit3) PopAllFruitLoop: inc hl ;Now on new X ld a,(hl) ;save X in a inc hl ;now on Index/Speed bit 7,a jr nz,PopAllFruitSkip ld a,(hl) cp e_Block|c_BSpeed jr z,PopAllFruitSkip call PopAllExp dec hl ;Now on INDEX/SPEED PopAllFruitSkip: inc hl ;Now on Timers inc hl ;Now on Y djnz PopAllFruitLoop ld (v_Score),de ret PopAllExp: inc de inc de inc de inc de inc de dec hl ;Now on Exp/X set 7,(hl) inc hl ;Now on INDEX/SPEED ld (hl),e_Poof3|(e_50>>4) inc hl ;Now on SPTTMR/SPDTMR ld (hl),c_ScoreTimer/2 ret ;ends at SPTTMR/SPDTMR TngDetect: ld hl,v_TngSize ld a,(hl) dec hl cp c_MaxTngSize jr nz,TngIsOkay res 0,(hl) TngIsOkay: add a,a add a,a ld b,a cpl add a,c_TngYOffset+1 ld d,a ld a,(v_PyoroSprite) bit 0,a ld a,(v_PyoroX) jr z,TngDetectLeft TngDetectRight: add a,b cp 88 jr c,TngDetectChkFruit res 0,(hl) jp TngDetectChkFruit TngDetectLeft: add a,4 sub b jr nc,TngDetectSkipLeft res 0,(hl) TngDetectSkipLeft: sub 4 TngDetectChkFruit: add a,10 ld e,a ;ed = Tounge(X,Y) ca = Fruit(X,Y) ld hl,v_QueueSize ;Now on QueueSize ld a,(hl) or a ret z ld b,a TngDetectLoop: inc hl ;Now on EXP/X ld c,(hl) ;save X in c inc hl ;Now on Speed/Index ld a,(hl) ;save INDEX in a inc hl ;Now on Timers inc hl ;Now on Y bit 7,c jr nz,SkipTngDetect cp e_Block|c_BSpeed jr z,SkipTngDetect ld a,(hl) ;save Y in a OnTngY: add a,13 cp d jr c,SkipTngDetect sub 10 cp d jr nc,SkipTngDetect OnTngX: ld a,c add a,10 cp e jr c,SkipTngDetect sub 10 cp e jr c,TngIntoPoints SkipTngDetect: djnz TngDetectLoop ret TngIntoPoints: ;Starts at Y ld d,(hl) dec hl ;Now on SPTTMR/SPDTMR dec hl ;Now on INDEX/SPEED push hl ld a,(hl) and %11000000 ld hl,v_NewBlocks cp e_Fruit2L jr nz,TngNotFruit2 inc (hl) ld hl,v_TngData set 3,(hl) TngNotFruit2: cp e_Fruit3L jr nz,TngNotFruit3 ld (hl),16 TngNotFruit3: ld a,d add a,8 ld e,e_10>>4 ld hl,(v_Score) TngScore: inc hl ;+10 =10 cp c_Height1+8 jr nc,TngScoreDone inc e ld bc,4 ;10+40 =50 add hl,bc cp c_Height2+8 jr nc,TngScoreDone inc e inc c ;50+50 =100 add hl,bc cp c_Height3+8 jr nc,TngScoreDone inc e ld c,20 ;100+200=300 add hl,bc cp c_Height4+8 jr nc,TngScoreDone inc e ld c,70 ;300+700=1000 add hl,bc TngScoreDone: ld a,e add a,a add a,a add a,a add a,a push af call ProcessScore call CheckIncBgnd pop af pop hl dec hl ;Now on Exp/X set 7,(hl) inc hl ;Now on INDEX/SPEED ld (hl),a inc hl ;Now on SPTTMR/SPDTMR ld (hl),c_ScoreTimer ld hl,v_TngData res 0,(hl) set 2,(hl) inc hl set 0,(hl) ;Make sure odd number tounge length ret ProjDetect: xor a ld (v_ProjGotFruit),a ld de,(v_ProjXY) ld a,8 add a,d ld d,a ld a,8 add a,e ld e,a ProjChkFruit: ;de = Proj(X,Y) ca = Fruit(X,Y) ld hl,v_QueueSize ;Now on QueueSize ld a,(hl) or a ret z ld b,a ProjDetectLoop: inc hl ;Now on EXP/X ld c,(hl) ;save X in c inc hl ;Now on Speed/Index ld a,(hl) ;save INDEX in a inc hl ;Now on Timers inc hl ;Now on Y bit 7,c jr nz,SkipProjDetect cp e_Block|c_BSpeed jr z,SkipProjDetect ld a,(hl) ;save Y in a OnProjY: add a,12 cp e jr c,SkipProjDetect sub 10 cp e jr nc,SkipProjDetect OnProjX: ld a,c add a,12 cp d jr c,SkipProjDetect sub 10 cp d jp c,ChangeIntoPoints SkipProjDetect: djnz ProjDetectLoop ld a,(v_ProjGotFruit) or a ret z ld b,a PutInProjLoop: ld a,(v_FruitInARow) MIN_A(4) ld c,a ld hl,(v_Score) ld de,5 ;(50)/10 = +5 Total: 50 add hl,de dec c jr z,ProjScoreDone add hl,de ;(100)/10 (-5) = +5 Total: 100 dec c jr z,ProjScoreDone ld e,20 ;(300)/10 (-10) = +20 Total: 300 add hl,de dec c jr z,ProjScoreDone ld e,70 ;(1000)/10 (-30) = +70 Total: 1000 add hl,de ProjScoreDone: add a,(e_50>>4)-1 ld c,a call ProcessScore pop hl ld a,c or (hl) ld (hl),a djnz PutInProjLoop jp CheckIncBgnd ;######################## ;# Graphics Functions # ;######################## ReDrawScreen: DrawGameOver: ld a,(v_PyoroY) cp c_PyoroGmOvr jp c,DrawBlocks DRAWC(s_GameOver,30,6,5,gbuf1) DRAWC(s_GameOver,30,6,5,gbuf2) DrawBlocks: ld hl,v_Blocks LDBC(0,64-c_GndHeight) DrawBlocksLoop: ld a,(hl) or a push hl push bc ld ix,s_Block call z,Draw8x8 pop bc pop hl ld a,b add a,6 ld b,a inc hl cp 90 jr nz,DrawBlocksLoop DrawBlocksEnd: ld a,(hl) or a ld ix,s_BlockEnd jp nz,DrawTng call Draw8x8 DrawTng: ld a,(v_TngSize) or a jp z,DrawProj ld bc,(v_PyoroXY) inc b ld hl,v_PyoroSprite bit 0,(hl) jr z,DrawTngLLoop inc b inc b inc b DrawTngRLoop: push af dec a ld ix,s_TngU_R call z,TngCheckHasFruit push bc call Draw8x8 pop bc ld a,b add a,8 ld b,a pop af dec a jp z,DrawProj DrawTngRContinue: push af dec a ld ix,s_TngD_R push bc call Draw8x8 pop bc ld a,c add a,-8 ld c,a pop af dec a jp nz,DrawTngRLoop jp DrawProj DrawTngLLoop: push af dec a ld ix,s_TngU_L call z,TngCheckHasFruit push bc call Draw8x8 pop bc ld a,b add a,-8 ld b,a pop af dec a jp z,DrawProj DrawTngLContinue: push af dec a ld ix,s_TngD_L ld a,b add a,4 jr nc,SkipTngClip ld ix,s_TngD_LClip ld b,a SkipTngClip: push bc call Draw8x8 pop bc ld a,c add a,-8 ld c,a pop af dec a jp nz,DrawTngLLoop DrawProj: ld a,(v_ProjDX) or a jp z,DrawPyoro ld bc,(v_ProjXY) ld ix,s_Proj call Draw8x8 DrawPyoro: ld ix,PyoroSpriteStart ld a,(v_PyoroSprite) add a,a add a,a add a,a add a,a ;a*16 ld h,0 ld l,a add hl,hl add hl,hl ;a*64 ex de,hl add ix,de ld bc,(v_PyoroXY) call Draw16x16 DrawQueue: ld hl,v_QueueSize ld a,(hl) or a ret z ld b,a inc hl DrawQueueLoop: push bc ld ix,SpriteStart ld b,(hl) bit 7,b jr z,RegularSprite ld ix,PointSpriteStart RegularSprite: inc hl ld a,(hl) and %11110000 inc hl bit 7,b jr nz,NotFlashing cp e_Block jr z,BlockFalling cp e_Fruit3L jr c,NotFlashing sub 64 ;go to previous sprite set bit 7,(hl) jr z,NotFlashing BlockFalling: sub 64 ;go to previous sprite set NotFlashing: inc hl ld c,(hl) inc hl push hl res 7,b ;clear out the EXP bit so its just the X ld d,0 ld e,a ld a,b cp 90 ;If this is the last block, draw the corner block. jr nz,NotEdgeBlock ld a,e add a,%00010000 ld e,a NotEdgeBlock: add ix,de call Draw8x8 pop hl pop bc djnz DrawQueueLoop ret TngCheckHasFruit: ld hl,v_TngData bit 2,(hl) ret z ld ix,s_Fruit1M bit 3,(hl) ret z ld ix,s_Fruit2M ret DrawCentered: ;de is (gbuf1 + Y*12 + shift/2) ex af,af' ld a,c ;hl is sprite cpl ;c is shift add a,13 ld b,a DrawCenteredLoop: ld a,(de) or (hl) ld (de),a inc hl inc de djnz DrawCenteredLoop ex af,af' dec a ret z ex de,hl add hl,bc ex de,hl jp DrawCentered DrawCenteredX: ;de is (gbuf1 + Y*12 + shift/2) ex af,af' ld a,c ;hl is sprite cpl ;c is shift add a,13 ld b,a DrawCenteredLoopX: ld a,(de) xor (hl) ld (de),a inc hl inc de djnz DrawCenteredLoopX ex af,af' dec a ret z ex de,hl add hl,bc ex de,hl jp DrawCenteredX SetupBack: ld c,12 ld hl,gbuf3 ld ix,s_BackDrop SetupBackLoop1: ld b,40 SetupBackLoop2: ld (hl),%00000000 inc hl djnz SetupBackLoop2 ld b,19 ld de,12 SetupBackLoop3: ld a,(ix+0) ld (hl),a add ix,de inc hl djnz SetupBackLoop3 ld b,5 SetupBackLoop4: ld (hl),%11111111 inc hl djnz SetupBackLoop4 ld de,-(12*19)+1 add ix,de dec c jr nz,SetupBackLoop1 ret DrawOntoBack: ld d,0 ;Input: ix = SpriteIndex(16*x,y,h,data) ld h,d ld l,(ix+0) add hl,hl ;hl = 32*x add hl,hl ;hl = 64*x inc ix ld e,(ix+0) add hl,de ;hl = 64*x + y ld de,gbuf3 add hl,de ;hl = gbuf + 64*x + y inc ix ld b,(ix+0) ld c,b res 7,b DrawOntoBackLoop: inc ix ld a,(ix+0) xor (hl) ld (hl),a inc hl djnz DrawOntoBackLoop bit 7,c ret z inc ix jp DrawOntoBack Draw16x16: push ix ;preserve ix in case of clipping push bc ;Same input as 8x8 call Draw8x8 ;Drawn clockwise strating at upper left pop bc pop ix ld de,16 add ix,de ld a,b add a,8 ld b,a push ix ;preserve ix in case of clipping push bc call Draw8x8 pop bc pop ix ld de,16 add ix,de ld a,c add a,8 ld c,a push ix push bc call Draw8x8 pop bc pop ix ld de,16 add ix,de ld a,b sub 8 ld b,a jp Draw8x8 ;"jp xxxx" replaces unconditional "call xxxx \ ret" DrawScore: ;Input: b = X (bytes)(right side) xor a ;Input: c = Y jr DrawFirstZero ;Input: hl = number to draw DivHLby10: xor a ld d,16 DivLoop: add hl,hl rla jr c,DivOverFlow cp 10 jr c,DivSkip DivOverFlow: sub 10 inc l DivSkip: dec d jr nz,DivLoop DrawFirstZero: ld e,a push bc push hl call DrawDigit pop hl pop bc dec b ld a,h or l jr nz,DivHLby10 ret DrawDigit: ld d,0 ;Input: b = Sprite X Position (bytes) sla e ;Input: c = Sprite Y Position sla e ;Input: e = Digit sla e ld ix,s_Numbers add ix,de ld h,d ;d is zero here ld e,c ld l,c add hl,de add hl,de add hl,hl add hl,hl ;hl = 12*y ld e,b add hl,de ;hl = 12*y + x push hl exx pop hl ld bc,gbuf2 add hl,bc ld de,12 push de exx pop de ld bc,gbuf1 add hl,bc ld b,8 DrawDigitLoop: exx ld a,(hl) or (ix+0) ld (hl),a add hl,de exx ld a,(hl) or (ix+0) ld (hl),a add hl,de inc ix djnz DrawDigitLoop ret ;##################### ;# Music Functions # ;##################### PlayNote: ld hl,v_MusicPlays inc (hl) ret z ld (hl),-1 ld hl,(v_NotePtr) ld a,(hl) inc a ret z inc a jr nz,SkipResetMP ld hl,(v_LoopPtr) SkipResetMP: ld a,(hl) inc hl ld (v_NotePtr),hl or a ret z ld e,a ld bc,c_NoteTime PlayNoteLoop2: ld d,e LINKOUT(set00) PlayNoteLoop1: dec bc ld a,b or c ret z dec d jr nz,PlayNoteLoop1 LINKOUT(setLR) jp PlayNoteLoop2 ;################### ;# SMC Functions # ;################### SMCrom: MAP(RestoreSingle,SMCrom,SMCram) RestoreLookLeft: MAP(smc_LeftOffset,SMCrom,SMCram)+2 ld a,(ix+0) dec a ld a,e jr z,RestoreSingleFound ld a,c cp 15 jr nz,RestoreNextRight ld a,e or a jr nz,RestoreNextLeft jr RestoreSingleReturn RestoreLookRight: MAP(smc_RightOffset,SMCrom,SMCram)+2 ld a,(ix+0) dec a ld a,c jr z,RestoreSingleFound ld a,e or a jr nz,RestoreNextLeft ld a,c cp 15 jr nz,RestoreNextRight RestoreSingleReturn: ld hl,v_QueueSize ;Delete the new item we allocated dec (hl) xor a ld (v_NewBlocks),a ;No more incoming blocks allowed ret RestoreSingleFound: ld (smc_FinalOffset),a MAP(smc_FinalOffset,SMCrom,SMCram)+2 ld (ix+0),2 add a,a ld c,a add a,a add a,c ;X=block*6 ld (hl),a inc hl ;now on index/speed ld (hl),e_Block|c_BSpeed inc hl ;now on timers ld (hl),%00010000 inc hl ;now on Y ld (hl),c_FallHeight+7 ld hl,v_NewBlocks dec (hl) ret RestoreNextRight: inc c ld a,c ld (smc_RightOffset),a jr RestoreLookRight RestoreNextLeft: dec e ld a,e ld (smc_LeftOffset),a jr RestoreLookLeft MAP(Draw8x8,SMCrom,SMCram) ld d,7 ;Input b = Sprite X Position ld a,c ;Input c = Sprite Y Position add a,d ;Input ix = Sprite jr c,ClipTop sub 64+7 ret nc cpl ;equivilent to "neg a / dec a" cp d jr nc,NoClip ClipBottom: ld d,a jr NoClip ClipTop: ld d,a ClipTopLoop: inc ix inc c jr nz,ClipTopLoop NoClip: ld a,b ld b,0 ld h,b ld l,c add hl,bc add hl,bc add hl,hl add hl,hl ;hl = 12*y ld c,a srl c srl c srl c add hl,bc ;hl = 12*y + x/8 push hl exx pop hl ld bc,gbuf2 add hl,bc ld de,12 exx ld bc,gbuf1 add hl,bc ld b,d inc b ld de,12 and %00000111 ;a is the alignment jr z,DrawSpriteAlignedLoop xor %00000111 ld e,a add a,a add a,e ;a = 3*(7-a) ld (smc_ShiftTable1),a ld (smc_ShiftTable2),a ;set up the SMC ld a,b DrawSpriteNonAligned: ex af,af' xor a ;Reset carry flag ld a,(ix+0) ;Shift B/W MAP(smc_ShiftTable1,SMCrom,SMCram)+1 jr $+0 ;SMC rra rr d ;d is always zero at this point rra rr d rra rr d rra rr d rra rr d rra rr d rra rr d ld e,a exx ld a,(ix+8) ;Shift Shadow inc ix MAP(smc_ShiftTable2,SMCrom,SMCram)+1 jr $+0 ;SMC rra ;carry flag is always reset here rr d ;d is always zero at this point rra rr d rra rr d rra rr d rra rr d rra rr d rra rr d ld e,a ;Create Left Mask 1,2 exx or e cpl ld c,a exx and (hl) ;Apply Left Mask 1 or e ld (hl),a inc hl ld a,d ;Create Right Mask 1,2 exx or d cpl ld b,a exx and (hl) ;Apply Right Mask 1 or d ld (hl),a ld de,11 add hl,de exx ld a,(hl) ;Apply Left Mask 2 and c or e ld (hl),a inc hl ld a,(hl) ;Apply Right Mask 2 and b or d ld (hl),a ld de,11 add hl,de ex af,af' dec a jr nz,DrawSpriteNonAligned ret DrawSpriteAlignedLoop: ld a,(ix+0) or (ix+8) cpl ld c,a ;c contains: not(s1 or s2) in register exx and (hl) or (ix+8) ld (hl),a add hl,de exx ld a,c and (hl) or (ix+0) ld (hl),a add hl,de inc ix djnz DrawSpriteAlignedLoop ret MAP(ClearScrn,SMCrom,SMCram) ld a,%00111110 ;load next byte into a jp SkipClearBit MAP(UpdateScrn,SMCrom,SMCram) ld a,%00011000 ;unconditional "jr" MAP(SkipClearBit,SMCrom,SMCram) ld (smc_Clear),a ld (smc_SaveSP1),sp ld sp,gbuf3-1 ld hl,smc_Gray rrc (hl) CopyBuf: ld a,$80 out ($10),a ld hl,gbuf1+(12*63)-1 ld ix,gbuf2+(12*63)-1 ld a,$20 ld c,a CopyNextCol: ld b,64 inc c ld de,-(12*64)+1 add hl,de add ix,de out ($10),a ld de,12 CopyLoop: add hl,de add ix,de MAP(smc_Gray,SMCrom,SMCram)+1 ld a,%10101010 rrca ld (smc_Gray),a or (ix+0) and (hl) out ($11),a MAP(smc_Clear,SMCrom,SMCram)+0 jr CopyNoClear ;will either jump or load # into a ld (ix+0),d ;d is zero here. pop af ld (hl),a CopyNoClearFinal: dec sp djnz CopyLoop ld a,c cp $2B+1 jr nz,CopyNextCol MAP(smc_SaveSP1,SMCrom,SMCram)+1 ld sp,$0000 ret CopyNoClear: nop jr CopyNoClearFinal ;gives it just enough T-States SMCromend: ;########## ;# Data # ;########## #include Music.inc #include Sprites.inc d_IncBgnd1: .dw 100,s_b1 .dw 250,s_b2 .dw 500,s_b3 .dw 1000,s_b4 .dw 1500,s_b5 .dw 2000,s_b6 .dw 2500,s_b7 .dw 3000,s_b8 .dw 3500,s_b9 .dw 4000,0 .dw 4500,s_b10 .dw -1 d_IncBgnd2: .dw 100,s_b11 .dw 250,s_b12 .dw 500,s_b13 .dw 100,s_b14 .dw 1500,s_b15 .dw 2000,s_b16 .dw 2500,s_b17 .dw 3000,s_b18 .dw 3500,s_b19 .dw 4000,0 .dw 4500,s_b10 .dw -1 d_IncBgnd3: .dw 100,s_b21 .dw 250,s_b22 .dw 500,s_b23 .dw 1000,s_b24 .dw 1500,s_b25 .dw 2000,s_b26 .dw 2500,s_b27 .dw 3000,s_b28 .dw 3500,s_b29 .dw 4000,0 .dw 4500,s_b10 .dw -1 ;########## ;# Text # ;########## txt_PyoroHS: .db 15h,"PyoroHS",0 .end