; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ V E R T I G O 0 . 9 4 (C) Matthew Shepcar 1998 ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß ; for the TI-82,83,85 and 86 #define VERSION "0.94" ; This source is EXTREMELY messy. It has 5 or 6 comments ; somewhere but I doubt they'll help you understand it much. :) ; To assemble the code you need to place a #define TI8X where 8X ; is the model of calculator. In the case of the TI85 you should ; insert #define TI85ZSHELL instead. If you want the editor to ; be assembled a #define EDITOR must also be included. ; Note on the TI-82, 83 and 85 versions: ; Since these calculators have multiple shells that often ; use relocation or other non-standard program loading methods ; I have implemented code to load the program at a fixed address ; and to allow variable creation and resizing. On the TI-85 ; the program is relocated in the same way as TI-82 and TI-83 ; programs to eliminate the need for CALL_ and JUMP_ statements. ; On all of these 3 calculators the program is then relocated ; back to its original location before any variable creation ; or resizing is performed. ; Due to the large amount of workspace required by Vertigo and the ; additional penalty of the interrupt handler and table required ; on the 82/85 a little trick is used to get a bit more space. ; Once the interrupt handler has been copied to the APD buffer/graphmem ; the space in the program where the interrupt handler was copied ; from is used as temporary workspace. The interrupt handler is ; copied back when it is uninstalled. This is not necessary on ; the TI-83 because the space at STATVARS is used. ; Final Note ; You might be able to make use of some of the maths routines from ; this source or even find some of the rom calls helpful (eg GET_KEY ; for the TI-83). Feel free to use any of the information or code ; in this program but give credit where credit is due. ; Thanks!! ; Matthew Shepcar ; M@Shepcar.force9.co.uk ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ To do list ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß ; þ contrast & greyscale controls ; þ ensure world 3 level 10 is possible ; þ mem checking on meminsert ; þ limit worlds to 99 levels & 16k ; þ flashing shadow when F1 selected ; þ time trial mode (save best times) ; þ two player stuff ; - send calced masks over link to improve speed ; - move other player's ball until next data packet received? ; þ demo recorder (already implemented just no interface) ; - record best times? ; þ rewrite swaplevels to work with variable level sizes ; þ put a diagram of the world coordinate system in src :) ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Bugs ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß ; þ Ball's centre bounces not its surface (code remmed out due to bugs) ; þ editor: blocks too high at back of board won't be drawn ; to allow this better vline & drawblock clipping needed ; otherwise height should be limited ; þ Some of the grid is cleared away by BlankMenuBar (85/86) ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Level Format ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß ; 0 2 Signature: 19h, 91h ; 2 1 Number of levels in string ; 3 1 Highest level reached ; 4 1 Title length ; 5 Title ; The levels follow each in this format: ; 0 121 Block heights & types ; 121 2 Ball position ; 123 1 Number of jewel/enemy waypoints (bit 7 set = jewel) ; 124 2 Jewel position ; 126 6 Level name ; 132 1 Time limit ; 133 n Waypoints ; Block height & type values: ; Bits ; 0 Clear if block empty (i think these are ; 1 Set if flat right anyway :) ; 2-7 Height ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Constants ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß RADIUS =4 ;ball radius YSCL =10 ;height of blocks * 2 THRUST =050h ;amount of thrust given by keys FRICTION =0ECh ;friction (0FFh = least friction) GRAVITY =013h ;acceleration due to gravity BOUNCINESS =09Ch ;higher values are bouncier STEPSIZE =100h ;maximum step size you can climb ENEMYFRAMES =2 ;move enemy every Xth frame ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Platform settings ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß #define FASTBUFCPY ;#define DEMO #ifdef TI82 #include ti82.h #define ROMCALL #define RELOC #define BUFSCR LINKPORT =0 D0HD1H =0C0H D0LD1H =0D4H D0HD1L =0E8H WorldInfo =8228h ;\ INTADDR =8282h ; | LinkBuffer =841Fh ; > apd buf LevelSpace =8421h ; | VarInfo =851Fh ;/ INTTABLE =8600h ;stuff here is backed up to textmem & cmdshadow SCRWID =96 XSCL =10 GAMESPEED =5 screenmem =GRAPH_MEM _curRow =CURSOR_ROW _penCol =CURSOR_X _divHLbyA =UNPACK_HL+2 CLEARTEXT =CLEARTEXT_F VATSTART =0FE6Eh VATEND =08D12h #define CUSTOMNAME "VARS" #define MORENAME "STAT" #define EXITNAME "MODE" #define DELNAME "DEL" #define F1NAME "Y=" .org START_ADDR StartAddr =$-3 #endif #ifdef TI83 #define equ .equ #define EQU .equ #include ti83asm.inc #define BUFSCR #define RELOC LINKPORT =0 Workspace =TEXTSHADOW VarInfo =TEXTSHADOW+117 SCRWID =96 XSCL =10 GAMESPEED =5 screenmem =PLOTSSCREEN LinkBuffer =8265h LevelSpace =8267h INTADDR =8383h Workspace2 =SAVESSCREEN+300h-70 INTTABLE =8600h WorldInfo =STATVARS CompressBuffer =PLOTSSCREEN _runindicoff =_runIndicOff _curRow =CURROW _penCol =PENCOL _clrScrn =_clrScrnFull _clrLCD =_CLRLCDFULL _setErrorHand =46A5h _clearErrorHand =46A9h _ASAP_IND =ASM_IND_CALL _ASAP_SEND =0Bh _ASAP_RECCONT =15h _ASAP_RECEIVE =16h _linkExec =_IO_EXEC LD_HL_MHL =4000h CP_HL_DE =4004h UNPACK_HL =4008h GET_KEY =4014h _insertMem =4432h ;2375 _CREATESTRNG =448Ah ;24E8 _delvar =44AAh ;26FF _deleteMem =44B2h ;2779 #define VATSTART (9319h) #define CUSTOMNAME "VARS" #define MORENAME "STAT" #define EXITNAME "MODE" #define DELNAME "DEL" #define F1NAME "Y=" .org 9327h StartAddr: nop jr Start .dw 0,Name,0,0 #endif #ifdef TI86 #include asm86.h #include ti86asm.inc #include ti86abs.inc #define NEWVAT #define GREY _setErrorHand =41A1h _clearErrorHand =41A4h _ASAP_SEND =0Ah _ASAP_RECCONT =14h _ASAP_RECEIVE =15h _linkExec =571Ch SCRWID =128 XSCL =12 GAMESPEED =7 LINKPORT =7 CONTRAST =0C008h screenmem =0FC00h VATSTART =0BFFFh VATEND =0D298h _divHLbyA =04048h _insertMem =046CFh _deleteMem =04767h #define CUSTOMNAME "CSTM" #define MORENAME "MORE" #define EXITNAME "EXIT" #define DELNAME "DEL" #define F1NAME "F1" .org _asm_exec_ram StartAddr: nop jp Start .dw 0,Name #endif #ifdef TI85 #include ti-85.h #define RELOC #define ROMCALL #define CUSTOMNAME "CSTM" #define MORENAME "MORE" #define EXITNAME "EXIT" #define DELNAME "DEL" #define F1NAME "F1" #define NEWVAT #define GREY #define VROM_CALL(addr) push hl \ ld hl,addr \ call VertRomCall ;#define SAFEGREY OP6 =80B9h WorldInfo =8641h INTADDR =8686h VarInfo =8850h INTTABLE =8900h LinkBuffer =8A01h LevelSpace =8A03h CompressBuffer =GRAPH_MEM SCRWID =128 XSCL =12 LINKPORT =7 D0HD1H =0C0H D0LD1H =0D4H D0HD1L =0E8H GAMESPEED =7 screenmem =0FC00h _curRow =CURSOR_ROW _penCol =CURSOR_X _divHLbyA =UNPACK_HL+2 VATSTART =0FA6Fh VATEND =08BEBh .org 09800h ;vertigo's own relocation routines are used StartAddr: #endif #ifndef TI86 #ifndef TI85 K_NOKEY =$00 ;No key K_DOWN =$01 ;Down K_LEFT =$02 ;Left K_RIGHT =$03 ;Right K_UP =$04 ;Up K_ENTER =$09 ;Enter K_PLUS =$0A ;+ X K_MINUS =$0B ;- T K_STAR =$0C ;* O K_SLASH =$0D ;/ J K_RAISE =$0E ;^ E K_CLEAR =$0F ;Clear K_SIGN =21h ; Space K_3 =$12 ;3 W K_6 =$13 ;6 S K_9 =$14 ;9 N K_RIGHTPAR =$15 ;) I K_TAN =$16 ;Tan D K_CUSTOM =$17 ;Custom K_DOT =$19 ;. Z K_2 =$1A ;2 V K_5 =$1B ;5 R K_8 =$1C ;8 M K_LEFTPAR =$1D ;( H K_COS =$1E ;Cos C K_PRGM =$1F ;Prgm K_MORE =$20 ;Del K_0 =$21 ;0 Y K_1 =$22 ;1 U K_4 =$23 ;4 Q K_7 =$24 ;7 L K_EE =$25 ;EE G K_SIN =$26 ;Sin B K_TABLE =$27 ;Table K_XVAR =$28 ;x-Var x K_ON =$29 ;On K_STO =$2A ;Sto = K_COMMA =$2B ;, P K_SQUARE =$2C ;x^2 K K_LN =$2D ;Ln F K_LOG =$2E ;Log A K_GRAPH =$2F ;Graph K_ALPHA =$30 ;Alpha K_F5 =$31 ;F5 K_F4 =$32 ;F4 K_F3 =$33 ;F3 K_F2 =$34 ;F2 K_F1 =$35 ;F1 K_SECOND =$36 ;2nd K_EXIT =$37 ;EXIT K_DEL =$38 ;stat #endif #endif Name: .db "Vertigo " #ifdef EDITOR .db "+ editor " #endif .db VERSION,0 ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ The Code! ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß Start: #ifdef TI82 ROM_CALL(BUSY_OFF) #else #ifndef TI85 call _runindicoff #endif #endif ;#ifdef TI82 ; RES 1,(IY+13) \ RES 2,(IY+13) ;#else ; res 1,(iy+13) ;#endif #ifdef BUFSCR set 7,(iy+20) #endif #ifdef TI85 ld hl,GRAPH_MEM+400h ld de,8860h ld bc,TEXT_MEM2-GRAPH_MEM-400h ldir #endif #ifdef TI82 ld hl,INTTABLE ld de,TEXT_MEM ld bc,81h ldir ld de,TEXT_MEM2 ld c,80h ldir #endif #ifdef TI86 call _flushallmenus call 4119h ;remove applets.. we need the space :) #endif #ifdef TI83 res 6,(iy+9) ;stats are now invalid #endif #ifdef TI85 CALL 8C0Fh .dw InstallInt-StartAddr ret c ld hl,Relocated push hl jp Relocate+adj Relocated: call ReInstallInt #else call InstallInt ret c #endif #ifndef TI82 #ifndef TI83 ld a,(CONTRAST) inc a inc a cp 32 jr nc,NotSetContrast out (2),a NotSetContrast: #endif #endif #ifdef TI85 ld hl,TI85ROMS ld a,(7FFFh) ld b,6 TryNextROM: cp (hl) inc hl jr z,GotROM inc hl djnz TryNextROM GotROM: ld a,(hl) ld (RomVerAdj),a #endif #ifdef TI82 ;Convert what ASH gives us to what CrASH would have done.. ld hl,(8D5Dh) ld de,302Eh ; .0 from ash 3.0 or a sbc hl,de jr nz,NotASHfix pop de pop bc pop hl dec hl dec hl dec hl push de push hl add hl,bc ld bc,3 ld de,StartAddr+ProgSize call SwapBytes ld c,3 pop hl ld de,StartAddr call SwapBytes pop hl inc c push de push bc push hl ;#ifdef EDITOR jr ASHFixed ;#endif NotASHfix: #endif #ifndef TI85 #ifdef RELOC ;#ifdef EDITOR ld hl,VarName rst 20h #ifndef NEWVAT call _CHKFINDSYM #else rst 10h inc de inc de inc de #endif ex de,hl inc hl inc hl push hl ;save current prog addr ;#endif #endif #endif #ifdef TI82 ASHFixed: ;#ifdef EDITOR call DeleteTemp ;#endif #endif xor a ld (Level),a TotalRestart: ld hl,NoWorldsFlag ld (hl),255 call StartWorldSearch Restart: call PutTitleBox ld hl,MenuStrings ld b,NumMenuStrings PutMenuStrings: ld e,(hl) inc hl ld d,(hl) inc hl call _vputs_de djnz PutMenuStrings PutWorldInfo: #ifdef TI86 call PageOut #endif ld hl,NoWorldsMsg ld a,(NoWorldsFlag) or a jr nz,NoWorldInfo ld hl,NameLength NoWorldInfo: call BlankWorldName ld b,(hl) inc hl call _vputsn PutGameMode: ld a,(GameMode) ld de,56*256+(SCRWID/2)-21 ld hl,ChallengeMsg dec a jr z,SetChallengeMode ld hl,LinkMsg dec a jr z,SetChallengeMode ld hl,PractiseMsg SetChallengeMode: call _vputs_de ld b,16 call vblank #ifdef BUFSCR call bufcpy #endif MainMenu: call GET_KEY cp K_ALPHA jr nz,NotChangeLevel xor a ld (Level),a call SearchNextWorld jr PutWorldInfo NotChangeLevel: cp K_DEL jr nz,NotModeChange ld hl,GameMode inc (hl) ld a,(hl) sub 2 ;3 jr nz,PutGameMode ld (hl),a jr PutGameMode NotModeChange: cp K_EXIT jp z,Exit #ifdef EDITOR cp K_MORE jp z,Editor #endif ld b,a call TryReceiveByte jr c,NotGotLinkByte cp LINK_VARINFO jp z,ReceiveWorld cp LINK_GAME jp z,AcceptLinkGame NotGotLinkByte: ld a,b cp K_CUSTOM jr nz,NotCustomKeys call PutTitleBox ld hl,CustomKeysMsg ld de,1700h+(SCRWID/2)-43 call _vputs_de ld de,2100h+(SCRWID/2)-30 call _vputs_de call GetCustomKey ld (KeyNW),a ld d,27h call _vputs_de call GetCustomKey ld (KeySE),a ld d,2Dh call _vputs_de call GetCustomKey ld (KeyNE),a ld d,33h call _vputs_de call GetCustomKey ld (KeySW),a #ifdef TI86 ld hl,VarName rst 20h rst 10h ret c ld hl,KeyNW-_asm_exec_ram+4 xor a add hl,de adc a,b ld de,KeyNW ld b,4 SaveKeys: push bc ex de,hl ld c,(hl) inc hl ex de,hl call _writeb_inc_ahl pop bc djnz SaveKeys #endif jp Restart NotCustomKeys: ld a,(NoWorldsFlag) or a jp nz,MainMenu ld a,b cp K_XVAR jp z,TransmitWorld cp K_F1 jp z,ViewScores cp K_SECOND jp nz,MainMenu ld a,(GameMode) cp 2 jr nz,NotAttemptLinkGame call PutTitleBox ld hl,WaitingMsg ld de,2000h+(SCRWID/2)-12 call _vputs_de TryConnect: ld a,LINK_GAME call SendByte ld a,1 jr nc,StartGame ld a,0BFh call _readkeypad bit 6,a jp z,Restart jr TryConnect NotAttemptLinkGame: xor a jr StartGame AcceptLinkGame: ld a,2 ;slave StartGame: ld (Linked),a xor a ld (Level),a ld a,5 ld (LivesLeft),a ld hl,0 ld (Score),hl ShowLevel: call DrawLevel ld hl,TimeMsg ld de,SCRWID-32 call _vputs_de ld a,(GameMode) or a jr z,DontPutScoreMsg ld hl,ScoreMsg ld de,3300h call _vputs_de ld hl,(Score) ld de,3900h ld b,5 call vputHL_de DontPutScoreMsg: StartLife: call InitBall call InitEnemy ld a,(TimeLimit) ld hl,0A00h call Multiply16 ld (TimeLeft),hl ld a,1 ld (TimeLeftTicker),a ld de,SCRWID-13 ld b,3 call vputHL_de ld a,(GameMode) or a jr z,DontPutLivesMsg ld hl,LivesMsg ld de,3900h+SCRWID-28 call _vputs_de ld a,(LivesLeft) ld hl,3900h+SCRWID-9 call vputAhl DontPutLivesMsg: ld hl,0 ld (XVelocity),hl ld (YVelocity),hl ld (HVelocity),hl ld (GameTics),hl #ifdef DEMO ld a,2 ld (DemoState),a ld (DownKeyState),hl ld (RightKeyState),hl ld (SecondKeyState),hl ld (XVARKeyState),hl ld hl,DemoBuffer ld (DemoPointer),hl #endif DEMO xor a ld (timer),a call HideBall call LoadEnemy call nz,RestoreBackground call HideJewel ld a,(WaypointCount) rla call nc,PutJewel call LoadEnemy call nz,PutSprite call LoadBall call GetSpriteCoords inc b inc c ld d,8 BallPopLoop: ld e,2 PopBlob: push bc ld a,b add a,d ld b,a call FlipPixels pop bc push bc ld a,c add a,d ld c,a call FlipPixels pop bc push bc ld a,b sub d ld b,a call FlipPixels pop bc push bc ld a,c sub d ld c,a call FlipPixels #ifdef BUFSCR push de call bufcpy pop de #endif pop bc dec e jr z,PoppedBlob ld a,10 call Delay jr PopBlob PoppedBlob: dec d ld a,d cp -2 jr nz,BallPopLoop PlayLoop: call GET_KEY cp K_F2 jr nz,NotToggleBallColour ld hl,Ball+3 #ifdef GREY ld b,6 #else ld b,3 #endif FlipBallColour: ld a,(hl) xor 11100000b ld (hl),a inc hl inc hl djnz FlipBallColour xor a NotToggleBallColour: cp K_F1 jr nz,NotFlashToggle ld hl,FlashFlag ld a,(hl) cpl ld (hl),a #if 0 ld hl,BallCentre ld a,(hl) #ifdef GREY or 64 ld (hl),a inc hl inc hl ld a,(hl) or 64 ld (hl),a #else and 0BFh ld (hl),a #endif ld hl,BallFlags ld a,(hl) or 2 ld (hl),a #endif NotFlashToggle: ld b,a ld a,(GameMode) or a ld a,b jr nz,NoChangeLevels ld hl,Level cp K_MINUS jr nz,NotPrev ld a,(hl) dec (hl) or a jr nz,NotLast ld a,(MaxLevel) ld (hl),a NotLast: jp ShowLevel NotPrev: cp K_PLUS jr nz,NotNext jr NextLev GotJewel: ld a,(Level) inc a ld hl,LevelCount cp (hl) jr z,NextLev ld hl,MaxLevel cp (hl) jr c,NextLev ld (hl),a call SaveWorldInfo NextLev: ld hl,(Score) ld de,(TimeLeft) add hl,de ld (Score),hl ld hl,Level ld a,(MaxLevel) inc (hl) cp (hl) jr nc,NotFirst ld (hl),0 ld a,(GameMode) dec a jp z,Completed NotFirst: jp ShowLevel NotNext: ; push af ; call HideBall ; pop bc NoChangeLevels: cp K_F5 jp z,Die cp K_MORE jr nz,NotPause Paused: ld hl,PauseMsg ld de,0600h+SCRWID-28 push de call _vputs_de pop hl ld (_penCol),hl xor a ld (timer),a PauseLoop: ld a,(timer) cp 50 jr nc,Paused cp 25 jr nz,NotFlashPause ld b,28 call vblank NotFlashPause: #ifdef BUFSCR call bufcpy #endif call GET_KEY or a jr z,PauseLoop ld b,28 call vblank NotPause: cp K_EXIT jr nz,NotExit ld a,(GameMode) or a jp z,Restart jp GameOver NotExit: ld b,a ld a,(BallH+1) sub 80h cp 78h jp c,Die ld a,(BallX+1) sub 0C0h cp 20h jp c,Die ld a,(BallY+1) sub 0C0h cp 20h jp c,Die #ifdef BUFSCR call bufcpy #endif ld hl,JewelData ld de,BallData push de call CheckSpriteCollision pop de jp c,GotJewel ld hl,EnemyData ld a,(WaypointCount) add a,a jr c,EnemyIsJewel call nz,CheckSpriteCollision jp c,Die EnemyIsJewel: ld a,FRICTION ld hl,(XVelocity) call Multiply16 ld (XVelocity),hl ld a,FRICTION ld hl,(YVelocity) call Multiply16 ld (YVelocity),hl call GetBallPlatformHeight ; push hl push de inc h ld de,(BallH) or a sbc hl,de add hl,hl pop de ; pop hl jr c,InFlight ld h,d ld l,e sra h rr l add hl,de ex de,hl call YThrust ;Y acceleration due to slope ld d,b ld e,c ld h,d ld l,e sra h rr l add hl,de ex de,hl call XThrust ;X acceleration due to slope jr OnGround InFlight: ld de,-GRAVITY call HThrust OnGround: call MoveEnemy ld a,0 FlashFlag =$-1 or a jr z,DontFlash ld hl,FlashTimer inc (hl) ld a,(hl) cp 8 jr c,DontFlash ld (hl),0 ld hl,BallCentre ld a,(hl) xor 64 ld (hl),a #ifdef GREY inc hl inc hl ld a,(hl) xor 64 ld (hl),a #endif DontFlash: call CheckDirectionKeys push hl call XThrust pop de call YThrust ld hl,(BallH) ld de,(HVelocity) add hl,de ld (BallH),hl call GetBallPlatformHeight push hl push de ld de,(BallH) or a sbc hl,de add hl,hl pop de pop hl jr c,NoHBounce ld de,(HVelocity) ld (BallH),hl sbc hl,hl sbc hl,de ld de,10h sbc hl,de jr nc,NotLanded sbc hl,hl NotLanded: ld a,BOUNCINESS call Multiply16 ld (HVelocity),hl NoHBounce: ld hl,(BallX) ld a,h ld de,(XVelocity) add hl,de ld (BallX),hl ; ld de,0 ; ld bc,BOUNCERADIUS ; add hl,bc xor h cp 16 ; jr nc,XBounce ; xor h ; ld de,0FFFh ; ld bc,-BOUNCERADIUS*2 ; add hl,bc ; xor h ; cp 16 jr c,NoXBounce XBounce: ; ld a,h ; and 0F0h ; or d ; ld d,a ; ld hl,(BallY) ; call GetPlatformHeight call GetBallPlatformHeight push hl ex de,hl ld hl,(BallH) ld bc,STEPSIZE add hl,bc or a sbc hl,de add hl,hl pop hl jr nc,NoXBounce or a ld de,(XVelocity) sbc hl,hl sbc hl,de ld (XVelocity),hl ld de,(BallX) add hl,de ld (BallX),hl NoXBounce: ld hl,(BallY) ld a,h ld de,(YVelocity) add hl,de ld (BallY),hl ; ld bc,BOUNCERADIUS ; ld de,0 ; add hl,bc xor h cp 16 ; jr nc,YBounce ; ld de,0FFFh ; xor h ; ld bc,-BOUNCERADIUS*2 ; add hl,bc ; xor h ; cp 16 jr c,NoYBounce YBounce: ; ld a,h ; and 0F0h ; or d ; ld h,a ; ld l,e ; ld de,(BallX) call GetBallPlatformHeight push hl ex de,hl ld hl,(BallH) ld bc,STEPSIZE add hl,bc or a sbc hl,de add hl,hl pop hl jr nc,NoYBounce or a ld de,(YVelocity) sbc hl,hl sbc hl,de ld (YVelocity),hl ld de,(BallY) add hl,de ld (BallY),hl NoYBounce: ld hl,TimeLeftTicker dec (hl) jr nz,NotDecTime ld (hl),4 ld hl,(TimeLeft) dec hl ld (TimeLeft),hl push hl ld de,SCRWID-13 ld b,3 call vputHL_de pop hl ld a,h or l jp z,Die NotDecTime: ld hl,timer ld a,(hl) sub GAMESPEED jr c,NotCatchupFrame ;don't render this frame if game is slowing down ld (hl),a jp PlayLoop NotCatchupFrame: call LoadBall call CalcSpriteMask call HideBall call LoadEnemy call nz,RestoreBackground call LoadEnemy call nz,PutSprite call PutBall ld a,GAMESPEED call Delay jp PlayLoop Die: call HideBall ld a,(GameMode) or a jr z,NotChallengeLives ld hl,LivesLeft dec (hl) jr z,GameOver NotChallengeLives: jp StartLife GreyBar: #ifdef GREY ld hl,(greybuffer) ld de,24*(SCRWID>>3) add hl,de ld d,h ld e,l inc de ld bc,16*(SCRWID>>3)-1 ld (hl),255 ldir #endif ld hl,24*(SCRWID>>3)+screenmem ld de,24*(SCRWID>>3)+1+screenmem ld bc,16*(SCRWID>>3)-1 ld (hl),0 ldir ret InvalidKeys .db K_EXIT,K_MORE,K_ALPHA,K_DEL,K_PLUS,K_MINUS,K_CLEAR .db K_F1,K_F2,K_F3,K_F4,K_F5 InvalidKeyCount =$-InvalidKeys GetCustomKey: push hl push de #ifdef BUFSCR call bufcpy #endif DoGetCustom: call WaitForKey ld hl,InvalidKeys ld bc,InvalidKeyCount cpir jr z,DoGetCustom push af ld a,'O' call _vputmap ld a,'K' call _vputmap #ifdef BUFSCR call bufcpy #endif pop af pop de pop hl ret WaitForKey: call GET_KEY Dowait: call GET_KEY or a jr z,Dowait ret Completed: ld a,(LivesLeft) ld de,100 ld hl,(Score) or a jr z,NoLivesBonus Bonus: add hl,de dec a jr nz,Bonus NoLivesBonus: ld (Score),hl call GreyBar ld hl,CompletedMsg ld de,1D00h+(SCRWID/2)-30 jr CheckScore GameOver: call GreyBar ld hl,GameOverMsg ld de,1D00h+(SCRWID/2)-20 CheckScore: call _vputs_de #ifdef BUFSCR call bufcpy #endif call WaitForKey ld hl,Highscores+10 ld b,3 CheckScores: ld e,(hl) inc hl ld d,(hl) inc hl push hl ld hl,(Score) inc de or a sbc hl,de pop hl jr nc,NewHigh ld de,10 add hl,de djnz CheckScores ViewScores: call ShowScores jr DoneHighscores NewHigh: ld de,-12 add hl,de push bc push hl ld a,b dec a jr z,DontShiftHighscores ld hl,Highscores+23 ld de,Highscores+35 ld c,a add a,a add a,c add a,a add a,a ld c,a ld b,0 lddr DontShiftHighscores: pop de ld h,d ld l,e inc de push hl ld (hl),' ' ld bc,10 ldir ld de,(Score) ld (hl),e inc hl ld (hl),d call ShowScores ld hl,NewScoreMsg ld de,3700h+(SCRWID/2)-28 call _vputs_de pop de pop bc ld a,3 sub b ld b,a add a,a add a,b add a,a add a,33 ld h,a ld l,(SCRWID/2)-37 ld a,10 ld b,1 call GetString call SaveWorldInfo DoneHighscores: ld hl,DoneScoresMsg ld de,3700h+(SCRWID/2)-36 call _vputs_de #ifdef BUFSCR call bufcpy #endif call WaitForKey jp Restart ShowScores: ld hl,0 ld (_penCol),hl ld hl,NameLength ld b,(hl) inc hl call _vputsn ld a,SCRWID ld hl,_penCol sub (hl) srl a push af call PutTitleBox pop af ld l,a ld h,18 ld (_penCol),hl ld hl,NameLength ld b,(hl) inc hl call _vputsn ld hl,HighscoresMsg ld de,1800h+(SCRWID/2)-18 call _vputs_de ld a,'1' ld d,33 ld hl,Highscores PutHighscores: push af push de push hl ex de,hl ld l,(SCRWID/2)-44 ld (_penCol),hl call _vputmap ld a,'.' call _vputmap ld a,' ' call _vputmap pop hl ld b,10 call _vputsn ld e,(hl) inc hl ld d,(hl) inc hl push hl ex de,hl ld a,(SCRWID/2)+24 ld (_penCol),a ld b,5 call vputHL pop hl pop af add a,6 ld d,a pop af inc a cp '4' jr nz,PutHighscores ret GetString: ld (MaxLength),a ld c,a ld a,b ld (MinLength),a ld (EntryPos),hl ld (StringAddr),de ld h,d ld l,e inc de ld (hl),32 ld b,0 dec bc ldir NameLoop: PutCur: call WriteString xor a ld (timer),a ld a,'|' call _vputmap BlankCursor: push bc ld b,6 call vblank #ifdef BUFSCR call bufcpy #endif pop bc GetNameKey: ld a,(timer) cp 50 jr nc,PutCur cp 25 jr nz,NotFlashCur call WriteString jr BlankCursor NotFlashCur: push bc call GET_KEY pop bc or a jr z,GetNameKey ld c,a ld a,b cp 8 MaxLength =$-1 jr z,NoAlphaKey ld a,c cp K_SIGN jr nz,NotSpace ld a,' ' jr GotAlpha NotSpace: push bc ld bc,26 ld hl,AlphaKeys cpir ld d,c pop bc jr nz,NoAlphaKey ld a,90 sub d dec b inc b jr z,FirstLetter add a,32 Capitalise =$-1 FirstLetter: GotAlpha: ld e,b inc b StoreChar: ld hl,(StringAddr) ld d,0 add hl,de ld (hl),a jr NameLoop NoAlphaKey: ld a,c cp K_DEL jr nz,NotDel ld a,b or a jr z,NotDel dec b ld a,' ' ld e,b jr StoreChar NotDel: cp K_ENTER jr nz,GetNameKey ld a,b cp 0 MinLength =$-1 jr c,GetNameKey call WriteString push bc ld b,6 call vblank #ifdef BUFSCR call bufcpy #endif pop bc ret WriteString: push bc ld hl,0 EntryPos =$-2 ld (_penCol),hl ld hl,0 StringAddr =$-2 ld a,b or a call nz,_vputsn #ifdef BUFSCR call bufcpy #endif pop bc ret Exit: call UninstallInt #ifdef TI85 ld hl,8860h ld de,GRAPH_MEM+400h ld bc,TEXT_MEM2-GRAPH_MEM-400h ldir #endif #ifdef TI82 ld hl,TEXT_MEM ld de,INTTABLE ld bc,81h ldir ld hl,TEXT_MEM2 ld c,80h ldir #endif #ifndef TI82 #ifndef TI83 ld a,(CONTRAST) out (2),a #endif #endif call _clrScrn #ifdef BUFSCR call grbufclr res 7,(iy+20) #endif ld hl,0 ld (_curRow),hl #ifdef TI85 ld hl,8C40h ld (hl),1 jp DeRelocate #else #ifdef RELOC #ifdef TI82 ;#ifdef EDITOR call RecreateTemp ;#endif ld hl,(8D5Dh) ld de,302Eh ; .0 from ash 3.0 or a sbc hl,de jp z,DeRelocate #endif ;#ifdef EDITOR jp Terminate ;#endif #endif ret #endif Delay: ld hl,timer cp (hl) jr nc,Delay sub (hl) neg ld (hl),a ret ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Enemy Movement ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß InitEnemy: ld hl,0 ld (EnemyH),hl ld (EnemyVH),hl ld (WaypointDist),hl ld hl,NextWaypoint xor a ld (hl),a inc a ld (EnemyFrame),a call SetNextWaypoint MoveEnemy: ld hl,EnemyFrame dec (hl) ret nz ld (hl),ENEMYFRAMES ld a,(WaypointCount) or a ret z ; ld hl,(EnemyH) ; ld de,0 ; call vputHLhex ld hl,(EnemyVH) ld de,-GRAVITY add hl,de ld (EnemyVH),hl ld de,(EnemyH) add hl,de ld (EnemyH),hl call GetEnemyCoords ld (EnemyY),hl ld (EnemyX),de ld a,(WaypointCount) rla jr nc,NotEnemyJewel ld (JewelY),hl ld (JewelX),de NotEnemyJewel: call GetPlatformHeight push hl push de ld de,(EnemyH) or a sbc hl,de add hl,hl pop de pop hl jr c,NoEnemyHBounce ld de,(EnemyVH) ld (EnemyH),hl sbc hl,hl sbc hl,de ld de,10h sbc hl,de jr nc,EnemyNotLanded ld hl,0 EnemyNotLanded: ld a,BOUNCINESS call Multiply16 ld (EnemyVH),hl NoEnemyHBounce: ld a,(WaypointCount) rla jr nc,NotEnemyJewelH ld hl,(EnemyH) ld (JewelH),hl NotEnemyJewelH: call LoadEnemy call CalcSpriteMask ld hl,WaypointPos ld a,(WaypointDist) inc (hl) cp (hl) ret nz ld (hl),0 SetNextWaypoint: ld a,(NextWaypoint) call GetWaypointCoords ld (WaypointXY),de push de inc a call GetWaypointCoords ld (NextWaypoint),a pop hl ld a,e sub l rra ld (WaypointXDist),a push af ld a,d sub h rra ld (WaypointYDist),a call SquareA pop af push hl call SquareA pop de add hl,de call SqrtHL ; ld hl,(WaypointXY) ; ld a,l ; rrca ; rr h ; rra ; and 0C0h ; srl a ; add a,40h ex de,hl ; add hl,hl ; call Multiply16 ld a,l srl a ld (WaypointDist),a ret GetWaypointCoords: ld b,a ld a,(WaypointCount) and 127 sub b jr z,LastWaypoint ld a,b LastWaypoint: ld l,a ld h,0 add hl,hl ld de,Waypoints add hl,de ld e,(hl) inc hl ld d,(hl) ret LoadEnemy: ld a,(WaypointCount) or a ret z ld ix,Enemy ld hl,EnemyData rlca ret nc ld ix,Jewel ld hl,JewelData ret GetEnemyCoords: ld a,(WaypointXDist) ld bc,(WaypointX) call GetEnemyCoord push hl ld a,(WaypointYDist) ld bc,(WaypointY) call GetEnemyCoord pop de ld bc,(EnemyH) ret GetEnemyCoord: push bc ld h,a ld l,0 ld a,(WaypointPos) call Multiply16 ld a,h rla ld a,(WaypointDist) jr c,NegEnemyCoord call _divHLbyA jr GotEnemyCoord NegEnemyCoord: ex de,hl or a sbc hl,hl sbc hl,de call _divHLbyA ex de,hl or a sbc hl,hl sbc hl,de GotEnemyCoord: pop bc ld a,l ; add a,a add a,a add a,c ld h,a ret PutTitleBox: call ClearScreen ld hl,screenmem+(SCRWID>>4)-6 ld de,screenmem+(SCRWID<<3)-(SCRWID>>4)-6 ld b,12 ld a,255 DrawBorder: ld (hl),a ld (de),a inc hl inc de djnz DrawBorder ld b,62 DrawSides: #if SCRWID==128 ld de,4 add hl,de #endif ld (hl),128 ld de,11 add hl,de ld (hl),1 inc hl djnz DrawSides #ifdef GREY ld hl,screenmem ld de,(greybuffer) ld bc,SCRWID<<3 ldir #endif ld hl,Logo ld de,(5*(SCRWID>>4))-4+screenmem #ifdef GREY ld b,2 GreyLogo: push bc #endif ld a,13 PutLogo: ld bc,8 ldir ld bc,(SCRWID>>3)-8 ex de,hl add hl,bc ex de,hl dec a jr nz,PutLogo #ifdef GREY push hl ld hl,(greybuffer) ld de,(5*(SCRWID>>4))-4 add hl,de ex de,hl pop hl pop bc djnz GreyLogo #endif ret ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Maths stuff ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß SqrtHL: ld b,15 ld de,0FFFFh sqrtwloop: push bc push hl call DivHLbyDE add hl,bc rr h rr l ex de,hl pop hl pop bc djnz sqrtwloop ret DivHLbyDE: ld b,d ld c,e ld de,0 ld a,16 divwloop: add hl,hl ex de,hl adc hl,hl sbc hl,bc jr nc,dosub add hl,bc dec e dosub: ex de,hl inc l dec a jr nz,divwloop ret divXYby16: ld a,h call divAby16 ld h,a ld a,l call divAby16 ld l,a ret divAby16: cp 0D0h ccf rra sra a sra a sra a ret divHLby16: ld a,h cp 0D0h ccf rr h rr l sra h rr l sra h rr l sra h rr l ret SquareA: ld h,a ld l,0 cp 128 jr c,Multiply16 neg ld h,a Multiply16: ex de,hl or a sbc hl,hl ld c,0 bit 7,d jr z,notnegmult push hl sbc hl,de ex de,hl inc c pop hl notnegmult: ld b,8 domult16: add hl,hl rla jr nc,noadd16 add hl,de adc a,0 noadd16: djnz domult16 ld l,h ld h,a dec c ret nz ex de,hl or a sbc hl,hl sbc hl,de ret ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Misc Physics and Level Routines ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß GetPlatformAddr: ld l,d call divXYby16 GetPlatformHLAddr: ld a,h add a,a add a,h add a,a add a,a sub h add a,l push de ld e,a ld d,0 ld ix,LevelSpace add ix,de pop de ld a,l cp 10 jr nc,BadPlatAddr ld a,h cp 10 BadPlatAddr: ld a,(ix) ret CheckSpriteCollision: inc de ld a,(de) add a,RADIUS/2 inc hl sub (hl) cp RADIUS call c,CheckXYCollide ret nc CheckXYCollide: inc de inc de ld a,(de) add a,RADIUS*2 ;ball radius + jewel radius inc hl inc hl sub (hl) cp RADIUS*4 ret #if 0 GetOverlapSquares: ld a,h and 15 cp 16-BALLRADIUS jr c,NotRoundUp ld a,h or 15 inc a ld h,a scf ret NotRoundUp: cp BALLRADIUS ret nc ld a,h and 240 dec a ld h,a scf ret #endif GetBallPlatformHeight: ld hl,(BallY) ld de,(BallX) #if 0 GetTallestPlatformHeight: call GetPlatformHeight push hl ld hl,(TempY) ld de,(TempX) call GetOverlapSquares jr nc,NoYOverlap push hl call GetPlatformHeight pop de pop bc push hl or a sbc hl,bc jr nc,GotTallestFromY pop hl push bc GotTallestFromY: ld hl,(TempX) call GetOverlapSquares jr nc,NoXYOverlap ex de,hl call GetPlatformHeight NoYOverlap: call GetOverlapSquares #endif GetPlatformHeight: ld (TempX),de ld (TempY),hl call GetPlatformAddr jr nc,ZeroHeightPlatform rra ZeroHeightPlatform: ld hl,0E000h ld d,l ld e,l ld b,l ld c,l ret nc rra jr nc,NotOnFlat ld a,(ix) GetHeightWord: rra rra and 63 ld h,a ld l,2 srl h rr l srl h rr l ret NotOnFlat: ld hl,(TempX) ld b,(ix+12) ld c,(ix+11) call Interpolate push hl ld hl,(TempX) ld b,(ix+1) ld c,(ix) call Interpolate pop bc ld c,h ld hl,(TempY) call Interpolate2 sra h rr l sra h rr l sra h rr l push hl ld b,(ix+12) ld c,(ix) call FixBC sub b rra ld d,a ld b,(ix+11) ld c,(ix+1) call FixBC sub b rra ld b,a add a,d ld l,a rla sbc a,a ld h,a add hl,hl ld a,d ex de,hl sub b ld c,a rla sbc a,a sla c rla ld b,a pop hl scf ret FixBC: ld a,b rra and 07Eh ld b,a ld a,c rra and 07Eh ld c,a ret Interpolate: call FixBC Interpolate2: add hl,hl add hl,hl add hl,hl add hl,hl Multiply: ld a,b sub c Multiply8: ;hl=a*h+c*256 ld e,a rla sbc a,a ld d,a ld a,h ld b,8 or a sbc hl,hl domult: add hl,hl add a,a jr nc,noadd add hl,de noadd: djnz domult ld a,c add a,h ld h,a ret XThrust: ld hl,(XVelocity) add hl,de ld (XVelocity),hl ret YThrust: ld hl,(YVelocity) add hl,de ld (YVelocity),hl ret HThrust: ld hl,(HVelocity) add hl,de ld (HVelocity),hl ret ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Keypad routines ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß _readkeypad: out (1),a in a,(1) push af ld a,255 out (1),a pop af ret PollKey: push bc dec a ld b,a srl b srl b srl b and 7 ld c,a ld a,0FFh out (1),a inc b ld a,07Fh GetKeyMask: rlca djnz GetKeyMask out (1),a in a,(1) ld b,c inc b GetKeyBit: rra djnz GetKeyBit pop bc ret CheckDirectionKeys: #ifdef DEMO ld ix,(DemoPointer) #endif ld de,0 ;y ld b,e ld c,e ld a,(KeySW) call PollKey jr c,NotDown IsDown: inc b NotDown: #ifdef DEMO push af ld hl,DownKeyState call RecordKeyState pop af #endif djnz NotNegYThrust ld de,-THRUST NotNegYThrust: ld bc,40h ld a,(KeyNE) call PollKey jr c,NotRight inc b NotRight: #ifdef DEMO ld hl,RightKeyState call RecordKeyState #endif djnz NotPosYThrust ld hl,THRUST add hl,de ex de,hl NotPosYThrust: push de ld bc,80h ld d,b ld e,b ld a,(KeyNW) call PollKey jr c,Not2ND inc b Not2ND: #ifdef DEMO ld hl,SecondKeyState call RecordKeyState #endif djnz NotNegXThrust ld de,-THRUST NotNegXThrust: ld bc,0C0h ld a,(KeySE) call PollKey jr c,NotXVAR inc b NotXVAR: #ifdef DEMO ld hl,XVARKeyState call RecordKeyState #endif djnz NotPosXThrust ld hl,THRUST add hl,de ex de,hl NotPosXThrust: pop hl #ifdef DEMO ld (DemoPointer),ix #endif ret #ifdef DEMO RecordKeyState: ld a,(DemoState) or a ret z dec a jr z,RecordingDemo PlayingDemo: ld a,(hl) dec (hl) dec hl ld b,(hl) or a ret nz push ix FindNextByte: ld a,(ix) inc ix ld b,a and 0C0h cp c jr nz,FindNextByte pop ix ld a,b and 63 ld (hl),a cp 63 ret z ; MOOOOOOOOOOOOOOOOO RecordingDemo: inc (hl) ld a,(hl) cp 63 call z,RecordLimit inc hl ld a,(hl) cp b ret z ld (hl),b dec hl ld a,(hl) RecordLimit: ld (hl),0 or c ld (ix),a inc ix ret #endif ClearScreen: #ifdef BUFSCR call grbufclr #else call _clrLCD #endif #ifdef GREY ld hl,screenmem ld de,(greybuffer) ld bc,SCRWID<<3 ldir #endif jp InitClipping ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ World Drawing Routines ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß DrawLevel: ; call HideBall ; call LoadEnemy ; call RestoreBackground ; ld hl,JewelData ; ld ix,Jewel ; call RestoreBackground #ifdef EDITOR ; ld hl,CursorData ; ld ix,Cursor ; call RestoreBackground #endif xor a ld (EnemyData+7),a ld (JewelData+7),a ld (BallData+7),a ld (CursorData+7),a ld (EnemyData+25),a ld (JewelData+25),a ld (BallData+25),a ld (CursorData+25),a call ClearScreen call InitClipping ld de,0600h ld hl,LevelMsg call _vputs_de ld a,(Level) inc a call vputA ld a,(Linked) cp 2 jr nz,NotSlaveLoadLevel call ReceivePacket jr LoadedLevel NotSlaveLoadLevel: push af call LoadLevel pop af dec a jr nz,LoadedLevel ld a,(WaypointCount) add a,a add a,LEVELSIZE ld b,a ld a,LINK_LEVEL ld hl,LevelSpace call SendPacketHL LoadedLevel: call WriteLevelName RedrawTiles: ld ix,LevelSpace+99 ld hl,((250-(19*YSCL))*256)-XSCL+SCRWID ld c,10 RedrawLoopY: ld b,10 RedrawLoopX: push bc call DrawBlock ld de,YSCL*256+XSCL add hl,de inc ix pop bc djnz RedrawLoopX ld de,YSCL*256-XSCL-((YSCL*256+XSCL)*10) add hl,de ld de,-21 add ix,de dec c jr nz,RedrawLoopY ret WriteLevelName: ld hl,0 ld (_penCol),hl ld hl,LevelName ld b,6 jp _vputsn #if 0 CalcLevelAddr: ld d,0 ld h,a ld l,d srl h rr l add a,a add a,a add a,a add a,a rl d ld e,a add hl,de ld a,(NameLength) add a,5 ld e,a ld d,0 add hl,de ret #endif MulXscl: push de ld d,h ld e,l #if XSCL==12 add hl,de add hl,de add hl,hl #endif #if XSCL==9 add hl,hl add hl,hl add hl,hl add hl,de rr h rr l #endif #if XSCL==10 add hl,hl add hl,hl add hl,de #endif pop de ret MulYscl: push de ld d,h ld e,l add hl,hl add hl,hl add hl,de rr h rr l pop de ret GetBlockHeights: ld de,YSCL*256+(256-YSCL) ld l,0 ld a,(ix) ld h,a srl h srl h rra ret nc rra push af ld l,h ld a,h sub YSCL ld e,a add a,2*YSCL ld d,a pop af ret c ld a,(ix+11) call div16 add a,YSCL ld d,a ld a,(ix+1) call div16 sub YSCL ld e,a ld a,(ix+12) call div16 ld l,a scf ret DrawBlock: push hl ld (blockxy),hl ld a,l add a,8 srl a ld hl,(clipleft) ld de,404h add hl,de cp h jr nc,DontDrawBlock add a,XSCL+1 cp l jr c,DontDrawBlock call GetBlockHeights jr c,DoDrawBlock DontDrawBlock: pop hl ret DoDrawBlock: ; D ; / \ ; H< >L ; | \ / | ; | E | ; | | | ld a,h sub d call GetDelta ld (TopDelta),bc ld a,h sub e call GetDelta ld (MidDelta),bc push ix push hl ld a,d sub l call GetDelta push bc ld a,e sub l call GetDelta push bc ld a,(blocky) ld d,a sub h ld h,a ld l,0 #if 0 ld a,(cliptop) add a,a add a,a cp h jr c,NotClipped pop hl pop hl pop hl pop ix DontDrawBlock: pop hl or a ret NotClipped: #endif ld (TopY),hl ld (MidY),hl ld h,d ld (BotY),hl ld c,2 RightHalf: ld b,XSCL/2 LeftHalf: push bc ld a,(blockx) srl a ld hl,clipleft cp (hl) jr c,ClipCol inc hl cp (hl) jr nc,ClipCol ld d,0FFh #ifdef GREY rl c jr nc,NotGreySide ld d,055h NotGreySide: #endif ld a,(MidY+1) add a,4 ld c,a ld a,(BotY+1) call DrawVLine ld a,(TopY+1) ld c,a #ifdef GREY ld d,055h #else ld d,0FFh #endif call DrawVLine ld a,(TopY+1) add a,4 ld c,a ld a,(MidY+1) #ifdef GREY ld d,0AAh #else ld d,0 #endif call DrawVLine ClipCol: ld hl,(TopY) ld de,(TopDelta) add hl,de ld (TopY),hl ld hl,(MidY) ld de,(MidDelta) add hl,de ld (MidY),hl pop bc ld hl,BotY+1 ld a,(hl) add a,c ld (hl),a ld hl,blockx inc (hl) inc (hl) djnz LeftHalf ld a,c ld c,-2 cp c jr z,DoneRightHalf pop hl ld (MidDelta),hl pop hl ld (TopDelta),hl jr RightHalf DoneRightHalf: pop bc ld a,(blockx) srl a ld hl,clipleft cp (hl) jr c,ClipLast inc hl cp (hl) jr nc,ClipLast ld a,(blocky) sub c ld c,a ld a,(BotY+1) #ifdef GREY ld d,055h #else ld d,0FFh #endif call DrawVLine ClipLast: pop ix scf pop hl ret GetDelta: bit 7,a jr z,PositiveDelta neg call PositiveDelta push hl or a sbc hl,hl sbc hl,bc jr GotDelta PositiveDelta: push hl ld h,a ld l,0 add hl,hl ld a,XSCL call _divHLbyA GotDelta: ex (sp),hl pop bc ret div16: rra rra and 63 ret DrawVLine: srl a srl c inc a inc c srl a srl c ld hl,cliptop cp (hl) ret c inc hl cp (hl) jr c,DontClipBottom ld a,(hl) DontClipBottom: ld b,a ld a,c dec a cp (hl) ret nc inc a dec hl cp (hl) jr nc,DontClipTop ld c,(hl) DontClipTop: ld a,b sub c ret c inc a #ifdef GREY add a,a #endif ld h,a ld a,(blockx) srl a ; cp SCRWID ; ret nc ld b,a ld a,(MaskingFlag) or a jr z,NormalVLine push hl ld hl,clipleft ld a,b sub (hl) ld e,a ld d,0 ld hl,PixelOffsets add hl,de ld a,(cliptop) neg add a,c #ifdef GREY add a,a #endif ld e,a ld d,0 ld a,(hl) cpl ld hl,(MaskAddr) add hl,de pop bc ld c,a VLineMaskLoop: ld a,(hl) and c ld (hl),a inc hl djnz VLineMaskLoop ret NormalVLine: push de push hl call FindPixel pop bc ld c,a pop de cpl ld e,a #ifdef GREY push ix #endif VLineLoop: ld a,(hl) and e rrc d jr nc,VL0 or c VL0: ld (hl),a push de ld de,SCRWID>>3 add hl,de pop de #ifdef GREY ex (sp),hl #endif djnz VLineLoop NoVLine: #ifdef GREY pop hl #endif ret PixelOffsets: .db 128,64,32,16,8,4,2,1 FlipPixels: inc b call FlipPixel dec b inc c call FlipPixel dec c dec b call FlipPixel inc b dec c call FlipPixel inc c ret FlipPixel: push af push bc push de call FindPixel jr c,BadPixel ld b,a xor (hl) ld (hl),a #ifdef GREY ld a,b xor (ix) ld (ix),a #endif BadPixel: pop de pop bc pop af ret FindPixel: ld a,c cp 64 ccf ret c ld a,b cp 128 ccf ret c and 7 ld hl,PixelOffsets ld e,a ld d,0 add hl,de ld a,c add a,a #if SCRWID==96 add a,c #endif add a,a rl d add a,a rl d #if SCRWID==128 add a,a rl d #endif srl b srl b srl b add a,b ld e,a ld a,d adc a,0 ld d,a ld a,(hl) ld hl,screenmem add hl,de #ifdef GREY ld ix,(greybuffer) add ix,de #endif ret ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Interrupt + Greyscale Routines ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß #ifndef TI86 InstallInt: im 1 ld hl,INTTABLE ld de,INTTABLE+1 ld (hl),INTADDR/256 ld bc,256 ldir #ifdef TI85 ld hl,(PROGRAM_ADDR) ld de,RelocRoutines-StartAddr add hl,de #else ld hl,RelocRoutines #endif ld de,INTADDR-(IHandler-RelocRoutines) ld bc,RelocRoutinesSize ldir #ifdef GREY #ifdef TI85 ld hl,(8BE5h) dec hl dec hl ld a,h sub 4 ld h,a ld l,0 ld (greybuffer),hl sub 0C0h ret c ld de,(8BE1h) sbc hl,de ret c add hl,de ld (greypage),a ld d,h ld e,l inc de ld (hl),0 ld bc,3FFh ldir #else ld hl,GREYMEM ld (greybuffer),hl #endif #endif #ifdef TI85 or a ret #endif ReInstallInt: #ifdef SAFEGREY call SwapGrey #endif ld a,INTTABLE/256 ld i,a im 2 or a ret UninstallInt: im 1 #ifndef TI83 ld de,RelocRoutines ld hl,INTADDR-(IHandler-RelocRoutines) ld bc,RelocRoutinesSize ldir #endif #ifdef GREY #ifdef TI85 ld a,3Ch out (0),a #ifdef SAFEGREY call SwapGrey #endif #endif #endif ret #ifdef SAFEGREY SwapGrey: ld hl,(greybuffer) ld de,GRAPH_MEM ld bc,400h jp SwapBytes #endif #else InstallInt: ld hl,GreySpace ld (greybuffer),hl ld a,(GreySpace>>8)-0C0h ld (greypage),a res 2,(iy+23h) ld hl,IHandler ld de,0D2FEh push de ld bc,IHandlerEnd-IHandler ldir ld de,40 pop hl ld a,(hl) dec hl push hl ld b,5 CalcChecksum: add hl,de add a,(hl) djnz CalcChecksum pop hl ld (hl),a set 2,(iy+23h) or a ret UninstallInt: res 2,(iy+23h) ld a,3Ch out (0),a ret #endif #ifndef TI83 #ifndef TI86 Workspace: Workspace2 =$+109 #endif #endif RelocRoutines: #ifdef TI82 DeleteTempUnadj: call DeRelocate ROM_CALL(3620h-1Ah) jr RelocateLoc RecreateTempUnadj: call DeRelocate ROM_CALL(38EAh-1Ah) RelocateLoc: jp Relocate+adj #endif IHandler: #ifndef TI86 exx ex af,af' #endif ld hl,timer inc (hl) #ifdef GREY in a,(3) bit 1,a jr z,notvbl #ifdef BUFSCR ld hl,greycounter inc (hl) ld a,(hl) cp 3 jr nz,NotReset ld (hl),0 ; jr notvbl NotReset: ld hl,screenmem dec a jr nz,PutGrey1 ld hl,GREYMEM PutGrey1: ld a,5 out (10h),a call lcdwait-IHandler+INTADDR ld c,12 greybufcols: ld a,080h out (10h),a call lcdwait-IHandler+INTADDR ld de,12 ld a,20h+12 sub c out (10h),a call lcdwait-IHandler+INTADDR ld b,64 greybufrows: push af pop af ld a,(hl) add hl,de out (11h),a djnz greybufrows ld de,1-(12*64) add hl,de dec c jr nz,greybufcols #else ld hl,greycounter inc (hl) ld a,(hl) cp 3 ld a,3Ch jr nz,notpage1 ld (hl),0 ld a,(greypage) notpage1: out (0),a #endif notvbl: #endif #ifndef TI86 jp 3Ah #else ret #endif #ifdef BUFSCR #ifdef GREY lcdwait: push af pop af ret #endif #endif IHandlerEnd: #ifdef RELOC adj =INTADDR-IHandler #else adj =0 #endif #ifdef TI82 DeleteTemp =DeleteTempUnadj+adj RecreateTemp =RecreateTempUnadj+adj #endif SaveWorldInfo =$+adj #ifdef RELOC call DeRelocate #endif call FindLevelVar #ifdef TI86 call PageIn #endif ex de,hl ld a,(NameLength) add a,NameLength-WorldInfo+1 ld hl,WorldInfo ld b,0 ld c,a jr DoStoreInfoLoc #ifdef TI83 SearchNextWorld =$+adj call DeRelocate jr ContinueSearch StartWorldSearch =$+adj call DeRelocate FirstWorld: ld hl,VATSTART ChangeWorld: ld a,(hl) and 31 dec hl ld e,(hl) dec hl ld d,(hl) dec hl cp 5 jr z,GotValidVar cp 6 jr z,GotValidVar cp 1 jr z,NotFoundProg cp 13 jr z,NotFoundProg ld a,(NoWorldsFlag) or a jr z,FirstWorld jr Relocate GotValidVar: ld (VATAddr),hl ex de,hl ld (WorldAddr),hl inc hl inc hl ld a,(hl) cp 19h jr nz,NotValidSig inc hl ld a,(hl) sub 91h jr nz,NotValidSig dec hl ld (NoWorldsFlag),a jr StoreWorldInfo NotValidSig: ContinueSearch: ld hl,(VATAddr) NotFoundProg: ld b,(hl) dec hl SkipName: dec hl djnz SkipName jr ChangeWorld #endif #ifdef TI82 SearchNextWorld =$+adj call DeRelocate jr ContinueSearch StartWorldSearch =$+adj call DeRelocate FirstWorld: ld hl,VATSTART ChangeWorld: ld de,(VATEND) inc de or a sbc hl,de jr nc,GotAVar ld a,(NoWorldsFlag) or a jr z,FirstWorld jr Relocate GotAVar: add hl,de ld a,(hl) and 31 dec hl ld b,4 cp 5 jr z,FoundProg cp 6 jr nz,NotFoundProg FoundProg: ld e,(hl) dec hl ld d,(hl) dec hl ld (VATAddr),hl ex de,hl ld (WorldAddr),hl inc hl inc hl ld a,(hl) cp 19h jr nz,NotValidSig inc hl ld a,(hl) sub 91h jr nz,NotValidSig dec hl ld (NoWorldsFlag),a jr StoreWorldInfo NotValidSig: ContinueSearch: ld hl,(VATAddr) ld b,(hl) NotFoundProg: dec hl SkipName: dec hl djnz SkipName jr ChangeWorld #endif #ifdef TI85 SearchNextWorld =$+adj #ifdef RELOC call DeRelocate #endif jr ContinueSearch StartWorldSearch =$+adj #ifdef RELOC call DeRelocate #endif FirstWorld: ld hl,VATSTART ChangeWorld: ld de,(VATEND) inc de or a sbc hl,de jr nc,GotAVar ld a,(NoWorldsFlag) or a jr z,FirstWorld #ifdef RELOC jr Relocate #else ret #endif GotAVar: add hl,de ld a,(hl) and 31 dec hl ld e,(hl) dec hl ld d,(hl) dec hl cp 12 jr nz,NotFoundProg GotValidVar: ld (VATAddr),hl ex de,hl ld (WorldAddr),hl inc hl inc hl ld a,(hl) cp 19h jr nz,NotValidSig inc hl ld a,(hl) sub 91h jr nz,NotValidSig dec hl ld (NoWorldsFlag),a jr StoreWorldInfo NotValidSig: ContinueSearch: ld hl,(VATAddr) NotFoundProg: ld b,(hl) dec hl SkipName: dec hl djnz SkipName jr ChangeWorld #endif #ifdef TI86 StartWorldSearch: ld hl,12 ld (_OP1),hl SearchNextWorld: xor a call 514Bh jr nc,GotNextVar ld a,(NoWorldsFlag) inc a jr nz,StartWorldSearch ret GotNextVar: rst 10h ex de,hl ld a,b ld (WorldAddr),hl ld (WorldAddr+2),a call PageIn inc hl inc hl ld e,(hl) inc hl ld d,(hl) dec hl ex de,hl ld bc,9119h xor a sbc hl,bc jr nz,NotGotWorld ld (NoWorldsFlag),a ex de,hl jr StoreWorldInfo NotGotWorld: call PageOut jr SearchNextWorld #endif #if 0 SearchNextWorld: ld hl,(VATAddr) jr ContinueSearch StartWorldSearch: FirstWorld: ld hl,VATSTART ChangeWorld: ld de,(VATEND) inc de or a sbc hl,de jr nc,GotAVar ld a,(NoWorldsFlag) or a jr z,FirstWorld ret GotAVar: add hl,de call _RAM_PAGE_7 ld a,(hl) and 31 dec hl ld e,(hl) dec hl ld d,(hl) dec hl ld b,(hl) dec hl dec hl cp 12 jr nz,NotFoundProg GotValidVar: push hl ld hl,WorldAddr ld (hl),e inc hl ld (hl),d inc hl ld (hl),b ex de,hl ld a,b call PageIn inc hl inc hl ld a,(hl) cp 19h jr nz,NotValidSig inc hl ld a,(hl) sub 91h jr nz,NotValidSig dec hl pop de ld (NoWorldsFlag),a ld (VATAddr),de jr StoreWorldInfo NotValidSig: pop hl ContinueSearch: call PageOut call _RAM_PAGE_7 NotFoundProg: ld b,(hl) dec hl SkipName: dec hl djnz SkipName jr ChangeWorld #endif LoadLevel =$+adj #ifdef RELOC call DeRelocate #endif call FindLevel #ifdef TI86 call PageIn #endif inc hl ld de,LevelSpace DoStoreInfoLoc: jr DoStoreInfo #ifdef EDITOR #ifndef TI86 InsertMemory =$+adj push af push hl #ifdef RELOC call DeRelocate #endif #ifdef SAFEGREY call UninstallInt #endif pop hl call DoInsertMemory pop af jr nc,NotStoreNewByte ld (hl),a NotStoreNewByte: #ifdef SAFEGREY call ReInstallInt #endif #ifdef RELOC jr Relocate #else ret #endif #endif #endif #ifdef RELOC DeRelocate =$+adj ld a,1 jr DoDeRelocate #endif GetWorldInfo =$+adj #ifdef RELOC call DeRelocate #endif call FindLevelVar #ifdef TI86 call PageIn #endif StoreWorldInfo: ld de,WorldInfo ld bc,WorldInfoLen DoStoreInfo: ldir or a DoneVarStuff: #ifdef TI86 PageOut: push af ld a,13 out (5),a pop af jp _RAM_PAGE_1 #else #ifndef RELOC ret #endif #endif ;TI86 #ifdef RELOC Relocate: xor a DoDeRelocate: push hl push af ld hl,VarName rst 20h #ifdef TI83 call _CHKFINDSYM #endif #ifdef TI82 ROM_CALL(213Eh-1Ah) #endif #ifdef TI85 rst 10h inc de inc de inc de #endif inc de inc de ex de,hl pop bc DoTerminate: ld de,StartAddr sbc hl,de rla add hl,de xor b ld bc,ProgSize rra jr nc,DoReloc add hl,bc ld de,StartAddr+ProgSize-1 ReverseSwapBytes: dec hl ld a,(de) ldd inc hl ld (hl),a ld a,b or c jr nz,ReverseSwapBytes pop hl ret SwapBytes =$+adj push hl DoReloc: ld a,(de) ldi dec hl ld (hl),a inc hl ld a,b or c jr nz,DoReloc pop hl ret Terminate =$+adj call DeRelocate pop hl push hl jr DoTerminate #endif ;RELOC #ifdef EDITOR SaveLevel =$+adj #ifdef RELOC call DeRelocate #endif call FindLevel ld a,(WaypointCount) add a,a add a,LEVELSIZE push af sub c ld l,a sbc a,a ld h,a #ifdef TI86 call PageOut call InsertMemory #else call DoInsertMemory #endif pop af ld (hl),a inc hl ld c,a ld b,0 ex de,hl ld hl,LevelSpace StoreInfoLocal: jr DoStoreInfo #endif ;EDITOR CopyLinkBlock =$+adj #ifdef RELOC push bc push de call DeRelocate pop de pop bc #endif ld hl,(WorldAddr) #ifdef TI86 push de ld a,(WorldAddr+2) call PageIn pop de #endif add hl,de ld de,LinkBuffer DoLinkCopy: #ifdef EDITOR jr StoreInfoLocal #else ldir jr DoneVarStuff #endif SaveLinkBlock =$+adj #ifdef RELOC push bc push de call DeRelocate pop de pop bc #endif ld hl,(WorldAddr) #ifdef TI86 push de ld a,(WorldAddr+2) call PageIn pop de #endif add hl,de ex de,hl ld hl,LinkBuffer+2 jr DoLinkCopy #if 0 ;def EDITOR SwapLevels =$+adj push de push hl #ifdef RELOC call DeRelocate #endif call FindLevelVar ld b,h ld c,l pop hl add hl,bc ex de,hl pop hl add hl,bc ld bc,LEVELSIZE call SwapBytes DoneMoo: jr DoneVarStuff #endif #ifndef TI86 CreateVar =$+adj push hl push de #ifdef RELOC call DeRelocate #endif #ifdef SAFEGREY call UninstallInt #endif pop hl rst 20h pop hl #ifdef TI82 ROM_CALL(23B1h-1Ah) #endif #ifdef TI83 call _CREATESTRNG #endif #ifdef TI85 VROM_CALL(2A1Ch) #endif #ifndef NEWVAT ld (hl),6 ;lock prgm #endif push de #ifdef RELOC call Relocate+adj #endif #ifdef SAFEGREY call ReInstallInt #endif pop de ret #endif #ifdef EDITOR #ifndef TI86 DoInsertMemory =$+adj ld a,h or l jp z,FindLevel push hl call FindLevel ex de,hl ex (sp),hl push hl bit 7,h jr z,IsInsert push de ex de,hl or a sbc hl,hl sbc hl,de ex de,hl pop hl push hl #ifdef TI82 ROM_CALL(25A7h-1Ah) #endif #ifdef TI83 call _deleteMem #endif #ifdef TI85 VROM_CALL(2C46h) #endif pop de jr DoneMemResize IsInsert: #ifdef TI82 ROM_CALL(2272h-1Ah) #endif #ifdef TI83 call _insertMem #endif #ifdef TI85 VROM_CALL(27FAh) #endif DoneMemResize: pop bc pop hl push de ex de,hl or a sbc hl,de ld (WorldAddr),hl ld e,(hl) inc hl ld d,(hl) ex de,hl add hl,bc ex de,hl ld (hl),d dec hl ld (hl),e pop hl ret #else ;TI86 InsertMemory: ld a,h or l jr nz,NotZeroInsert call FindLevel jp PageIn NotZeroInsert: push hl call FindLevel ex de,hl ex (sp),hl push hl bit 7,h jr z,IsInsert push de ex de,hl or a sbc hl,hl sbc hl,de ex de,hl pop hl push af push hl call _deleteMem pop de pop af jr DoneMemResize IsInsert: call _insertMem ;insert bytes DoneMemResize: pop bc pop hl push af push de or a ex de,hl sbc hl,de sbc a,0 ld (WorldAddr),hl ld (WorldAddr+2),a push af push hl call 521Dh ex de,hl add hl,bc ex de,hl pop hl pop af call 5221h pop hl pop af jr PageIn #endif ;TI86 #endif ;EDITOR FindLevel =$+adj call FindLevelVar ld de,40 ld bc,1 push bc ld b,0 Level =$-1+adj inc b inc b SkipToLevel: ex (sp),hl add hl,de inc hl ex (sp),hl add hl,de #ifdef TI86 adc a,0 push hl push af call _GETB_AHL ld e,a pop af pop hl call _inc_ptr_ahl #else ld e,(hl) inc hl #endif djnz SkipToLevel #ifdef TI86 call _dec_ptr_ahl #else dec hl #endif ld c,e pop de ret FindLevelVar =$+adj ld hl,(WorldAddr) #ifdef TI86 ld a,(WorldAddr+2) call _inc_ptr_ahl call _inc_ptr_ahl #else inc hl inc hl #endif ret #ifdef TI85 VertRomCall =$+adj push de ld de,0 RomVerAdj =$-2+adj add hl,de ld (VROMAddr),hl pop de pop hl ex (sp),hl jp 0 VROMAddr =$-2+adj #endif VarName =$+adj #ifndef NEWVAT .db 6,"VERTIGO",0 #else .db 12,7,"vertigo" #endif #ifdef RELOC RelocRoutinesSize =$-RelocRoutines #endif #ifdef TI86 PageIn: call 4633h ;ABS->ASIC ld de,-4000h add hl,de sub d out (5),a inc a out (6),a ret #endif ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Sprite Routines ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß FindWorldPixel: ;hl=y, de=x, bc=h call divHLby16 push hl ex de,hl call divHLby16 push hl or a sbc hl,de call MulYscl ld de,(250-(10*YSCL))<<6 add hl,de sbc hl,bc ld c,h pop de ex (sp),hl add hl,de call MulXscl ld de,(SCRWID-(10*XSCL))<<7 add hl,de ld b,h ;b=x c=y ;hl=x*256 pop de ;de=y*256 scf ret InitBall: ld hl,BallStartX ld e,0 ld d,(hl) ld (BallX),de inc hl ld d,(hl) ld (BallY),de call GetBallPlatformHeight ld a,h cp 0E0h jr nz,NotBadBallHeight ld h,0 NotBadBallHeight: ld (BallH),hl ret PutBall: call LoadBall jp PutSprite GetSpritePos: ld c,(hl) inc hl ld b,(hl) inc hl ld e,(hl) inc hl ld d,(hl) inc hl jp LD_HL_MHL GetSpriteCoords: call GetSpritePos push hl push de call FindWorldPixel ld hl,clipleft ld a,b sub (ix) ld (hl),a rla jr c,SpriteOffScreen ld a,b ld b,(hl) add a,(ix) cp SCRWID jr nc,SpriteOffScreen inc a inc hl ld (hl),a ld h,c ld a,c cp 64 jr nc,SpriteOffScreen sub (ix+1) inc a cp 64 jr nc,SpriteOffScreen ld c,a ld l,a ld (cliptop),hl or 1 .org $-1 SpriteOffScreen: scf pop de pop hl ret ClearMask: ld bc,27 add hl,bc ld (MaskAddr),hl push de ld d,h ld e,l inc de ld (hl),255 ld bc,7 ldir pop de ret CalcSpriteMask: ;hl=spritedata,ix=sprite push hl call GetSpriteCoords jr nc,MaskOnScreen pop hl ret MaskOnScreen: ex (sp),hl call ClearMask pop hl ld a,d and 240 ld d,a ld a,h and 240 ld h,a xor a ld l,a ld e,a ld b,2 push bc push hl ld l,d call divXYby16 ex (sp),hl ld bc,0 call FindWorldPixel add hl,hl ;double x precision ld c,h ex de,hl add hl,hl add hl,hl ;quad y ld b,h push bc ld a,1 ld (MaskingFlag),a jr ContinueRedraw RedrawLoop: ld b,3 RedrawThree: push bc push hl push de call GetPlatformHLAddr jr nc,ContinueRedraw ex de,hl call DrawBlock ContinueRedraw: pop de ld hl,YSCL*256+XSCL add hl,de ex de,hl pop hl inc l pop bc djnz RedrawThree ex de,hl ld bc,YSCL*256-XSCL-((YSCL*256+XSCL)*2) add hl,bc ex de,hl ld a,l inc a dec l dec l cp 13 jr nc,DoneRedraw dec h ld a,h add a,3 cp 13 jr c,RedrawLoop DoneRedraw: InitClipping: xor a ld (MaskingFlag),a ld hl,SCRWID*256 ld (clipleft),hl ld hl,3F00h ld (cliptop),hl ret LoadBall: ld hl,BallData ld ix,Ball ret PutJewel: ld a,(JewelStartX) ld d,a ld e,0 ld (JewelX),de ld a,(JewelStartY) ld h,a ld l,e ld (JewelY),hl call GetPlatformHeight ld a,h cp 0E0h jr nz,NotBadJewelHeight ld h,0 NotBadJewelHeight: ld (JewelH),hl ld b,h ld c,l ld hl,JewelData ld ix,Jewel push hl push ix call CalcSpriteMask pop ix pop hl PutSprite: push ix push hl call GetSpriteCoords jr nc,SpriteOnScreen pop hl pop hl ret SpriteOnScreen: push bc ;bc = pixel coords of sprite push hl push de call GetPlatformHeight ld b,h ld c,l pop de pop hl jr nc,NoShadow call FindWorldPixel call FindPixel pop bc pop ix push ix push bc ld b,(hl) xor b ld (hl),a ld (ix+24),l ld (ix+25),h ld (ix+26),b NoShadow: pop bc ld a,b and 7 inc a ld (rotcount),a call FindPixel ex de,hl pop hl ld bc,6 add hl,bc ld (hl),e inc hl ld (hl),d inc hl ex de,hl ex (sp),hl inc hl ld a,(hl) ex (sp),hl push de push hl #ifdef GREY push ix add a,a push ix #endif DoStore: ldi ldi ld bc,(SCRWID>>3)-2 add hl,bc #ifdef GREY ex (sp),hl #endif dec a jr nz,DoStore #ifdef GREY pop hl pop ix #endif pop de pop hl ld bc,19 add hl,bc ex de,hl ;de -> mask ex (sp),hl ;hl -> sprite ld a,(hl) #ifndef GREY pop ix ;ix -> screen #else add a,a #endif ld b,a PlotSprite: push bc push de inc hl ld a,(de) cpl or (hl) ld b,a inc hl ld a,(de) and (hl) ld c,a ld a,b ld de,0FF00h ld b,0 rotcount =$-1 dec b jr z,NoSprRot RotateSprite: scf rra rr d srl c rr e djnz RotateSprite NoSprRot: and (ix) xor c ld (ix),a ld a,d and (ix+1) xor e ld (ix+1),a ld de,SCRWID>>3 add ix,de pop de inc de pop bc #ifdef GREY ex (sp),ix djnz PlotSprite pop hl #else djnz PlotSprite #endif ret HideJewel: ld hl,JewelData ld ix,Jewel jr RestoreBackground HideBall: call LoadBall RestoreBackground: push hl ld bc,6 add hl,bc ld e,(hl) inc hl ld d,(hl) ld a,d or a jr z,NoBGRestore ld (hl),0 inc hl ld a,(ix+1) #ifdef GREY ld ix,(greybuffer) ld bc,-screenmem add ix,bc add ix,de add a,a push ix #endif DoRestore: ldi ldi ld bc,(SCRWID>>3)-2 ex de,hl add hl,bc #ifdef GREY ex (sp),hl #endif ex de,hl dec a jr nz,DoRestore #ifdef GREY pop hl #endif NoBGRestore: pop hl ld de,24 add hl,de ld e,(hl) inc hl ld d,(hl) ld (hl),0 inc hl dec d inc d ret z ldi ret ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ The level editor ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß CreateWorldVar: ;this is needed by receiveworld as well as editor now #ifdef TI86 push hl rst 10h ccf pop hl ret c push hl call 46E3h pop hl ret c call _CREATESTRNG ld a,b ld (WorldAddr+2),a #else push hl #ifndef NEWVAT ld hl,NewVarName rst 20h call _CHKFINDSYM #else ld hl,NewVarName-1 rst 20h rst 10h #endif ccf pop hl ret c push hl ld a,(NewVarName) #ifdef TI82 ROM_CALL(22C8h-1Ah) #endif #ifdef TI83 call 443Eh #endif #ifdef TI85 VROM_CALL(293Fh) #endif pop hl ret c #ifdef NEWVAT ld de,NewVarName-1 #else ld de,NewVarName #endif call CreateVar #endif ld (WorldAddr),de ld (VATAddr),hl #ifdef TI86 ld hl,_OP1+5 ld de,_OP1+1 ;muah, took a while to realise this was ld bc,8 ;necessary.. which it is if searchnextworld ldir ;is to work without corrupting the screen :) #endif xor a ld (Level),a ld (NoWorldsFlag),a ret #ifdef EDITOR BlockTypes .db "BlkSlpBlkFlt" ;EditMsg .db "Editor",0 StartposModeMsg .db "Start",0 JewelposModeMsg .db "Jewel",0 LandscapeModeMsg .db "Land",0 .db "Flt Slp Blk",0,"Hgt ",1Fh," Hgt ",1Eh,0 MovtpathModeMsg .db "Path",0 .db "Spr Add De|",0,"Prev Next",0 LevelModeMsg .db "Options",0 .db "Name Wld",0,"New Del",0 MemMsg .db "Out of mem!",0 DeleteConfirmMsg .db "Delete level?",0 ClearConfirmMsg .db "Clear level?",0 YesNoMsg .db "Yes",0,"No",0 EditorMsg .db "Press 2nd to edit world:",0 NewWorldMsg .db "or ",MORENAME," for " .db "new world",0 NewWorldNameMsg .db "Enter variable name:",0 NewWorldTitleMsg .db "Enter world name:",0 Editor: ld hl,0 ld (CursorX),hl ld (CursorY),hl ld a,(NoWorldsFlag) or a jr nz,GetVarName call PutTitleBox ld hl,EditorMsg ld de,1C00h+(SCRWID/2)-42 call _vputs_de ld hl,2300h+(SCRWID/2)-40 ld (_penCol),hl ld hl,NameLength ld b,(hl) inc hl call _vputsn ld hl,NewWorldMsg ld de,2D00h+(SCRWID/2)-42 call _vputs_de #ifdef BUFSCR call bufcpy #endif WaitForWorldChoice: call GET_KEY cp K_EXIT jp z,Restart cp K_SECOND jp z,EditWorld cp K_MORE jr nz,WaitForWorldChoice GetVarName: call PutTitleBox ld hl,NewWorldNameMsg ld de,1C00h+(SCRWID/2)-42 call _vputs_de ld hl,2300h+(SCRWID/2)-40 #ifndef NEWVAT xor a ld (Capitalise),a #endif ld a,8 ld b,1 #ifdef TI86 ld de,_OP1+2 #else ld de,NewVarName+1 #endif call GetString #ifndef NEWVAT ld a,32 ld (Capitalise),a #endif ld a,b #ifdef TI86 ld (_OP1+1),a rst 10h #else #ifndef NEWVAT ld hl,NewVarName+1 ld e,a ld d,0 add hl,de ld (hl),0 ld hl,NewVarName ld (hl),a rst 20h call _CHKFINDSYM #else ld hl,NewVarName ld (hl),a dec hl rst 20h rst 10h #endif #endif jr nc,GetVarName call PutTitleBox call InputWorldName ld a,b ld (NameLength),a ld hl,9119h ld (LevelSig),hl ld hl,0 ld (LevelCount),hl ld hl,Highscores ld de,Highscores+1 ld bc,35 ld (hl),32 ldir ld hl,0 ld (Highscores+10),hl ld (Highscores+22),hl ld (Highscores+34),hl add a,41 ld l,a call CreateWorldVar jp c,TotalRestart jp InsertLevel EditWorld: call InitEditScreen LandscapeMode: LandscapeRedraw: call BlankMenuBar ld hl,LandscapeModeMsg ld de,3300h call _vputs_de ld de,3900h call _vputs_de #ifdef BUFSCR ld de,3900h+SCRWID-34 #else ld de,3900h+SCRWID-35 #endif call _vputs_de ld hl,CursorData call ClearMask RedrawCursor: ld hl,(CursorY) ld de,(CursorX) call GetPlatformAddr push ix push af push hl and 3 ld hl,600h+SCRWID-12 ld (_penCol),hl ld hl,BlockTypes ld e,a add a,a add a,e ld e,a ld d,0 add hl,de ld b,3 call _vputsn pop hl push hl ld a,l ld hl,SCRWID-19 call vputAhl pop af ld hl,SCRWID-29 call vputAhl pop af pop ix ld b,a ; jr nc,NotGotPlatHeight srl a jr c,GotPlatHeight ;block is not blank ;NotGotPlatHeight: call CheckIfHeightConnected ld a,0 jr c,GotFlatHeight ld a,b GotFlatHeight: srl a GotPlatHeight: srl a push af ld hl,SCRWID-9 call vputAhl pop hl ld l,0 srl h rr l srl h rr l ld (CursorH),hl ld hl,CursorData ld ix,Cursor call PutSprite #ifdef BUFSCR call bufcpy ;_GRBUFCPY_V #endif EditLoop: ld a,20 call Delay ld hl,FlashTimer inc (hl) ld a,(hl) cp 2 jr c,DontFlashCursor ld (hl),0 ld hl,CursorCentre ld a,(hl) xor 64 ld (hl),a DontFlashCursor: call CheckDirectionKeys add hl,hl sbc a,a rl l adc a,0 add a,a add a,a add a,a add a,a ld hl,CursorY+1 add a,(hl) cp 0B0h jr nc,BadCursorY ld (hl),a BadCursorY: rl e sbc a,a rl e adc a,0 add a,a add a,a add a,a add a,a ld hl,CursorX+1 add a,(hl) cp 0B0h jr nc,BadCursorX ld (hl),a BadCursorX: ld hl,(CursorY) ld de,(CursorX) call GetPlatformAddr ld a,0BFh call _readkeypad rra jp nc,IncreaseHeight rra jp nc,DecreaseHeight call CheckEditorKeys jp c,LandscapeRedraw cp K_MORE jp z,StartposMode cp K_F1+1 jr nc,NotBlockType cp K_F3 jp nc,ChangeBlockType NotBlockType: push af call HideCursor pop af cp K_CLEAR jr nz,NotClearLevel ld hl,ClearConfirmMsg call YesNo call z,ClearLevel jp LandscapeRedraw NotClearLevel: jp RedrawCursor ; call HideCursor ; call HideBall HideCursorJunk: HideCursor: ld hl,CursorData ld ix,Cursor jp RestoreBackground CheckEditorKeys: ld a,0FDh call _readkeypad rra rra jr nc,EditLevelUp rra jr nc,EditLevelDown call GET_KEY cp K_EXIT pop hl jr nz,NotRestart call SaveLevel jp Restart NotRestart: or a jp (hl) EditLevelDown: call SaveLevel ld a,(Level) or a ret z dec a jr EditChangeLevel EditLevelUp: call SaveLevel ld hl,Level inc (hl) ld a,(LevelCount) cp (hl) ld a,(hl) jr nz,NotInsert pop hl jp InsertLevel NotInsert: EditChangeLevel: ld (Level),a ld a,0DFh call _readkeypad rla ; jr nc,MoveLevel InitEditScreen: call DrawLevel ; ld de,0 ; ld hl,EditMsg ; call _vputs_de scf ret #if 0 MoveLevel: ld a,(hl) push af ; call CalcLevelAddr ; ld de,(LevelAddr) ; ld (LevelAddr),hl call SwapLevels pop af ld hl,3914h inc a call vputAhl ld b,4 call vblank scf ret #endif ChangeBlockType: sub K_F3 cp 2 jr nz,NotType2 inc a NotType2: ld b,a ld a,(ix) and 0FCh or b scf jr ChangeBlock IncreaseHeight: ld c,4 jr ChangeHeight DecreaseHeight: ld c,-4 ChangeHeight: ld a,0DFh call _readkeypad rla ld a,c jr nc,NotBigHeight add a,a add a,a NotBigHeight: ld c,a sra a sra a ld b,(ix) srl b srl b add a,b cp 64 jp nc,EditLoop ld a,(ix) add a,c or a ChangeBlock: push af push af push ix call HideCursorJunk pop ix pop bc call GetTallest ld (ix),b pop af push de push af push ix ld hl,1000h ld de,(CursorX) add hl,de ex de,hl ld hl,(CursorY) ld bc,0 call FindWorldPixel pop ix call CheckIfHeightConnected ld d,(XSCL/2) jr c,DontRedrawNextBlock DoRedrawNextBlock: ld d,XSCL DontRedrawNextBlock: ld a,b sub d jr nc,NotNegClipLeft xor a NotNegClipLeft: ld hl,clipleft ld (hl),a pop af ld a,b jr c,ExtraRight bit 0,(ix) jr z,NotExtraRightRedraw bit 1,(ix) jr z,NotExtraRightRedraw ExtraRight: add a,(XSCL/2)+1 cp SCRWID jr c,NotClipRightOver ld a,SCRWID NotClipRightOver: NotExtraRightRedraw: inc hl ld (hl),a call GetTallest pop af ld b,a sub d rla jr c,DgtB ld d,b DgtB: sra d sra d ld a,c sub d sub (YSCL/4)+1 inc hl ld (hl),a inc hl inc c ld (hl),c add a,a add a,a ld c,a ld a,(clipleft) ld b,a add a,a ld (blockx),a ld a,(clipright) sub b ld b,a ld a,(hl) add a,a add a,a BlankBlock: push af push bc ld d,0 call DrawVLine pop bc pop af ld hl,blockx inc (hl) inc (hl) djnz BlankBlock call RedrawTiles jp RedrawCursor EditWorldName: call PutTitleBox call InputWorldName ld a,b push af ld hl,NameLength sub (hl) ld l,a sbc a,a ld h,a ld de,Level ld a,(de) push af ld a,255 ld (de),a or a call InsertMemory #ifdef TI86 call PageOut #endif pop af ld (Level),a pop af ld (NameLength),a call SaveWorldInfo call InitEditScreen jp LevelMode EditLevelName: ld hl,0 push hl ld (_penCol),hl ld b,32 call vblank ld a,6 ld b,1 ld de,LevelName pop hl call GetString jp LevelModeLoop InputWorldName: ld hl,NewWorldTitleMsg ld de,1C00h+(SCRWID/2)-42 call _vputs_de ld a,20 ld b,3 ld hl,2300h+(SCRWID/2)-40 ld de,NameLength+1 jp GetString #if 0 RotateBoard: ld hl,(LevelAddr) ld de,RotateMem ld bc,121 ldir ld ix,RotateMem+10 ld hl,(LevelAddr) ld c,11 RotateY: ld d,0 ld b,11 RotateX: ld a,(ix) and 0FCh ld e,a ld a,(ix-1) and 3 or e ld (hl),a inc hl ld e,11 add ix,de djnz RotateX ld de,-122 add ix,de dec c jr nz,RotateY call DrawLevel jp RedrawCursor #endif CheckIfHeightConnected: ld a,(CursorX+1) or a jr z,NotConnectedX ld a,(ix-1) call CheckConnection ret nc NotConnectedX: ld a,(CursorY+1) cp 1 ret c ld a,(ix-11) call CheckConnection ret nc ld a,(CursorX+1) cp 1 ret c ld a,(ix-12) CheckConnection: srl a ccf ret c srl a ;carry clear if block connected ret GetTallest: push hl call GetBlockHeights ld a,d sub e rla jr nc,DgtE ld d,e DgtE: ld a,d sub h rla jr nc,DgtH ld d,h DgtH: ld a,d sub l rla jr nc,DgtL ld d,l DgtL: pop hl call CheckIfHeightConnected ret c ld a,(ix-1) srl a srl a add a,YSCL ld e,a ld a,(ix-11) srl a srl a sub YSCL cp e jr c,EgtA ld e,a EgtA: ld a,e sub d rla jr c,DgtA2 ld d,e DgtA2: ret StartposMode: call BlankMenuBar ld hl,600h+SCRWID-22 ld (_penCol),hl ld b,12 call vblank ld hl,StartposModeMsg ld de,3300h call _vputs_de call HideCursor DoMoveBall: call InitBall call LoadBall call CalcSpriteMask call HideBall call PutBall ld hl,(BallH) ld bc,(BallStartX) call MoveSprite ld (BallStartX),bc #ifdef BUFSCR call bufcpy ;_GRBUFCPY_V #endif call CheckEditorKeys jr c,StartposMode cp K_MORE jr nz,DoMoveBall JewelposMode: call HideBall ld a,(WaypointCount) rla jr c,MovtpathMode ld hl,JewelposModeMsg ld de,3300h call _vputs_de DoMoveJewel: ; call LoadJewel ; call CalcSpriteMask call HideJewel call PutJewel ld hl,(JewelH) ld bc,(JewelStartX) call MoveSprite ld (JewelStartX),bc #ifdef BUFSCR call bufcpy ;_GRBUFCPY_V #endif call CheckEditorKeys jr c,JewelposMode cp K_MORE jr nz,DoMoveJewel MovtpathMode: call HideJewel call BlankMenuBar ld hl,MovtpathModeMsg ld de,3300h call _vputs_de ld de,3900h call _vputs_de #ifdef BUFSCR ld de,3900h+SCRWID-34 #else ld de,3900h+SCRWID-35 #endif call _vputs_de xor a ld (NextWaypoint),a MovtpathModeLoop: ld a,(WaypointCount) and 7Fh push af jr z,NoWaypointNum ld a,(NextWaypoint) inc a NoWaypointNum: ld hl,0600h+SCRWID-21 call vputAhl ld a,'/' call _vputmap pop af push af call vputA #ifdef BUFSCR call bufcpy #endif pop af jr z,NoWaypointsYet ld a,(NextWaypoint) add a,a ld e,a ld d,0 ld hl,Waypoints add hl,de push hl ld e,d ld d,(hl) inc hl ld h,(hl) ld l,e push hl push de call GetPlatformHeight ld a,h cp 0E0h jr nz,NotBadEnemyHeight ld h,0 NotBadEnemyHeight: ex de,hl call LoadEnemy ld (hl),e inc hl ld (hl),d pop de pop bc push hl inc hl ld (hl),e inc hl ld (hl),d inc hl ld (hl),c inc hl ld (hl),b ld c,d pop hl push bc ld b,(hl) dec hl ld c,(hl) push bc call CalcSpriteMask call LoadEnemy call RestoreBackground call LoadEnemy call PutSprite pop hl pop bc call MoveSprite pop hl ld (hl),c inc hl ld (hl),b NoWaypointsYet: call CheckEditorKeys jp c,MovtpathMode jp z,MovtpathModeLoop ld b,a ld a,(WaypointCount) and 7Fh ld a,b jr z,NoWaypoints cp K_F4 jr nz,NotPrevWaypoint ld hl,NextWaypoint ld a,(hl) or a jr nz,NotOnFirstWaypoint ld a,(WaypointCount) and 7Fh NotOnFirstWaypoint: dec a ld (hl),a jp MovtpathModeLoop NotPrevWaypoint: cp K_F5 jr nz,NotNextWaypoint ld hl,NextWaypoint inc (hl) ld a,(WaypointCount) and 7Fh cp (hl) jr nz,NotOnLastWaypoint ld (hl),0 NotOnLastWaypoint: jp MovtpathModeLoop NotNextWaypoint: NoWaypoints: cp K_F2 jr nz,NotAddWaypoint ld a,(WaypointCount) and 7Fh cp 60 jp z,MovtpathModeLoop ld hl,NextWaypoint or a jr z,NewPath inc (hl) NewPath: sub (hl) add a,a ld c,a ld b,0 ld a,(WaypointCount) add a,a ld e,a ld d,0 ld hl,Waypoints+1 add hl,de ld e,l ld d,h dec hl dec hl ld a,c or a jr z,NoWaypointInsert lddr NoWaypointInsert: inc hl ld (hl),58h inc hl ld (hl),58h ld hl,WaypointCount inc (hl) jp MovtpathModeLoop NotAddWaypoint: cp K_F3 jr nz,NotDeleteWaypoint ld hl,WaypointCount ld a,(hl) and 7Fh jp z,MovtpathModeLoop dec a jr nz,NotDeletedPath call LoadEnemy call nz,RestoreBackground xor a ld (WaypointCount),a jp MovtpathModeLoop NotDeletedPath: dec (hl) ld hl,NextWaypoint cp (hl) jr nz,NotDeletedCurrent dec (hl) jp MovtpathModeLoop NotDeletedCurrent: sub (hl) add a,a ld c,a ld b,0 ld a,(hl) add a,a ld e,a ld d,0 ld hl,Waypoints add hl,de ld e,l ld d,h inc hl inc hl ldir jp MovtpathModeLoop NotDeleteWaypoint: cp K_F1 jr nz,NotChangePathType call LoadEnemy call nz,RestoreBackground ld hl,WaypointCount ld a,(hl) xor 80h ld (hl),a jp MovtpathModeLoop NotChangePathType: cp K_MORE jp nz,MovtpathModeLoop call LoadEnemy call nz,RestoreBackground LevelMode: call BlankMenuBar ld hl,LevelModeMsg ld de,3300h call _vputs_de ld de,3900h call _vputs_de ld de,3900h+SCRWID-30 call _vputs_de ld hl,TimeMsg ld de,SCRWID-32 call _vputs_de WriteTimeLimit: ld a,(TimeLimit) ld hl,0A00h call Multiply16 ld de,SCRWID-13 ld b,3 call vputHL_de #ifdef BUFSCR call bufcpy #endif LevelModeLoop: call CheckEditorKeys jr c,LevelMode jr z,LevelModeLoop ld hl,TimeLimit cp K_DOWN jr nz,NotDecTimeLimit dec (hl) jr z,IncTimeLimit jr WriteTimeLimit NotDecTimeLimit: cp K_UP jr nz,NotIncTimeLimit IncTimeLimit: ld a,(hl) cp 99 jr z,NotIncTimeLimit inc (hl) jr WriteTimeLimit NotIncTimeLimit: cp K_F1 jp z,EditLevelName cp K_F2 jp z,EditWorldName cp K_F4 jp z,InsertLevel cp K_F5 jp z,DeleteLevel cp K_MORE jr nz,LevelModeLoop jp LandscapeMode MoveSprite: push bc add hl,hl add hl,hl push hl ld a,c ld hl,SCRWID-19 call vputAhex ld a,b ld hl,SCRWID-29 call vputAhex pop af ld hl,SCRWID-9 call vputAhl #ifdef BUFSCR call bufcpy #endif ld a,10 call Delay call CheckDirectionKeys ld a,0DFh call _readkeypad ld d,a pop bc add hl,hl sbc a,a rl l adc a,0 bit 7,d jr z,NotBigY add a,a add a,a add a,a NotBigY: add a,b cp 0A0h jr nc,BadSpriteY ld b,a BadSpriteY: rl e sbc a,a rl e adc a,0 rl d jr nc,NotBigX add a,a add a,a add a,a NotBigX: add a,c cp 0A0h jr nc,BadSpriteX ld c,a BadSpriteX: ret YesNo: push hl call BlankJustMenu pop hl ld de,3900h call _vputs_de ld hl,YesNoMsg ld de,3900h+SCRWID-30 call _vputs_de ld de,3900h+SCRWID-12 call _vputs_de #ifdef BUFSCR call bufcpy #endif WaitYesNo: call GET_KEY cp K_F4 ret z cp K_F5 jr nz,WaitYesNo or a ret DeleteLevel: ld a,(LevelCount) dec a jp z,LevelMode ld hl,DeleteConfirmMsg call YesNo jp nz,LevelMode ld hl,LevelCount dec (hl) call SaveWorldInfo ld a,(WaypointCount) add a,a neg add a,-LEVELSIZE-1 ld l,a ld h,-1 or a call InsertMemory #ifdef TI86 call PageOut #endif ld hl,Level ld a,(LevelCount) cp (hl) jr nz,NotDeletedLastLevel dec (hl) NotDeletedLastLevel: call InitEditScreen jp LevelMode InsertLevel: #ifdef TI85 #ifdef GREY ld hl,(greybuffer) ld de,-144 add hl,de or a ld de,(8BE1h) sbc hl,de ret c #endif #endif ld hl,LevelCount inc (hl) call SaveWorldInfo #ifndef TI86 ld a,LEVELSIZE ld hl,LEVELSIZE+1 scf call InsertMemory #else ld hl,LEVELSIZE+1 call InsertMemory ld (hl),LEVELSIZE call PageOut #endif call ClearLevel jp LevelMode ClearLevel: ld hl,LevelSpace ld de,LevelSpace+1 ld (hl),7 ld bc,121 ldir ld (hl),8 inc hl ld (hl),8 inc hl ld (hl),0 inc hl ld (hl),98h inc hl ld (hl),98h inc hl ld (hl),'?' ld d,h ld e,l inc de ld bc,6 ldir ld (hl),30 ;time limit call SaveLevel jp InitEditScreen #endif ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Compressed level support routines ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß #if 0 ;nope, no compressed levels in this version :) ; The level format should be revamped for best compression and the ; two type bits split from the 6 height bits of each level point Decode: ld b,1 DecodeOctet: .db 0DDh ld a,l .db 0DDh or h ret z ld a,(hl) inc hl dec ix djnz NotGetFlags ld b,9 ld c,a jr DecodeOctet NotGetFlags: rr c jr nc,DecodeLZString ld (de),a inc de jr DecodeOctet DecodeLZString: push bc push hl ld l,a scf rr l scf rr l ld h,-1 add hl,de and 3 add a,3 ld b,0 ld c,a ldir pop hl pop bc jr DecodeOctet #ifdef EDITOR Encode: di push iy ld (OutStart),de ld (LZStart),hl ld b,1 EncodeOctet: djnz NotSetFlags ld b,8 push de pop iy inc de NotSetFlags: push ix push de push hl ld de,-64 add hl,de ld de,1234h LZStart =$-2 call CP_HL_DE jr c,GotMatchStart ex de,hl GotMatchStart: pop hl ld c,0 StartSearch: call CP_HL_DE jr z,DoneSearch call Compare inc de ld a,c cp 6 jr nz,StartSearch DoneSearch: pop de ex (sp),hl ld a,l or h ex (sp),hl jr z,DoneEncode ld a,c cp 3 rr (iy) cp 3 jr nc,StoreString pop ix ldi inc bc dec ix jr EncodeOctet StoreString: ex (sp),iy ; Ý flagpos push bc ; Ý flagcnt Ý flagpos push iy ; Ý bytesleft Ý flagcnt Ý flagpos ex (sp),hl ; Ý curpos Ý flagcnt Ý flagpos ld b,0 ld c,a ld a,h or a jr nz,NotTooLong ld a,c cp l jr c,NotTooLong ld c,l NotTooLong: or a sbc hl,bc ld a,c ex (sp),hl ; Ý bytesleft Ý flagcnt Ý flagpos ex de,hl push ix ; Ý matchpos Ý bytesleft Ý flagcnt Ý flagpos ex (sp),hl ; Ý destpos Ý bytesleft Ý flagcnt Ý flagpos sbc hl,de ex de,hl add hl,bc ex (sp),hl ; Ý curpos Ý bytesleft Ý flagcnt Ý flagpos sub 3 rrca rrca rla rl e rla rl e ld (hl),e inc hl ex de,hl pop hl pop ix pop bc pop iy jp EncodeOctet DoneEncode: pop hl ld a,b or a jr z,NoIYadj AdjIY: rr (iy) djnz AdjIY NoIYadj: ld hl,1234h OutStart =$-2 ex de,hl or a sbc hl,de push hl pop ix pop iy ei ret Compare: push bc push hl push de ld b,0 CompareNext: ld a,(de) cp (hl) jr nz,Mismatch inc b ld a,b cp 6 inc hl inc de jr nz,CompareNext Mismatch: pop de pop hl ld a,b pop bc cp c ret c ld c,a push de pop ix ret #endif #endif ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ TI-82 and TI-83 screen routines ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß #ifdef BUFSCR #ifdef TI82 grbufclr: ld hl,screenmem ld de,screenmem+1 ld bc,2FFh ld (hl),0 ldir ret #else grbufclr =_GRBUFCLR #endif #ifdef FASTBUFCPY bufcpy: #ifdef GREY ret #else ; di ld a,5 out (10h),a call lcdbusy ld hl,screenmem ld c,12 bufcols: ld a,080h out (10h),a call lcdbusy ld de,12 ld a,20h+12 sub c out (10h),a call lcdbusy ld b,64 bufrows: push af pop af ld a,(hl) add hl,de out (11h),a djnz bufrows ld de,1-(12*64) add hl,de dec c jr nz,bufcols ; ei ret lcdbusy: push af pop af ret #endif #else #ifdef TI83 bufcpy =_GRBUFCPY_V #else bufcpy: ROM_CALL(DISP_GRAPH) ret #endif #endif #endif ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Link stuff ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß LINK_VARINFO =1Eh LINK_VARDATA =21h LINK_ACK =35h LINK_RESEND =39h LINK_ACCEPT =45h LINK_REJECT =4Bh LINK_GAME =77h LINK_LEVEL =89h SENDATTEMPTS =100 TIMEOUT =0FFFFh TransmitMsg .db "Sending...",0 ReceiveMsg .db "Receiving...",0 ReceivedMsg .db "World received ok!",0 LinkErrorMsg .db "Link error!",0 AbortErrorMsg .db "Aborted!",0 RejectedMsg .db "World not sent!",0 SentMsg .db "World sent ok!",0 MemoryMsg .db "No mem or var exists",0 ReceiveWorld: call ReceivePacketCont jp c,LinkError call BlankWorldName ld hl,ReceiveMsg call _vputs #ifdef BUFSCR call bufcpy #endif ld a,(LinkBuffer) cp LINK_VARINFO jp nz,LinkError ld hl,LinkBuffer+4 xor a ld b,a ld c,(hl) inc c #ifdef TI86 ld de,_OP1+1 #else ld de,NewVarName #endif ldir ld (de),a ld hl,(LinkBuffer+2) ld (ReceiveLength),hl call CreateWorldVar jr nc,AcceptWorld ld a,LINK_REJECT call SendByte ld hl,MemoryMsg jr LinkMsgAndExit AcceptWorld: ld a,LINK_ACCEPT call SendByte ld hl,0 DoReceiveWorld: push hl call ReceivePacket pop de jr c,LinkError ld a,(LinkBuffer) sub LINK_VARDATA jr nz,LinkError ld hl,(LinkBuffer+1) ld h,a ld b,a ld c,l add hl,de push hl inc de inc de call SaveLinkBlock pop hl ld de,0 ReceiveLength =$-2 call CP_HL_DE jr c,DoReceiveWorld ReceivedWorld: call GetWorldInfo ld hl,ReceivedMsg jr LinkMsgAndExit TransmitWorld: call BlankWorldName ld hl,TransmitMsg call _vputs #ifdef BUFSCR call bufcpy #endif ld bc,2 ld d,b ld e,b call CopyLinkBlock ld a,'.' call _vputmap #ifdef BUFSCR call bufcpy #endif #ifdef TI86 rst 10h ld de,-5 add hl,de #else ld hl,(VATAddr) #endif ld de,LinkBuffer+2 ld b,(hl) push bc inc b CopyVarName: ld a,(hl) ld (de),a inc de dec hl djnz CopyVarName pop af add a,3 ld b,a ld a,LINK_VARINFO call SendPacket jr nc,SentVarInfoOK LinkError: ld a,0BFh call _readkeypad bit 6,a ld hl,LinkErrorMsg jr nz,LinkMsgAndExit ld hl,AbortErrorMsg LinkMsgAndExit: call BlankWorldName call _vputs #ifdef BUFSCR call bufcpy #endif call WaitForKey jp PutWorldInfo SentVarInfoOK: ld a,'.' call _vputmap #ifdef BUFSCR call bufcpy #endif ld d,SENDATTEMPTS WaitForWorldAccept: push de call ReceiveByte pop de jr nc,WorldAccepted dec d jr nz,WaitForWorldAccept jr LinkError WorldAccepted: cp LINK_ACCEPT ld hl,RejectedMsg jr nz,LinkMsgAndExit ld a,'.' call _vputmap #ifdef BUFSCR call bufcpy #endif ld hl,2 ld bc,(LinkBuffer) DoTransmitWorld: push hl push bc ld bc,100 push bc ex de,hl call CopyLinkBlock pop bc pop hl or a sbc hl,bc jr nc,NotLastBlock add hl,bc ld b,h ld c,l ld hl,0 NotLastBlock: ex (sp),hl add hl,bc push hl ld b,c ld a,LINK_VARDATA call SendPacket pop hl pop bc jr c,LinkError ld a,b or c jr nz,DoTransmitWorld ;m00f? hrm ; ld a,D0HD1H ; out (LINKPORT),a ld hl,SentMsg jr LinkMsgAndExit #ifdef TI83 LINKMASK =12 #else LINKMASK =3 #endif SendPacket: ld hl,LinkBuffer SendPacketHL: push af ld de,250 PreSendDelay: dec de ld a,d or e jr nz,PreSendDelay pop af ld d,a ld a,D0HD1H out (LINKPORT),a in a,(LINKPORT) and LINKMASK cp LINKMASK ResendPacket: scf ret nz ld a,d call SendByte ld a,b call nc,SendByte ret c push bc push de push hl ld c,0 SendBytes: ld a,(hl) call SendByte jr c,PacketSendFailed ld a,c add a,(hl) ld c,a inc hl djnz SendBytes ld a,c call SendByte PacketSendFailed: pop hl pop de pop bc call ReceiveByte ret c cp LINK_ACK ret z cp LINK_RESEND jr ResendPacket ReceivePacket: call ReceiveByte ReceivePacketCont: ld hl,LinkBuffer ld (hl),a inc hl call nc,ReceiveByte ret c ld (hl),a inc hl ld b,a ld c,0 ReceiveBytes: call ReceiveByte jr c,PacketReceiveFailed ld (hl),a add a,c ld c,a inc hl djnz ReceiveBytes call ReceiveByte cp c jr z,GotPacketOK PacketReceiveFailed: ld a,LINK_RESEND call SendWithDelay ret c jr ReceivePacket GotPacketOK: ld a,LINK_ACK SendWithDelay: push af ld hl,300 SendDelay: dec hl ld a,h or l jr nz,SendDelay pop af jr SendByte #ifndef TI82 #ifndef TI83 #ifndef TI85 TryReceiveByte: in a,(LINKPORT) #ifdef TI83 and 12 cp 12 #else and 3 cp 3 #endif scf ret z ReceiveByteCont: push bc ld b,_ASAP_RECCONT jr DoLink ReceiveByte: push bc ld b,_ASAP_RECEIVE jr DoLink SendByte: push bc ld b,_ASAP_SEND DoLink: push de push hl ld hl,_ASAP_IND ld (hl),b ld hl,LinkErrorHandler call _setErrorHand set 2,(iy+12h) call _linkExec ld h,a call _clearErrorHand or 1 ;clear cf .org $-1 LinkErrorHandler: scf DoneLink: res 2,(iy+12h) ;error handler resets this anyway #ifdef TI83 ld a,0D0h out (0),a #endif ld a,h pop hl pop de pop bc ret #endif #endif #endif #ifndef TI86 ;#ifndef TI83 LinkPrep: ex (sp),hl push bc push de set 2,(iy+12h) ld b,8 jp (hl) TryReceiveByte: in a,(LINKPORT) and LINKMASK cp LINKMASK scf ret z ReceiveByteCont: call LinkPrep jr ReceiveCont ReceiveByte: call LinkPrep ReceiveBits: ld de,-1 WaitRecBit: call CheckLink jr z,LinkFailed cp LINKMASK jr z,WaitRecBit ReceiveCont: sub LINKMASK/3*2 ld a,LINKMASK/3*2 ld d,D0LD1H jr c,ReceiveLow rra ld d,D0HD1L ReceiveLow: rr c ld (AckBit),a ld a,d out (LINKPORT),a ld de,-1 WaitAckRec: call CheckLink cp 0 AckBit =$-1 jr nz,WaitAckRec ld a,D0HD1H out (LINKPORT),a ld d,4 WaitReadyRec: dec d jr z,ReadyRec in a,(LINKPORT) cp LINKMASK jr nz,WaitReadyRec ReadyRec: djnz ReceiveBits jr LinkSuccess SendByte: call LinkPrep ld c,a SendBits: rr c ld a,D0LD1H jr nc,SendLow ld a,D0HD1L SendLow: out (LINKPORT),a ld de,-1 WaitAckSend: call CheckLink jr nz,WaitAckSend SendAcked: ld a,D0HD1H out (LINKPORT),a ld de,-1 WaitReadySend: call CheckLink cp LINKMASK jr nz,WaitReadySend djnz SendBits LinkSuccess: or 0 .org $-1 LinkFailed: scf res 2,(iy+12h) #ifdef TI83 ld a,0D0h out (0),a #endif ld a,c pop de pop bc pop hl ret CheckLink: pop hl dec de ld a,d or e jr z,LinkFailed ld a,0BFh call _readkeypad bit 6,a jr z,LinkFailed in a,(LINKPORT) and LINKMASK jp (hl) ;#endif #endif ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ TI-82 and TI-85 ZShell ROM_CALL compatibility and other misc junk ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß BlankWorldName: push hl ld hl,50*256+(SCRWID/2)-21 ld (_penCol),hl push hl ld b,67 call vblank pop hl ld (_penCol),hl pop hl ret #ifdef EDITOR BlankMenuBar: ld hl,3300h ld (_penCol),hl ld b,25 call vblank ld hl,0600h+SCRWID-21 ld (_penCol),hl ld b,21 call vblank ld hl,SCRWID-32 ld (_penCol),hl ld b,32 call vblank BlankJustMenu: ld hl,3900h ld (_penCol),hl ld b,(SCRWID/2)-13 call vblank ld a,(SCRWID/2)+14 ld (_penCol),a ld b,(SCRWID/2)-14 #endif vblank: ld a,' ' call _vputmap djnz vblank ret #if 0 vputHLhex: ; ld (_penCol),de push hl ld a,h call vputAhex2 pop hl ld a,l jr vputAhex2 #endif #ifdef EDITOR vputAhex: ld (_penCol),hl vputAhex2: push af rra rra rra rra call PutHexDigit pop af PutHexDigit: and 15 add a,'0' cp '9'+1 jr c,NotAlpha add a,'A'-'9'-1 NotAlpha: jp _vputmap #endif vputAhl: ld (_penCol),hl vputA: ld l,a ld h,0 ld b,2 jr vputHL vputHL_de: ld (_penCol),de vputHL: ld de,UnpackBuffer xor a ld (de),a doputhl: dec de call UNPACK_HL add a,'0' ld (de),a djnz doputhl ex de,hl jp _vputs _vputs_de: ld (_penCol),de #ifdef ROMCALL _vputs: ROM_CALL(D_ZM_STR) \ ret _vputmap: ROM_CALL(M_CHARPUT) \ ret _vputsn: ROM_CALL(D_LM_STR) \ ret _clrLCD: ROM_CALL(CLEARLCD) \ ret #ifdef TI82 _clrScrn: ROM_CALL(CLEARTEXT_F) \ ret _CHKFINDSYM: ROM_CALL(213Eh-1Ah) \ ret #else _clrScrn: ROM_CALL(CLEARTEXT) \ ret #endif _putc: ROM_CALL(TX_CHARPUT) \ ret #else jp _vputs #endif ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Sprites ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß ; sprite format: ; .db (sprite width-1)/2 ; .db sprite height ; .db sprite data Jewel .db 2,4 #ifdef GREY .db 10001111b,01110000b,10001111b,01110000b .db 00000111b,10001000b,00000111b,10001000b .db 10001111b,01010000b,10001111b,01010000b .db 11011111b,00100000b,11011111b,00100000b #else .db 10001111b,01110000b .db 00000111b,10001000b .db 10001111b,01010000b .db 11011111b,00100000b ; .db 10000011b,00111000b ; .db 00000001b,01000100b ; .db 10000011b,00101000b ; .db 11000111b,00010000b #endif Ball .db 1,3 #ifdef GREY .db 00011111b,01000000b,00011111b,11100000b .db 00011111b,11100000b,00011111b,11100000b .db 00011111b,01000000b,00011111b,11100000b BallCentre =$-7 #else .db 00011111b,11100000b .db 00011111b,10100000b .db 00011111b,11100000b BallCentre =$-3 #endif Enemy .db 1,3 #ifdef GREY .db 00011111b,01000000b,00011111b,11100000b .db 00011111b,11100000b,00011111b,11100000b .db 00011111b,01000000b,00011111b,11100000b #else .db 00011111b,11100000b .db 00011111b,10100000b .db 00011111b,11100000b #endif #ifdef EDITOR Cursor .db 1,2 #ifdef GREY .db 11111111b,01000000b,11111111b,01000000b .db 10111111b,10100000b,10111111b,10100000b CursorCentre =$-1 #else .db 255,01000000b .db 255,11100000b CursorCentre =$-1 #endif #endif ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Data ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß #ifdef TI85 TI85ROMS: ; .dw 284Eh-10,2CBEh \ .db 2Ah ;2.0 ; .dw 2851h-10,2CC1h \ .db 57h ;4.0 - 4?? ; .dw 2859h-10,2CC9h \ .db 3Ah ;4.0 + 4 ; .dw 2804h-10,2C74h \ .db 91h ;9.0 ; .dw 281Eh-10,2C8Eh \ .db 35h ;10.0 ; .dw 2855h-10,2CC5h \ .db 0 ;4.0 .db 2Ah,49h .db 57h,4Dh .db 3Ah,55h ;?? .db 97h,55h ;rom 8 .db 91h,00h ;rom 9 .db 35h,1Ah ;rom 10 - works .db 51h ;3Dh = rom 6 ;8Eh = rom 4 #endif #include logo.inc NumMenuStrings =12 MenuStrings .db (SCRWID/2)+32,2,VERSION,0 .db (SCRWID/2)-32,14,"by Matthew Shepcar",0 .db (SCRWID/2)-43,23,"2nd - Start",0 .db (SCRWID/2)-01,23,"ALPHA - World",0 .db (SCRWID/2)-43,29,DELNAME," - Mode",0 #ifdef EDITOR .db (SCRWID/2)-01,29,MORENAME," - Edit",0 #else .db (SCRWID/2)-01,29,"(No editor)",0 #endif .db (SCRWID/2)-43,35,F1NAME," - Scores",0 .db (SCRWID/2)-01,35,"x - Send",0 .db (SCRWID/2)-43,41,CUSTOMNAME," - Keys",0 .db (SCRWID/2)-01,41,EXITNAME," - Exit",0 .db (SCRWID/2)-45,50,"World:",0 .db (SCRWID/2)-45,56,"Mode:",0 CustomKeysMsg .db "Customise keys:",0 .db "North-west: ",0 .db "South-east: ",0 .db "North-east: ",0 .db "South-west: ",0 NoWorldsMsg .db 16,"NO WORLDS FOUND!" PractiseMsg .db "Practice",0 ChallengeMsg .db "Challenge",0 LinkMsg .db "Linked game",0 WaitingMsg .db "Waiting...",0 #ifdef BUFSCR LevelMsg .db "Lev",0 #else LevelMsg .db "Level ",0 #endif TimeMsg .db "Time",0 LivesMsg .db "Lives",0 ScoreMsg .db "Score",0 PauseMsg .db "Paused!",0 GameOverMsg .db "G A M E O V E R",0 CompletedMsg .db "WORLD COMPLETED!!!",0 HighscoresMsg .db "High scores",0 NewScoreMsg .db "Enter your name!",0 DoneScoresMsg .db "Press a key to continue",0 #ifndef BUFSCR AlphaKeys .db 2Eh,26h,1Eh,16h,0Eh .db 2Dh,25h,1Dh,15h,0Dh .db 2Ch,24h,1Ch,14h,0Ch .db 2Bh,23h,1Bh,13h,0Bh .db 22h,1Ah,12h,0Ah .db 21h,19h #else AlphaKeys .db 2Fh,27h,1Fh .db 2Eh,26h,1Eh,16h,0Eh .db 2Dh,25h,1Dh,15h,0Dh .db 2Ch,24h,1Ch,14h,0Ch .db 2Bh,23h,1Bh,13h,0Bh .db 2Ah,22h,1Ah #endif greycounter .db 0 GameMode .db 0 KeyNW .db K_SECOND KeySE .db K_XVAR KeyNE .db K_RIGHT KeySW .db K_DOWN ProgSize =$-StartAddr ; ÚÄÄ¿ ÜÜÜÜÜÜ ÜÜÜÜÜ ÜÜ Ü Ü Ü Ü ; ³ Workspace ; ÀÄÄÙ ßßßßßß ßßßßß ßß ß ß ß ß #ifdef TI86 Workspace =_textShadow VarInfo =_textShadow+117 Workspace2 =_cmdShadow WorldInfo =_cmdShadow+70 LinkBuffer =$ LevelSpace =$+2 #endif TopY =Workspace MidY =Workspace+2 BotY =Workspace+4 TopDelta =Workspace+6 MidDelta =Workspace+8 EnemyFrame =Workspace+10 TimeLeft =Workspace+11 TimeLeftTicker =Workspace+13 blockxy =Workspace+14 blockx =Workspace+14 blocky =Workspace+15 MaskingFlag =Workspace+16 HVelocity =Workspace+17 NextWaypoint =Workspace+19 FlashTimer =Workspace+20 GameTics =Workspace+21 WaypointDist =Workspace+23 ;distance between current and next waypoint WaypointPos =Workspace+24 ;enemy's distance from current waypoint WaypointXDist =Workspace+25 WaypointYDist =Workspace+26 BallData =Workspace+27 BallH =BallData BallX =BallData+2 BallY =BallData+4 XVelocity =BallData+20 ;extra data stored in unused fourth row YVelocity =BallData+22 ;of old background storage EnemyData =Workspace+62 EnemyH =EnemyData EnemyX =EnemyData+2 EnemyY =EnemyData+4 WaypointXY =EnemyData+20 WaypointX =EnemyData+20 WaypointY =EnemyData+21 EnemyVH =EnemyData+22 MaskAddr =Workspace+97 LivesLeft =Workspace+99 Score =Workspace+100 UnpackBuffer =Workspace+107 Linked =Workspace+108 JewelData =Workspace2 JewelH =JewelData JewelX =JewelData+2 JewelY =JewelData+4 CursorData =Workspace2+35 CursorH =CursorData CursorX =CursorData+2 CursorY =CursorData+4 TempX =CursorData+16 ;ok so none of this is TempY =CursorData+18 ;related to the cursor clipleft =CursorData+20 ;but it uses up the two clipright =CursorData+21 ;free rows of background cliptop =CursorData+22 ;storage left over clipbottom =CursorData+23 LevelSig =WorldInfo LevelCount =WorldInfo+2 MaxLevel =WorldInfo+3 Highscores =WorldInfo+4 NameLength =WorldInfo+40 WorldInfoLen =62 BallStartX =LevelSpace+121 BallStartY =LevelSpace+122 WaypointCount =LevelSpace+123 JewelStartX =LevelSpace+124 JewelStartY =LevelSpace+125 LevelName =LevelSpace+126 TimeLimit =LevelSpace+132 Waypoints =LevelSpace+133 LEVELSIZE =133 VATAddr =VarInfo NoWorldsFlag =VarInfo+2 WorldAddr =VarInfo+3 greybuffer =VarInfo+6 greypage =VarInfo+8 timer =VarInfo+9 #ifndef TI86 NewVarName =OP6 #endif #ifdef TI86 GreySpace =((LevelSpace+256) | 255)+1 DemoState =80FFh DemoPointer =8100h RightKeyState =8102h DownKeyState =8104h SecondKeyState =8106h XVARKeyState =8108h DemoBuffer =810Ah #endif .end