;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; ; +----------------------------------------+------------+ ; | ____ ____ ____ ____ _ __ __ | ___ | ; | ||__)) ||__ ||__)) || // \\ ||\ || | o (O_O) | ; | || \\ ||__ || || \\_// || \|| o | \\_| |_ | ; | | \_ _\ | ; +----------------------------------------+ |_| \\ | ; | R E P T O N z80 - Ben Ryves 2003 | / ^ \ o | ; | Based on the game by Superior Software | || || | ; | (C) Timothy Tyler 1985 | /_/ \_\ | ; | Visit www.calc83plus.tk for more! | | ; +----------------------------------------+------------+ ;z80 programmers: quake with fear as ye see how I ruthlessly ;ignore putting any useful comments on the source (mwahahah) ; ;Everyone else - this code was written by me (Ben Ryves) and ;what wasn't written by me is such trivial stuff as the ;greyscale engine, written by the l33t programmer Duck (don't ;ask). ; ;Thanks for downloading! ; ; -Ben Ryves ; ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;UPDATES: ;NO1: Fixed bug that meant eggs smashed ALWAYS when up 1 l/r 1 ; I think it is fair to say that there is SHEDLOADS of code here: ;#define NOMONSTERS ;If defined - Monsters don't appear :) ;#define CHEATS ;When defined, the cheat key is available. #define MapW 32 #define MapH 32 #define R.L1 1 #define R.L2 2 #define R.R1 3 #define R.R2 4 #define R.U1 5 #define R.U2 6 #define M.U 1 #define M.D 2 #define M.L 3 #define M.R 4 ;========================================================== ;Header ;========================================================== .nolist #ifdef VTI #define TI83P #endif #include "keyval.inc" #ifdef MIRAGE #define TI83P #include "mirage.inc" ;NB IS MY MODIFIED VERSION!!! #else #include "ion.inc" #endif .list #ifdef TI83P .org progstart-2 .db $BB,$6D #else .org progstart #endif ret #ifdef MIRAGE ;MIRAGEOS HEADER: .db 1 .db %00000000, %00000000 .db %01111111, %11111100 .db %00000000, %00000000 .db %00111000, %00000000 .db %01110100, %01110000 .db %00111000, %10101000 .db %00110001, %01011100 .db %01111101, %10101100 .db %00110001, %01011100 .db %01111000, %11111000 .db %01101100, %01110000 .db %00000000, %00000000 .db %01111111, %11111100 .db %01111111, %11111100 .db %00000000, %00000000 #else ;ION HEADER: jr nc,start_of_program #endif .db "Repton v1 - Ben Ryves",0 start_of_program: ;========================================================== ; start of program ;========================================================== ld a,(contrast) ;SYSTEM value add a,18h ;=valid contrast :) ld (ReptonContrast),a ;///////////////////////////////////Create RAM page file... for level decompression &c bcall(42E5h) ; Free RAM => hl. ld de,32*34 ; Size of level => de bcall(_cphlde) ; Compare ret c ; Not enough RAM? Shame! RET. ;Create 'page file': bcall(_zeroop1) ; Set Op1 to zero ld hl,PageFileName ; the name of the prog ld de,op1 ; copy it to op1 ld bc,8 ; 7 chars in name ldir ; do the copying bcall(_chkfindsym) ; look it up jr c,NoNeedDelete bcall(_delvar) ; if it is there delete it (to keep things clean) NoNeedDelete: ld hl,32*34 ; length of program (in bytes) bcall(_createprog) ; create it inc de ; skip 1st length byte inc de ; skip 2nd length byte ld (LevelLoc),de ;DE = Start Location of Page file- preserve it to (LevelLoc) ;////////////////////////////////////////////////////////////////////////////////////// ld hl,gActivebuf1 ld bc,768*2 ld a,$FF bcall(4C33h) ld hl,SplashScreen1 ld de,gActivebuf2+(15*12) ld bc,12*32 ldir ld hl,SplashScreen2 ld de,gActivebuf1+(15*12) ld bc,12*32 ldir call gsEnable call Wait2nd MainMenu: call gsDisable set textwrite,(iy+sgrflags) ;Write to BUFFER ;Now we have created the page file... (I hate internal caching- it makes the program so HUGE) ;...Scan for levels! ld hl,(ProgPtr) ld ix,FileName call ionDetect ret nz LoopedFiles: ld hl,(ProgPtr) ld (ProgPt),hl FindNextFile: ld hl,(ProgPt) ld ix,FileName call ionDetect ld (ProgPt),de jp nz,LoopedFiles inc hl ld (FileLoc),hl ld hl,(FileLoc) bcall(_grbufclr) ld hl,Title ld de,PlotsScreen+(12*5) ld bc,8*12 ldir ld hl,Credit ld de,(256*20)+24 ;'Ben Ryves 2003' ld (pencol),de bcall(_vputs) ld de,(256*27)+16 ;'www.calc83plus.tk' ld (pencol),de bcall(_vputs) ld de,(256*42)+22 ;'2nd to Play' ld (pencol),de bcall(_vputs) ld de,(256*49)+15 ;'Alpha:' ld (pencol),de bcall(_vputs) ld hl,(FileLoc) bcall(_vputs) ;Display level name ld (FileLoc),hl bcall(_grbufcpy) LoadingLevelKeyLoop: bcall(_getcsc) cp 36h jp z,LoadLevel cp 30h jp z,FindNextFile cp 0fh jp z,Quit jp LoadingLevelKeyLoop LoadLevel: ;///////////////////////////////////////////////////// res textwrite,(iy+sgrflags) ;Write to BUFFER off ReloadAll: ld a,4 ld (Lives),a ld hl,(FileLoc) ld a,(hl) ; Load all dec a ld (Repton.x),a ; the (x,y) inc hl ; details ld a,(hl) ; from the inc a ld (Repton.y),a ; map for inc hl ; repton. ld a,(hl) ld (OffsetX),a inc hl ld a,(hl) ld (OffsetY),a inc hl ld (OrigLoc),hl xor a ld (MoveDir),a ld hl,0 ld (OldXY),hl ld hl,BadDude ld (BadDudePtr),hl ld hl,BadDude ld bc,16 ;16 bytes of BadDude caching! (d@mn I'm generous) ld a,-1 bcall(4C33h) ld hl,(LevelLoc) ld bc,34*32 ld a,4 bcall(4C33h) ;Fill the level area with solid blocks ! ld hl,32 ; program data is FROM 'level' ld de,(LevelLoc) ;Location of pagefile in RAM (+33) add hl,de push hl pop de ld hl,(OrigLoc) ld bc,32*32 ; program data length (32*32) ldir ;Copy all the data... CommitHaraKiri: ;Like honourable Japanese man. ld a,(Lives) ;LOSE A LIFE! [Not as if I had one anyway] :( dec a ld (Lives),a cp 0 ;Are we COMPLETELY a$$ed? jp z,GameOver ;//////////////Display Level Screen: call gsDisable ;IMPORTANT! [Hell yeah] bcall(_clrlcdfull) ;Mmmm, lovely ROM calls. ld hl,Lives_TXT ld de,(256*3)+3 ld (currow),de bcall(_puts) ld a,(Lives) ld l,a ld h,0 bcall(_disphl) ;Gaaah I hate this routine :( call BufferedKey ;Mine. ;///////////////Displayed Level Screen call ClearGBuffer ;\ Enable greyscale handler (im2) call gsEnable ;/ ld hl,(FileLoc) ld a,(hl) ; Load all dec a ld (Repton.x),a ; the (x,y) inc hl ; details ld a,(hl) ; from the inc a ld (Repton.y),a ; map for inc hl ; repton. ld a,(hl) ld (OffsetX),a inc hl ld a,(hl) ld (OffsetY),a ld a,(OffsetX) ld b,a ld a,(Repton.X) sub b ld (Screen.x),a ld a,(OffsetY) ld b,a ld a,(Repton.y) sub b ld (Screen.y),a call RealtoRX ld hl,(Repton.rX) ld (Repton.tX),hl call CalculateRealPos call ShiftScreenRight MainLoop: ;]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] Move any baddies! call ChangeBadDude ld hl,(Repton.rX) ld (TempRX),hl call CalculateRealPos ld hl,(Repton.x) ld (TempRXB),hl #ifndef NOMONSTERS ld a,(BadDelay) inc a ld (BadDelay),a cp 2 ;Speed of bad dude! jp nz,SkipBadDude xor a ld (BadDelay),a ld de,BadDude ld (MovBD),de BaddieMovingLoop: ld hl,(MovBD) ld a,(hl) cp -2 jp z,SkipBadDude cp -1 jp z,BadDudeDisabled ld hl,(MovBD) bcall(_ldhlind) ;Load current (x,y) of monster ld (Repton.x),hl ;...into Repton.x, Repton.y call ReadMapReal cp 20 jp nz,BadDudeDisabled ;There are the co-ords, but if there is no moster there ignore! xor a ;\ Erase the old bad dude position call WriteMapReal ;/ ld a,(TempRXB) ;IN->a = x position of Repton ld b,a ;a=>b ld a,(Repton.x) ;a=x pos of bad dude cp b jp z,NoMoveLeftRight jp nc,MoveBaddieLeft jp c,MoveBaddieRight MoveBaddieLeft: call DecX ;Look 1 left call ReadMapReal ;Check new pos cp 0 jp z,BaddieXIsRepX ;It's good! Move the bad dude! call IncX ;Move back to original location jp NoMoveLeftRight MoveBaddieRight: call IncX ;Look 1 right call ReadMapReal ;Check new pos cp 0 jp z,BaddieXIsRepX ;It's good! Move the bad dude! call DecX ;Move back to original location jp NoMoveLeftRight BaddieXIsRepX: ld a,20 call WriteMapReal jp MovedBaddieAI NoMoveLeftRight: ld a,(TempRXB+1) ;IN->a = x position of Repton ld b,a ;a=>b ld a,(Repton.y) ;a=x pos of bad dude cp b jp c,MoveBaddieDown jp nc,MoveBaddieUp MoveBaddieUp: call DecY ;Look 1 up call ReadMapReal ;Check new pos cp 0 jp z,BaddieXIsRepX ;It's good! Move the bad dude! call IncY ;Move back to original location jp BaddieXIsRepX MoveBaddieDown: call IncY ;Look 1 down call ReadMapReal ;Check new pos cp 0 jp z,BaddieXIsRepX ;It's good! Move the bad dude! call DecY ;Move back to original location jp BaddieXIsRepX MovedBaddieAI: ld hl,(MovBD) push hl pop ix ;ix= position to save new baddie position to ld hl,(Repton.x) ;Take in the new baddie position ld a,h ld (ix+1),a ld a,l ld (ix+0),a ;////////// Has the baddie 'hit' us? ld hl,(Repton.x) ld de,(TempRXB) bcall(_cphlde) jp z,Repton.Die BadDudeDisabled: ;ie, a=(-1) ld hl,(MovBD) inc hl \ inc hl ;add 2 ld (MovBD),hl jp BaddieMovingLoop SkipBadDude: #endif ld hl,(TemprX) ld (Repton.RX),hl call CalculateRealPos call RenderLevel call RenderRepton call gscopybuffer ld hl,(Repton.Rx) ld (Repton.BkupRx),hl ld hl,(Screen.x) ld (Screen.Bkupx),hl ;]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] End moving bad guys. ;Get key input: KeyWaitLoop: DelayLoopKey: ld hl,(AniTimer) inc hl ld (AniTimer),hl ld de,1024 bcall(_cphlde) jp z,Repton.Blink ld de,255 bcall(_cphlde) jr nz,NotResetPos xor a ld (ReptonChar),a jp MainLoop NotResetPos: call gsGetk cp GClear \ jp z,GameOver cp GUp \ jp z,Repton_Up cp GDown \ jp z,Repton_Down cp GLeft \ jp z,Repton_Left cp GRight \ jp z,Repton_Right cp GDel \ jp z,Repton.Die cp GF5 \ call z,gsSetFreq #ifdef CHEATS cp GSto \ call z,ParalyseBeasties #endif jp MainLoop quit: call gsDisable ;//////////Delete damn pagefile: bcall(_zeroop1) ; Set Op1 to zero ld hl,PageFileName ; the name of the prog ld de,op1 ; copy it to op1 ld bc,8 ; 7 chars in name ldir ; do the copying bcall(_chkfindsym) ; look it up ret c bcall(_delvar) ; if it is there delete it (to keep things clean) bcall(_clrLCDfull) im 1 di ret Repton.Blink: call RenderLevel call RenderRepton call gscopybuffer call RenderLevel ld ix,ReptonBlink call CustomRepton call gscopybuffer ld a,10 ShortPause: dec a cp 0 jr nz,ShortPause ld hl,0 ld (AniTimer),hl jp MainLoop ;///////////////////////////////////////////////////////////////////////////////////////////////////// RenderLevel: call GetMemAddress ld bc,96 ld de,0 NextPartOfLevel: ld a,(hl) cp 0 \ jr z,Tile_Space cp 1 \ jr z,Tile_Dirt cp 2 \ jr z,Tile_Diamond cp 3 \ jr z,Tile_Boulder cp 4 \ jr z,Tile_PlainBlck cp 5 \ jr z,Tile_Rounded cp 6 \ jr z,Tile_Rounded2 cp 7 \ jr z,Tile_Fours cp 8 \ jr z,Tile_Slope1 cp 9 \ jr z,Tile_Slope2 cp 10 \ jr z,Tile_Slope3 cp 11 \ jr z,Tile_Slope4 cp 12 \ jr z,Tile_Top cp 13 \ jr z,Tile_Bottom cp 14 \ jr z,Tile_Left cp 15 \ jr z,Tile_Right cp 16 \ jr z,Tile_Centre cp 17 \ jr z,Tile_Egg cp 18 \ jr z,Tile_Key cp 19 \ jr z,Tile_Safe cp 20 \ jr z,Tile_BadDude Tile_Space: ld ix,Space \ jr Level_FoundSprite Tile_Dirt: ld ix,Dirt \ jr Level_FoundSprite Tile_Diamond: ld ix,Diamond \ jr Level_FoundSprite Tile_Boulder: ld ix,Boulder \ jr Level_FoundSprite Tile_PlainBlck: ld ix,PlainBlck \ jr Level_FoundSprite Tile_Rounded: ld ix,Rounded \ jr Level_FoundSprite Tile_Rounded2: ld ix,Rounded2 \ jr Level_FoundSprite Tile_Fours: ld ix,Fours \ jr Level_FoundSprite Tile_Slope1: ld ix,Slope1 \ jr Level_FoundSprite Tile_Slope2: ld ix,Slope2 \ jr Level_FoundSprite Tile_Slope3: ld ix,Slope3 \ jr Level_FoundSprite Tile_Slope4: ld ix,Slope4 \ jr Level_FoundSprite Tile_Top: ld ix,SlopeTop \ jr Level_FoundSprite Tile_Bottom: ld ix,SlopeBottom \ jr Level_FoundSprite Tile_Left: ld ix,SlopeLeft \ jr Level_FoundSprite Tile_Right: ld ix,SlopeRight \ jr Level_FoundSprite Tile_Centre: ld ix,SlopePlain \ jr Level_FoundSprite Tile_Egg: ld ix,Egg \ jr Level_FoundSprite Tile_Key ld ix,Key \ jr Level_FoundSprite Tile_Safe ld ix,Safe \ jr Level_FoundSprite Tile_BadDude ld ix,Monster \ jr Level_FoundSprite Level_FoundSprite: push hl push de ld a,d ld l,e call gsAlignedSprite pop de pop hl inc d ld a,d cp 12 jr nz,NoIncY ld d,0 ld a,e add a,8 ld e,a push de ld de,32-12 ;Level=32 Wide add hl,de pop de NoIncY: inc hl dec bc ld a,b or c jp nz,NextPartOfLevel ret ;///////////////////////////////////////////////////////////////////////////////////////////////////// OldXY: .dw 0 GetMemAddress: ;Gets Memory Address for tile @ (Screen.x,Screen.y) ld hl,(LevelLoc) push hl ld a,(Screen.y) ld l,a ld h,0 ;hl=Repton.y add hl,hl ;hl*2 add hl,hl ;hl*4 add hl,hl ;hl*8 add hl,hl ;hl*16 add hl,hl ;hl*32 ld a,(Screen.x) ld e,a ld d,0 add hl,de pop de add hl,de ret ReadMap: ;In: Repton.Rx, Repton.Ry, Screen.x, Screen.y Out: a= block he is on! call CalculateRealPos ReadMapReal: ld hl,(Screen.x) push hl ld hl,(Repton.x) ld (Screen.x),hl call GetMemAddress ex de,hl pop hl ld (Screen.x),hl ld a,(de) ret WriteMapReal: push af jr WriteReal WriteMap: ;In: Repton.Rx, Repton.Ry, Screen.x, Screen.y,a Out: Repton.x,Repton.y on map =a push af call CalculateRealPos WriteReal: ld hl,(Screen.x) push hl ld hl,(Repton.x) ld (Screen.x),hl call GetMemAddress ex de,hl pop hl ld (Screen.x),hl pop af ld (de),a ret CalculateRealPos: ;Calculate 'real' position of REPTON! ld a,(Repton.Ry) ld b,a ld a,(Screen.y) add a,b ld (Repton.y),a ld a,(Repton.Rx) ld b,a ld a,(Screen.x) add a,b ld (Repton.x),a ret Repton_Up: ld a,M.U ld (MoveDir),a call ReptonAniUD ld a,(Repton.y) cp 0 jp z,MainLoop ld a,(Repton.Ry) cp 2 call z,ShiftScreenUp dec a jr SetReptonY Repton_Down: ld a,M.D ld (MoveDir),a call ReptonAniUD ld a,(Repton.y) cp 32 jp z,MainLoop ld a,(Repton.Ry) cp 5 call z,ShiftScreenDown inc a SetReptonY: ld (Repton.Ry),a jp CheckNewPos Repton_Left: ld a,M.L ld (MoveDir),a call ReptonAniL ld a,(Repton.x) cp 0 jp z,MainLoop ld a,(Repton.Rx) cp 2 call z,ShiftScreenLeft dec a jr SetReptonX Repton_Right: ld a,M.R ld (MoveDir),a call ReptonAniR ld a,(Repton.x) cp 31 jp z,MainLoop ld a,(Repton.Rx) cp 9 call z,ShiftScreenRight inc a SetReptonX: ld (Repton.Rx),a jp CheckNewPos ShiftScreenDown: push af ld a,(Screen.y) cp 25 jp z,ReturnScreenShift inc a ld (Screen.y),a pop af dec a ret ShiftScreenUp: push af ld a,(Screen.y) cp 1 ;1 because of border of rocks ;( jp z,ReturnScreenShift dec a ld (Screen.y),a pop af inc a ret ShiftScreenLeft: push af ld a,(Screen.x) cp 0 jp z,ReturnScreenShift dec a ld (Screen.x),a pop af inc a ret ShiftScreenRight: push af ld a,(Screen.x) cp 32-12 jp z,ReturnScreenShift inc a ld (Screen.x),a pop af dec a ret ReturnScreenShift: pop af ret ReptonAniL: ld a,(ReptonChar) cp 0 jr z,RALIsZero cp R.L2 jr nz,RALNotZero RALIsZero: ld a,R.L1 ld (ReptonChar),a ret RALNotZero: ld a,R.L2 ld (ReptonChar),a ret ReptonAniR: ld a,(ReptonChar) cp 0 jr z,RARIsZero cp R.R2 jr nz,RARNotZero RARIsZero: ld a,R.R1 ld (ReptonChar),a ret RARNotZero: ld a,R.R2 ld (ReptonChar),a ret ReptonAniUD: ld a,(ReptonChar) cp 0 jr z,RAUIsZero cp R.U2 jr nz,RAUNotZero RAUIsZero: ld a,R.U1 ld (ReptonChar),a ret RAUNotZero: ld a,R.U2 ld (ReptonChar),a ret CheckNewPos: ;Physics! ld hl,0 ld (AniTimer),hl call CalculateRealPos call ReadMap ld (CurPiece),a cp 0 jp z,Move cp 1 jr z,MoveIntoDirt cp 2 jr z,PickupDiamond cp 3 jr z,PushRock cp 17 jr z,PushRock ;Egg! cp 18 jp z,UnlockSafes ;Key - unlock all the safes! NoMove: ld hl,(Repton.BkupRx) ld (Repton.Rx),hl ld hl,(Screen.BkupX) ld (Screen.x),hl jp MainLoop MoveIntoDirt: ld a,0 call WriteMap CheckLevelEnd: ld hl,(LevelLoc) ld bc,1024 DiamondScanRepeat: ld a,(hl) ; Getting the current byte cp 2 jr z,NotLevelEnd ;A diamond? We cannot have finished the level then... cp 19 ;Or a safe? jr z,NotLevelEnd inc hl dec bc ; Handling the loop ld a,b or c jr nz,DiamondScanRepeat jp CompletedLevel ;<> the level is over! <> NotLevelEnd: jp Move PickupDiamond: jr MoveIntoDirt PushRock: ld a,(MoveDir) cp M.L jp z,PushRockLeft cp M.R jp z,PushRockRight jp NoMove PushRockLeft: call DecRX call ReadMap cp 0 jp nz,NoMove ld a,(CurPiece) call WriteMap call IncRX call CalculateRealPos ld a,0 call WriteMap ;call QuickRender call FallDown jp Move PushRockRight: call IncRX call ReadMap cp 0 jp nz,NoMove ld a,(CurPiece) call WriteMap call DecRX call CalculateRealPos ld a,0 call WriteMap ;call QuickRender call FallDown jp Move Move: ;Now we have moved, the fun can begin! (no, not really... it's time to calculate stone movement!) ld hl,(Repton.Rx) ;Preserve the rX and rY of Repton ld (TempRX),hl ;"""""""" """ "" """ "" "" """""" ld (TempRXB),hl ;/////////////////////////////////////////SCANS for rocks &c UP & LEFT/RIGHT xor a ld (FallDist),a ld hl,(TempRXB) push hl call DecRY call DecRY call DecRX call ReadMap ld (CurPiece),a cp 3 call z,FallingBLoop cp 17 call z,FallingBLoop call IncRX call IncRX call ReadMap ld (CurPiece),a cp 3 call z,FallingBLoop cp 17 call z,FallingBLoop pop hl ld (Repton.rX),hl ld (TempRX),hl ld (TempRXB),hl ;///////////////////////////////////////////////////////////////////////////////////// ;Check top-left call DecRX call DecRX call DecRY call ReadMap cp 3 jr z,NFFTL cp 17 jr z,NFFTL ;Egg jp FailedFreeTL NFFTL: ld (CurPiece),a call IncRX call ReadMap cp 0 jp nz,FailedFreeTL call IncRY call ReadMap cp 0 jp nz,FailedFreeTL call DecRX call ReadMap cp 9 \ jr z,NotTL cp 3 \ jr z,NotTL cp 2 \ jr z,NotTL cp 5 \ jr z,NotTL cp 6 \ jr z,NotTL cp 7 \ jr z,NotTL jp FailedFreeTL NotTL: call DecRY xor a call WriteMap call IncRX ld a,(CurPiece) call WriteMap call FallingBLoop FailedFreeTL: ;Check top-right ld hl,(TempRXB) ld (Repton.rX),hl call IncRX call IncRX call DecRY call ReadMap cp 3 jr z,NFFTR cp 17 jr z,NFFTR jp FailedFreeTR NFFTR: ld (CurPiece),a call DecRX call ReadMap cp 0 jp nz,FailedFreeTR call IncRY call ReadMap cp 0 jp nz,FailedFreeTR call IncRX call ReadMap cp 8 \ jr z,NotTR cp 3 \ jr z,NotTR cp 2 \ jr z,NotTR cp 5 \ jr z,NotTR cp 6 \ jr z,NotTR cp 7 \ jr z,NotTR jp FailedFreeTR NotTR: call DecRY xor a call WriteMap call DecRX ld a,(CurPiece) call WriteMap call FallingBLoop FailedFreeTR: ;Check bottom-left ld hl,(TempRXB) ld (Repton.rX),hl call DecRX call IncRY call ReadMap cp 3 jr z,NFFBL cp 17 jr z,NFFBL jp FailedFreeBL NFFBL: ld (CurPiece),a call IncRX call ReadMap cp 0 jp nz,FailedFreeBL call IncRY call ReadMap cp 0 jp nz,FailedFreeBL call DecRX call ReadMap cp 9 \ jr z,NotBL cp 3 \ jr z,NotBL cp 2 \ jr z,NotBL cp 5 \ jr z,NotBL cp 6 \ jr z,NotBL cp 7 \ jr z,NotBL jp FailedFreeBL NotBL: call DecRY xor a call WriteMap call IncRX ld a,(CurPiece) call WriteMap call FallingBLoop FailedFreeBL: ;Check bottom-right ld hl,(TempRXB) ld (Repton.rX),hl call IncRX call IncRY call ReadMap cp 3 jr z,NFFBR cp 17 jr z,NFFBR jp FailedFreeBR NFFBR: ld (CurPiece),a call DecRX call ReadMap cp 0 jp nz,FailedFreeBR call IncRY call ReadMap cp 0 jp nz,FailedFreeBR call IncRX call ReadMap cp 9 \ jr z,NotBR cp 3 \ jr z,NotBR cp 2 \ jr z,NotBR cp 5 \ jr z,NotBR cp 6 \ jr z,NotBR cp 7 \ jr z,NotBR jp FailedFreeBR NotBR: call DecRY xor a call WriteMap call DecRX ld a,(CurPiece) call WriteMap call FallingBLoop FailedFreeBR: ld hl,(TempRXB) ld (Repton.rX),hl call DecRY call DecRX call ReadMap cp 3 jr z,StoneUpLeft cp 17 ;Egg jr z,StoneUpLeft jp NoStoneUpLeft StoneUpLeft: ld (CurPiece),a ;Okay, so there is a stone up one and left one. Now, manage it! call RockFallAbove NoStoneUpLeft: ld hl,(TempRX) ld (Repton.rX),hl call DecRY call IncRX call ReadMap cp 3 jr z,StoneUpRight cp 17 ;Egg jr z,StoneUpRight jp NoStoneUpRight StoneUpRight: ld (CurPiece),a ;Okay, so there is a stone up one and left one. Now, manage it! call RockFallAbove NoStoneUpRight: ld hl,(TempRX) ld (Repton.rX),hl ;Now, all I need to do is check that there are no stones to fall on Repton and KILL HIM!!! (Mwahahaha) call DecRY call ReadMap cp 0 jr nz,NoHitHead call DecRY call ReadMap cp 3 jr z,HitHead cp 17 jr z,HitHead jp NoHitHead HitHead: ld (CurPiece),a xor a call WriteMap call IncRy ld a,(CurPiece) call WriteMap ld hl,(TempRX) ld (Repton.rX),hl call DecRy xor a call WriteMap call FallingBLoop ;If not called, Rock hits Repton, and sticks in mid air :{) I have a l33t moustache. ld hl,(temprxb) ld (Repton.rx),hl jp Repton.Die NoHitHead: ld hl,(TempRX) ld (Repton.rX),hl ;Okay, okay... now to check if he has moved away from a rock on a slope freeing its movement... [][][][][][][][][][][][][][][][][][][][] ld a,(MoveDir) cp M.L jp nz,NotMovedLeft call IncRX call IncRX call ReadMap cp 3 jr z,Roll ;No Rock on left: quit this routine... cp 17 ;Egg jr z,Roll jp NoRoll Roll: ld (CurPiece),a call IncRY call ReadMap cp 8 \ jr z,Roll3 cp 3 \ jr z,Roll3 cp 2 \ jr z,Roll3 cp 5 \ jr z,Roll3 cp 6 \ jr z,Roll3 cp 7 \ jr z,Roll3 cp 17 \ jr z,Roll3 jp NoRoll Roll3: call DecRX call ReadMap ;Check for hole for ball to go into cp 0 jp nz,NoRoll ;OKAY! We have a ball and a hole for it to land in... so shift it! ShiftBallDownL: ld a,(CurPiece) call WriteMap ;Place the ball in the hole ld hl,(Repton.Rx) ld (TempWord),hl call IncRX call DecRY xor a call WriteMap ld hl,(TempRX) ld (TempRXB),hl ld hl,(TempWord) ld (Repton.Rx),hl call FallingBLoop NotMovedLeft: ;Not moved left? ld a,(MoveDir) cp M.R jp nz,NotMovedRight ld hl,(TempRXB) ld (Repton.rX),hl call DecRX call DecRX call ReadMap cp 3 jr z,Roll2 cp 17 jr z,Roll2 jp NoRoll ;No Rock on left: quit this routine... Roll2: ld (CurPiece),a call IncRY call ReadMap cp 9 \ jr z,Roll4 cp 3 \ jr z,Roll4 cp 2 \ jr z,Roll4 cp 5 \ jr z,Roll4 cp 6 \ jr z,Roll4 cp 7 \ jr z,Roll4 cp 17 \ jr z,Roll4 jp NoRoll Roll4: call IncRX call ReadMap ;Check for hole for ball to go into cp 0 jp nz,NoRoll ;OKAY! We have a ball and a hole for it to land in... so shift it! ld a,(CurPiece) call WriteMap ;Place the ball in the hole ld hl,(Repton.Rx) ld (TempWord),hl call DecRX call DecRY xor a call WriteMap ld hl,(TempRX) ld (TempRXB),hl ld hl,(TempWord) ld (Repton.Rx),hl call FallingBLoop NotMovedRight: ; jp NoRoll ; NoRoll: ld hl,(TempRX) ld (Repton.rX),hl jp MainLoop FallDown: ld hl,(Repton.Rx) ld (TempRXB),hl ld a,(Repton.Rx) ld b,a ld a,(MoveDir) cp M.L jr nz,NotMoveLeftF dec b jr NotMoveRightF NotMoveLeftF: inc b NotMoveRightF: ld a,b ld (Repton.Rx),a ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;Repton.rX = boulder.x (I like x's) FallingBLoop: ;Will make the rock @ pos (rx,ry) fall down... repton is preserved in temprxb ld a,(FallDist) inc a ld (FallDist),a call IncRY ;add 1 to .rY so that we can see if boulder is on ? call ReadMap cp 8 jp z,RockMovesLeft cp 9 jp z,RockMovesRight cp 2 ;\ jp z,HitRoundedObject ;| cp 3 ;| jp z,HitRoundedObject ;| cp 5 ; \ Scan for 'rounded' blocks for rock to roll over! jp z,HitRoundedObject ; / cp 6 ;| jp z,HitRoundedObject ;| cp 7 ;| jp z,HitRoundedObject ;/ cp 20 ;Bad dude? call z,CrushBadDude cp 0 jr nz,StopFalling ;If there is not '0' under boulder, stop falling. ld a,(CurPiece) ;a=3, ie boulder. call WriteMap ;Put boulder in new position call DecRY ld a,0 call WriteMap call IncRY ld hl,(Repton.Rx) ;Preserve 'false' value ld de,(TempRXB) bcall(_cphlde) jp z,KillReptonRockOnHead RollingRockRet: ld (TempWord),hl ld hl,(TempRXB) ld (Repton.Rx),hl ld (TempRXB),hl call QuickRender ;Render display ld hl,(TempWord) ld (Repton.Rx),hl jr FallingBLoop StopFalling: ld a,(FallDist) cp 1 jr z,NotFallenFarEnough ;Stop falling code ld a,(CurPiece) cp 17 ;Was it an egg that just dropped? call z,EggBreak ;Break the egg! ;SMASH! NotFallenFarEnough: ld hl,(TempRXB) ld (Repton.Rx),hl ret KillReptonRockOnHead: pop af ld hl,(TempRXB) ld (Repton.rX),hl jp Repton.Die HitRoundedObject: ;Jump here when (rx,ry) = rounded object (other rock, diamond etc) ld hl,(Repton.rX) ;\ Preserve rX push hl ;/ call DecRY ;Up one call DecRX ;One left call ReadMap cp 0 ;Is the space left of the block free? jr z,WillMoveLeft call IncRX call IncRX call ReadMap cp 0 jr z,WillMoveRight pop hl ld (Repton.rX),hl jp StopFalling ;Have hit an object, cannot roll left/right, so stop falling! WillMoveLeft: pop hl ld (Repton.rX),hl jp RockMovesLeft WillMoveRight: pop hl ld (Repton.rX),hl jp RockMovesRight RockMovesLeft: ld hl,(Repton.rX) ld (RockBuggered),hl ;Rock wants to get to (Repton.rX) = 1 down from current pos! call DecRY ;Check 1 above... (where rock used to be) call DecRX ;...and one left! (Where rock is rolling into) call ReadMap cp 0 jp nz,NoRockRoll call IncRY ;Go 1 down (this is where the rock will roll into!) call ReadMap cp 0 ;'0'? If not.. jp nz,NoRockRoll ;Don't move the bloody rock. ld a,(CurPiece) ;Hahaha! We can move the rock! call WriteMap ld hl,(Repton.rX) push hl ;Push x,y of Rock onto stack call IncRX call DecRy xor a call WriteMap ;Erase old Rock position! ld hl,(TempRXB) ld (Repton.Rx),hl ld (TempRXB),hl call QuickRender ;Repton.rX needs to be Addr of rock pos! pop hl ld (Repton.rX),hl jp RollingRockRet RockMovesRight: ld hl,(Repton.rX) ld (RockBuggered),hl ;Rock wants to get to (Repton.rX) = 1 down from current pos! call DecRY ;Check 1 above... (where rock used to be) call IncRX ;...and one left! (Where rock is rolling into) call ReadMap cp 0 jp nz,NoRockRoll call IncRY ;Go 1 down (this is where the rock will roll into!) call ReadMap cp 0 ;'0'? If not.. jp nz,NoRockRoll ;Don't move the bloody rock. ld a,(CurPiece) ;Hahaha! We can move the rock! call WriteMap ld hl,(Repton.rX) push hl ;Push x,y of Rock onto stack call DecRX call DecRy xor a call WriteMap ;Erase old Rock position! ld hl,(TempRXB) ld (Repton.Rx),hl ld (TempRXB),hl call QuickRender ;Repton.rX needs to be Addr of rock pos! pop hl ld (Repton.rX),hl jp RollingRockRet NoRockRoll: ld hl,(RockBuggered) ld (Repton.Rx),hl call DecRY jp StopFalling IncRX: ld a,(Repton.rX) \ inc a \ ld (Repton.rX),a \ ret DecRX: ld a,(Repton.rX) \ dec a \ ld (Repton.rX),a \ ret IncRY: ld a,(Repton.rY) \ inc a \ ld (Repton.rY),a \ ret DecRY: ld a,(Repton.rY) \ dec a \ ld (Repton.rY),a \ ret IncX: ld a,(Repton.X) \ inc a \ ld (Repton.X),a \ ret DecX: ld a,(Repton.X) \ dec a \ ld (Repton.X),a \ ret IncY: ld a,(Repton.Y) \ inc a \ ld (Repton.Y),a \ ret DecY: ld a,(Repton.Y) \ dec a \ ld (Repton.Y),a \ ret RockFallAbove: ;////////////Not covered by FallingBLoop jobby call IncRY call ReadMap cp 20 ;Bad dude? call z,CrushBadDude cp 0 jr z,RockCanFall ret RockCanFall: call DecRY RockFallLoopLeft: call IncRY call ReadMap cp 0 jp nz,RockLeftStoppedFalling ld a,(CurPiece) call WriteMap ;Put a rock in the new lower position call DecRY ; xor a call WriteMap ; Clear the rock. ld a,(Repton.rY) ; inc a ; Go one dn (to reset original repton pos - stored in repton.ky) ld (Repton.kY),a ;Now that the first stone has been moved, I need to check and see if any on top of it need shifting: FindPiledRocks: call DecRY ; call ReadMap cp 3 jr nz,NoMorePiledRocks ;We've found a rock! (dude!) xor a call WriteMap call IncRY ld a,(CurPiece) call WriteMap call DecRY jr FindPiledRocks NoMorePiledRocks: ;No more rocks on top! ld a,(Repton.kY) ld (Repton.rY),a ld hl,(Repton.Rx) push hl ld hl,(TempRX) ld (Repton.rX),hl call QuickRender pop hl ld (Repton.Rx),hl jr RockFallLoopLeft RockLeftStoppedFalling: ;The rock has stopped falling (ie hit something!) call DecRY ;up 1 call FallingBLoop ;And now check it with the 'standard' routines. ret HitRoundedObject2: jp RockLeftStoppedFalling Repton.Die: ;Routine to show that Repton is to die (a hollible hollible death, ja?) ld hl,ReptonDie1 ld (TempRx),hl DeathLoop: call RenderLevel ld hl,(TempRx) push hl pop ix call CustomRepton call gsCopyBuffer ld hl,(TempRx) ld de,16 add hl,de ld (TempRx),hl ld de,ReptonDie5+16 bcall(_cphlde) jr nz,DeathLoop ld a,20 DeathPauseLoop: push af call gsCopyBuffer pop af dec a cp 0 jr nz,DeathPauseLoop jp CommitHaraKiri UnlockSafes: ld hl,(LevelLoc) ld de,(LevelLoc) ld bc,1024 SafeScanRepeat: ld a,(hl) ; Getting the current byte cp 19 jr nz,NotSafe ;Not a safe? Skip next stage: ld a,2 ;a=diamond tile NotSafe: inc hl ld (de),a ; Storing it inc de dec bc ; Handling the loop ld a,b or c jr nz,SafeScanRepeat jp MoveIntoDirt Repton.x: .db 0 Repton.y: .db 0 Repton.Rx: .db 0 Repton.Ry: .db 0 Repton.Tx: .db 0 Repton.Ty: .db 0 Screen.x: .db 0 Screen.y: .db 0 TempWord: .dw 0 TempRX: .dw 0 TempRXB: .dw 0 Repton.kY: .db 0 RollingRock: .dw 0 Repton.BkupRx: .dw 0 Screen.BkupX: .dw 0 AniTimer: .dw 0 MoveDir: .db 0 LevelLoc: .dw 0 FreedBoulder: .db 0 RockBuggered: .dw 0 OrigLoc: .dw 0 ReptonChar: .db 0 ProgPt: .dw 0 CurPiece: .db 0 KeyTimer: .db 0 BadDudeSp: .db 0 OffsetX: .db 0 OffsetY: .db 0 BadDude: .db -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-2 ;Or as many as you need! (-1 = no guy, -2 = EO array) BadDudePtr: .dw 0 MovBD: .dw 0 FileLoc: .dw 0 ReptonContrast: .db 50 Lives: .db 0 BadDelay: .db 0 FallDist: .db 0 QuickRender: call RenderLevel call RenderRepton call gsCopyBuffer ret RenderRepton: ld a,(ReptonChar) cp 0 jr z,NormalRepton cp R.L1 \ jr z,R.L1r cp R.L2 \ jr z,R.L2r cp R.R1 \ jr z,R.R1r cp R.R2 \ jr z,R.R2r cp R.U1 \ jr z,R.U1r cp R.U2 \ jr z,R.U2r R.L1r: ld ix,ReptonLeft1 \ call CustomRepton \ ret R.L2r: ld ix,ReptonLeft2 \ call CustomRepton \ ret R.R1r: ld ix,ReptonRight1 \ call CustomRepton \ ret R.R2r: ld ix,ReptonRight2 \ call CustomRepton \ ret R.U1r: ld ix,ReptonUp1 \ call CustomRepton \ ret R.U2r: ld ix,ReptonUp2 \ call CustomRepton \ ret NormalRepton: ld ix,Repton call CustomRepton ret CustomRepton: ld a,(Repton.Ry) sla a sla a sla a ld l,a ld a,(Repton.Rx) call gsAlignedSprite ret EggBreak: ;SMASH! The egg. call ReadMap cp 17 ;Egg? There should be jr z,NoDecRY call DecRY ;Move up 1 (if egg has been missed) NoDecRY: call CalculateRealPos xor a call WriteMap ld hl,(BadDudePtr) push hl pop ix ld hl,(Repton.X) ld a,h ld (ix+1),a ld a,l ld (ix+0),a ld hl,(BadDudePtr) inc hl inc hl ld (BadDudePtr),hl ld a,20 ;Draw in a 'Bad guy'. call WriteMap ret ChangeBadDude: ld a,(BadDudeSp) cp 0 jr z,M1Set ld hl,Monster1 xor a jr M2Set M1Set: ld hl,Monster2 ld a,1 M2Set: ld (BadDudeSp),a ld de,Monster ld bc,16 ldir ret RealToRX: ;In: Repton.x,Repton.y Out: Screen.x, Screen.y & Repton.rX, Repton.rY ld a,(Screen.x) ld b,a ld a,(Repton.x) sub b ld (Repton.rX),a ld a,(Screen.y) ld b,a ld a,(Repton.y) sub b ld (Repton.ry),a ret CrushBadDude: ;KILLKILLKILL! IN: (rx,ry) = pos of beastie. xor a call WriteMap ret ;========================================================== ; grayscale include file ;========================================================== ; comment these defines in or out to activate/deactivate them ;#DEFINE NODOUBLEBUFFER ;when on,routines write directly to screen (faster and smaller) ;#DEFINE 3LEVELGRAY ;makes it 3-level grayscale (a bit faster) #DEFINE XORSPRITE ;includes gsPutSprite ;#DEFINE LARGESPRITE ;includes gsLargeSprite #DEFINE ALIGNEDSPRITE ;includes gsAlignedsprite ;#DEFINE ALIGNEDMASKEDSPRITE #include graylib.inc #include "grfx.inc" PageFileName: .db 5,"REPPAGE",0 FileName: .db $C9,"Repton1",0 Credit: .db "Ben Ryves 2003",0 .db "www.calc83plus.tk",0 Key1: .db "2nd - Play Game",0 Key2: .db "Alpha - ",0 Lives_TXT: .db "Lives",0 ClearGBuffer: ;Clears the greyscale buffers FULLY xor a ld hl,gActivebuf1 ld bc,768*2 bcall(4C33h) ret Wait2nd: SplashLoop: call gsGetK cp G2nd jr nz,SplashLoop call gsDisable BufferedKey: bcall(_getcsc) cp 36h jp nz,BufferedKey ret GameOver: call ClearGBuffer call gsDisable bcall(_grbufclr) ld hl,GameOverPic ld de,PlotsScreen+(12*28) ld bc,8*12 ldir bcall(_grbufcpy) call Wait2nd jp MainMenu CompletedLevel: call ClearGBuffer call gsDisable bcall(_grbufclr) ld hl,LevelDone ld de,PlotsScreen+(12*23) ld bc,17*12 ldir bcall(_grbufcpy) call Wait2nd jp MainMenu #ifdef CHEATS ParalyseBeasties: ld hl,BadDude ld (BadDudePtr),hl ld hl,BadDude ld bc,16 ;16 bytes of BadDude caching! (d@mn I'm generous) ld a,-1 bcall(4C33h) ret #endif .end END