**************************************************************************** **************************************************************************** ** ** Phoenix (Display routine) ** ** Copyright 2000 by Patrick Davidson. This software may be freely ** modified and/or copied with no restrictions. There is no warranty. ** ** by Patrick Davidson (pad@calc.org, http://pad.calc.org/) ** ** Last updated August 9, 2000 ** **************************************************************************** **************************************************************************** ******************************************** SLOW DOWN TO 32 FRAMES/SEC * * This routine regulates the speed of gameplay to ensure that it runs * always at 32 frames per second (except when playing in fast mode on a * TI-89, where the game always runs at 48 frames per second). It does this * by waiting until the timer value returns to its beginning. * * It determines whether the game has run too slowly by testing the * trigger_flag variable, which is set at the beginning of each new interval. * If it has run at an acceptable speed, it would already be waiting by this * time, and it clears the flag at the end of the wait loop. If the flag is * set before that, the routine then sets the slow_flag variable, warning * that the game was running too slowly, and then goes into the wait loop * anyway, which will slow it down to the end of the next frame. However, * the next time the delay is called, it recognizes that and skips the delay, * also resetting the flags. This way, when the game is running too slowly, * the slow flag will alternate, and the delay will happen less frequently, * hopefully synchronizing the speed at 2/3 the intended frame rate. * * Of course, this slow condition should never or almost never occur in * actual use. * ******** EVEN Timer_Delay: tst.b slow_flag(a5) ; Test for if the "slow warning" bne.s skip_delay ; was given on the last frame tst.b trigger_flag ; Test if this frame ran too bne.s slow_warning ; slowly, set warning if it did Timer_Delay_Loop: ; Wait for next 32Hz interval tst.b $600017 bne.s Timer_Delay_Loop skip_delay: sf trigger_flag sf slow_flag(a5) rts slow_warning: st slow_flag(a5) sf trigger_flag rts trigger: st trigger_flag ; Indicate a new 32Hz interval rte ; has started (if this happens ; when the game isn't waiting, ; that indicates the game is ; running too slowly). ******************************************** PREPARE DISPLAY SYSTEM * * This routine prepares the display for gameplay by drawing the shield bar, * and, if not on the TI-89, displaying the title message in the status bar. * ******** Status_Prepare: IFND ti89d PEA _full_title(pc) ; Display title JSR ST_showHelp addq.l #4,sp Shield_Update: lea LCD_MEM+L_SHIELD*30+30,a0 ; Display shield level moveq #14,d0 Shield_Clear_Loop: clr.w -(a0) dbra d0,Shield_Clear_Loop move.w player_dmg(a5),d0 subq.w #2,d0 blt.s Shield_Out_Of_Range cmp.w #30,d0 bge.s Shield_Out_Of_Range Shield_Draw_Loop: st (a0)+ dbra d0,Shield_Draw_Loop ENDIF IFD ti89d Shield_Update: lea LCD_MEM+L_SHIELD*30+20,a0 ; Display shield level moveq #9,d0 Shield_Clear_Loop: clr.w -(a0) dbra d0,Shield_Clear_Loop move.w player_dmg(a5),d0 subq.w #2,d0 add.w d0,d0 divs #3,d0 ble.s Shield_Out_Of_Range cmp.w #20,d0 bge.s Shield_Out_Of_Range Shield_Draw_Loop: st (a0)+ dbra d0,Shield_Draw_Loop swap d0 mulu #3,d0 move.w #$FF00,d1 asr.w d0,d1 move.b d1,(a0)+ ENDIF Shield_Out_Of_Range: RTS ******************************************** INITIALIZE DISPLAY * * This routine initializes the display for the start of the program by * drawing the bar over the top row (which is necessary to decrease LCD * artifacts, especially on the TI-92) and also draws a solid bar on the * right side of the screen for all calculators but the TI-89 (which is * needed there since the game only uses 228 pixels of screen width). * ******** Initialize_Stuff: IFND ti89d lea LCD_MEM,a0 ; Draw bar over top row moveq #-1,d1 moveq #14,d0 ltbar: move.w d1,(a0)+ dbra d0,ltbar LEA 640(a5),A0 MOVEQ #127,D0 MOVEQ #-1,D1 LAB_011B: MOVE D1,(A0)+ ; Set up filled-in sides lea 28(a0),a0 MOVE D1,(A0)+ DBF D0,LAB_011B LEA LCD_MEM+$1C,A0 ; Draw black column on right MOVEQ #120,D0 MOVEQ #-1,D1 LAB_011D: MOVE #$FFFF,(A0) LEA 30(A0),A0 DBF D0,LAB_011D ENDIF ******************************************** DISPLAY SCREEN BUFFER Display_Screen: IFND ti89d move.w #$FF7F,$18(a6) lea 32*(20+120)+2(a5),a0 lea LCD_MEM+(120*30)+28,a1 moveq #119,d0 Copy_Lines: movem.l (a0)+,d1-d7 movem.l d1-d7,-(a1) subq.l #2,a1 lea -60(a0),a0 dbf d0,Copy_Lines btst #6,$1b(a6) ENDIF IFD ti89d move.w #%1111111111011111,$18(a6) LEA 6+32*22(A5),A0 LEA LCD_MEM,A1 MOVEQ #98,D0 LAB_0124: MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ MOVE.L (A0)+,(A1)+ lea 12(a0),a0 lea 10(a1),A1 DBF D0,LAB_0124 btst #0,$1b(a6) ENDIF beq save_game RTS bla: dc.b '%d',0,0 ******************************************** CLEAR GAMEPLAY AREA IFND ti89d Clear_Screen: lea LCD_MEM+30,a0 moveq #119,d1 moveq #0,d0 CLS: move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.l d0,(a0)+ move.w d0,(a0)+ move.w d0,(a0)+ addq.w #2,a0 dbra d1,CLS rts ENDIF IFD ti89d Clear_Screen_Main: lea 121*32+26(a5),a0 move.b inv(a5),d0 ext.w d0 ext.l d0 move.l d0,d1 move.l d0,d2 move.l d0,d3 move.l d0,d4 moveq #101,d5 Clear_Screen_Loop_: movem.l d0-d4,-(a0) lea -12(a0),a0 dbra d5,Clear_Screen_Loop_ rts Clear_Screen: lea LCD_MEM+98*30+20,a0 moveq #0,d0 moveq #0,d1 moveq #0,d2 moveq #0,d3 moveq #0,d4 moveq #98,d5 Clear_Screen_Loop: movem.l d0-d4,-(a0) lea -10(a0),a0 dbra d5,Clear_Screen_Loop bra Status_Prepare ENDIF