*************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot1.a99 xxx * * This file contains the main game program *************************************************************** ********@*****@*********************@************************** IDT 'TI' TITL 'Time Pilot' DEF SFIRST, SLAST, SLOAD AORG >A000 VDPSAT EQU >0300 ; VDP Sprite Attribute table VDPSPT EQU >0400 ; VDP Sprite Pattern Table VDPPT EQU >0800 ; VDP Pattern Table SFIRST B @MAIN ; Start main SLOAD EQU SFIRST *************************************************************** * RAM memory setup for Time Pilot ********@*****@*********************@************************** *RAMSAT EQU >8340 ; SAT table in scratch-pad memory (128 bytes) RAMSAT BSS 128 TIMER BSS 160 ; Space for 20 slot timers (160 bytes) RAMBUF BSS 1024 ; Work-buffer in memory (1024 bytes) *-------------------------------------------------------------- * Memory specific for Time Pilot game *-------------------------------------------------------------- STATUS DATA 0 ; Game status RTOFF DATA 0 ; Current offset in ROTATE table MYORDR BSS 32 ; Sprite order table *-------------------------------------------------------------- * Equates for Bullets *-------------------------------------------------------------- BULSIZ EQU 12 ; 12 bytes required per bullet entry BULLTS EQU 9 ; Handle 9 bullets BULMAX EQU BULLTS*BULSIZ ; Table length *-------------------------------------------------------------- * Memory for bullets *-------------------------------------------------------------- BULCNT DATA 0 ; Bullets counter BULCUR DATA 0 ; Current offset in BULTAB table BULTAB BSS BULMAX+1 ; Table for handling bullets. 1 byte padded to avoid bug BULPAT BSS BULLTS*8 ; Buffer bullet patterns. *************************************************************** * Time Pilot main program ********@*****@*********************@************************** MAIN LWPI WSSPC1 ; Load main workspace LIMI 0 LI STACK,STKBUF ; Setup simulated stack LI R0,VMODE1 ; "graphics mode 1" BL @LVDPSH ; Load shadow registers LI R0,>0704 ; Set backdrop to blue MOV R0,@VDPR7 BL @VIDOFF ; Disable screen updates BL @WVDPSH ; Write shadow registers to VDP BL @KONFNT ; Load Konami Font BL @VDPADR DATA GETPCT MOV @OUTP0,R0 LI R1,COLORS LI R2,32 BL @VMBW BL @VDPADR ; Result is in @OUTP0 DATA GETPDT ; Get address of pattern descriptor table MOV @OUTP0,R1 AI R1,16*8 LI R0,ISVDP BL @XCPY DATA CPYROM,LG,3*8 ; 16..18 Copy G-H-I DATA CPYROM,LP,8 ; 19 Copy P DATA CPYROM,LU,8 ; 20 Copy U DATA CPYROM,D0,3*8 ; 21..23 Copy 0-1-2 DATA CPYROM,DB,8 ; 24 Copy HYPHEN DATA CPYROM,BETA,4*8 ; 25..28 Copy BETA-0.x DATA 0 *-------------------------------------------------------------- * Draw screen and start task scheduler *-------------------------------------------------------------- LI R0,10 BL @FILSCR ; Clear screen "black" BL @FIBOX DATA 0,0,23,23,32 ; Clear game area "blue" BL @PUTTX DATA >1904,STR1 ; X=25/Y=04/'HIGH' BL @PUTTX DATA >1905,STR3 ; X=25/Y=05/'000000' BL @PUTTX DATA >1909,STR2 ; X=25/Y=09/'1-UP' BL @PUTTX DATA >190A,STR3 ; X=25/Y=0A/'000000' BL @PUTTX DATA >1A17,STR4 ; X=27/Y=23/'BETA-0.x' BL @PATTRN BL @GINIT ; Initalize game BL @VIDON ; Enable screen updates BL @WVDPSH ; Write shadow registers to VDP B @TMGR ; Start task scheduler *************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot1.a99 * * This file contains the game initalisation * * KONFNT - Load Konami font * PATTRN - Load sprite patterns * GINIT - Initalize game * OSHIP - Display object Fighter *************************************************************** *************************************************************** * KONFNT - Load Konami font *************************************************************** * BL @KONFNT *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** KONFNT INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK BL @VDPADR ; Result is in @OUTP0 DATA GETPDT ; Get address of pattern descriptor table *-------------------------------------------------------------- * Copy Konami digits to VDP *-------------------------------------------------------------- MOV @OUTP0,R0 LI R1,DIGITS LI R2,11*8 ; For displaying score BL @VMBW *-------------------------------------------------------------- * Copy Konami letters to VDP *-------------------------------------------------------------- AI R0,65*8 ; ASCII 65 LI R1,LETTRS LI R2,26*8 ; Bytes to copy BL @VMBW BL @POPRG2 ; Exit *************************************************************** * PATTRN - Load sprite and tile patterns *************************************************************** * BL @PATTRN *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** PATTRN INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV R4,*STACK *-------------------------------------------------------------- * Setup SPT address *-------------------------------------------------------------- LI R0,>0606 ; SPT at VDP >3000 MOV R0,@VDPR6 ; Set Shadow register 6 BL @VWTR ; Write VDP register *-------------------------------------------------------------- * Copy sprite patterns (fighter) to VDP >3000 *-------------------------------------------------------------- * Bytes to copy: 960 = 15 * 2 * 32 BL @PVRAM ; Copy 4x4 patterns (>00 - >74) DATA >3000,FGHT1,960 ; VDP>3000 ... VDP>33C0 *-------------------------------------------------------------- * Mirror sprite patterns (fighter) to VDP >3800 *-------------------------------------------------------------- LI R1,RAMBUF ; scratch-pad verwenden! LI R2,64 LI R3,FGHTE ; RAM source address LI R4,>3800 ; VDP target address PATTR1 MOV R3,R0 ; Restore RAM source address BL @CPYMX ; Copy 2 patterns to ram buffer BL @MIRRV DATA RAMBUF,64,SWAP ; Mirror patterns MOV R4,R0 ; Set VDP target address BL @VMBW CI R3,FGHT1 JEQ PATTR2 ; Exit if last patterns processed AI R3,-64 ; Set RAM source address AI R4,64 ; Set VDP target address JMP PATTR1 *-------------------------------------------------------------- * Copy other sprite patterns to VDP >33C0 and >3BC0 *-------------------------------------------------------------- PATTR2 BL @PVRAM DATA >33C0,BGCLD1,160 BL @PVRAM DATA >3BC0,BGCLD1,160 *-------------------------------------------------------------- * Copy tile patterns (fighter) to VDP *-------------------------------------------------------------- * Bytes to copy: 480 = 15 * 4 * 8 BL @PVRAM DATA >0BE0,TFGHT1,480 *-------------------------------------------------------------- * Mirror tile patterns (fighter) to VDP >0DC0 *-------------------------------------------------------------- LI R2,32 LI R3,TFGHTE ; RAM source address LI R4,>0DC0 ; VDP target address PATTR3 MOV R3,R0 ; Restore RAM source address BL @CPYMX ; Copy 1 pattern to ram buffer BL @MIRRV DATA RAMBUF,32,SWAP ; Mirror patterns MOV R4,R0 ; Set VDP target address BL @VMBW CI R3,TFGHT1 JEQ PATTR4 ; Exit if last patterns processed AI R3,-32 ; Set RAM source address AI R4,32 ; Set VDP target address JMP PATTR3 *-------------------------------------------------------------- * Exit *-------------------------------------------------------------- PATTR4 B @POPRG4 *************************************************************** * GINIT - Initialize game *************************************************************** * BL @GINIT *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** GINIT INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK *-------------------------------------------------------------- * Some initialisation *-------------------------------------------------------------- BL @FILMEM DATA BULTAB,BULTAB+BULMAX,>00 ; Clear bullets table CLR @BULCUR ; Clear offset CLR @STATUS ; Reset game flags *-------------------------------------------------------------- * Set up sprites *-------------------------------------------------------------- BL @CPYM DATA ROMSAT,RAMSAT,32*4 ; Put sprites in shadow SAT LI R0,MYORDR BL @SPRORD ; Initialize sprite order table LI R0,VDPSAT LI R1,RAMSAT SETO R2 ; No sprite order table LI R2,MYORDR ; Use sprite order table BL @PUTSAT MOV @PLS8,@RTOFF ; Frame 15 *-------------------------------------------------------------- * Set up game controllers *-------------------------------------------------------------- MOV @PLS10,@THIGH ; Highest slot in use BL @MKSLOT DATA 0,2,KBSCAN ; Controller 0 - Keyboard BL @MKSLOT DATA 1,1,PSGTCK ; Controller 1 - Play PSG sound BL @MKSLOT DATA 2,3,ZCLOUD ; Controller 2 - Big sprite clouds LI R0,SPR5 ; First cloud is sprite 5 MOV R0,@TPRV2 ; Set private variable controller 2 BL @MKSLOT DATA 3,8,ZCLOUD ; Controller 3 - Small sprite clouds LI R0,SPR13 ; First cloud is sprite 13 MOV R0,@TPRV3 ; Set private variable controller 3 BL @MKSLOT DATA 5,2,ZSHIP ; Controller 5 - Time pilot fighter BL @MKSLOT DATA 6,1,GAME ; Controller 6 - Game controller LI R0,>0405 MOV R0,@TPRV6 ; For sprite rotation BL @IRDY ; Setup controller 9/10 ("player ready" text) *-------------------------------------------------------------- * Start Time Pilot tune *-------------------------------------------------------------- LI R0,SND1 BL @EPSGMD B @POPRG2 ; Exit *************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot3.a99 * * This file contains the objects and controllers for handling * bullets and firing system *************************************************************** *************************************************************** * OBULET - Draw all bullets *************************************************************** * Does not push/pop registers. Can only be called from ZBULET. *************************************************************** * INPUT * NONE ********@*****@*********************@************************** OBULET CLR R2 ; R2 = offset in bullet table CLR R4 ; Loop counter *-------------------------------------------------------------- * STEP 1: Determine what to do *-------------------------------------------------------------- OBULL1 MOV @BULTAB(R2),R1 ; Is entry empty ? JEQ OBULL6 ; Skip to next bullet *-------------------------------------------------------------- * STEP 2: Erase old tile from playfield *-------------------------------------------------------------- MOV @BULTAB+10(R2),R0 ; Get VDP address *-------------------------------------------------------------- * Inline VSBW *-------------------------------------------------------------- LI R1,>2000 ; SPACE character ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP MOVB R1,@VDPW *-------------------------------------------------------------- * STEP 3: Calculate tile positions of bullets *-------------------------------------------------------------- OBULL2 MOV @BULTAB(R2),R1 ; Is entry empty ? CI R1,>FFFF ; Bullet destroyed ? JNE OBULL3 ; No, so process CLR @BULTAB(R2) ; Reset >FFFF with >0000 JMP OBULL6 ; Skip to next bullet *-------------------------------------------------------------- * Calculate X tile position of bullet *-------------------------------------------------------------- OBULL3 CLR R0 ; For 32 bit division SRL R1,8 ; High byte to low byte DIV @PLS8,R0 ; R0=Quotient, R1=Remainder MOV R0,R3 ; Save quotient MOV R1,@BULTAB+4(R2) ; Save X-pixel offset in tile pattern. *-------------------------------------------------------------- * Calculate Y tile position of bullet *-------------------------------------------------------------- MOV @BULTAB(R2),R1 SZCB @BITMSB,R1 ; Clear high byte CLR R0 DIV @PLS8,R0 ; R0=Quotient, R1=Remainder *-------------------------------------------------------------- * Hack for avoiding bullet split if Y direction = 1 or -1 * (See @FIREDR - Frame 5,6,7,9,10,18,19,21,22) *-------------------------------------------------------------- CI R1,7 ; Y offset is 7 JNE OBULL5 ; No, continue LI R1,6 ; Set Y offset to 6 OBULL5 MOV R1,@BULTAB+6(R2) ; Save Y-pixel offset in tile pattern *-------------------------------------------------------------- * Calculate VDP address according to YX quotient values *-------------------------------------------------------------- SLA R0,5 ; Offset = Y * 32 A R3,R0 ; Offset = Offset + X MOV R4,@BULTAB+8(R2) ; Character to write MOV R0,@BULTAB+10(R2) ; Save VDP address in bullets table *-------------------------------------------------------------- * Some table housekeeping *-------------------------------------------------------------- OBULL6 CI R2,BULMAX ; All bullets processed ? JEQ OBULL7 ; Continue with STEP 4 AI R2,BULSIZ INC R4 JMP OBULL1 ; Process next bullet *-------------------------------------------------------------- * STEP 4: Loop over table and setup patterns *-------------------------------------------------------------- OBULL7 LI R0,BULPAT ; Start clear bullet patterns LI R1,BULLTS*8 ; Erase patterns OBULL8 CLR *R0+ DEC R1 JNE OBULL8 ; End clear bullet patterns LI R0,BULTAB CLR R1 CLR R2 *-------------------------------------------------------------- * Draw bullet in memory. R0=Offset in pattern table *-------------------------------------------------------------- OBULL9 MOV @BULTAB(R2),R0 ; Is entry empty ? JEQ OBULLA ; Yes, skip entry CI R0,>FFFF JEQ OBULLA MOV @BULTAB+8(R2),R1 ; Get pattern number SLA R1,3 ; Offset=pattern number * 8 A @BULTAB+6(R2),R1 ; Add Y to offset MOV @BULTAB+4(R2),R3 ; Get X SOCB @OBMASK(R3),@BULPAT(R1) SOCB @OBMASK(R3),@BULPAT+1(R1) *-------------------------------------------------------------- * Some table housekeeping *-------------------------------------------------------------- OBULLA AI R2,BULSIZ ; Next entry in table CI R2,BULMAX ; All bullets processed ? JLT OBULL9 ; No, process next entry in table *-------------------------------------------------------------- * STEP 5: Write bullets to VDP *-------------------------------------------------------------- LI R0,>0908 ; VDP >0908 - ASCII 33 LI R1,BULPAT LI R2,BULLTS*8 *-------------------------------------------------------------- * Inline VMBW *-------------------------------------------------------------- ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA OBULLB MOVB *R1+,@VDPW DEC R2 JNE OBULLB CLR R2 ; R2 = offset in bullet table *-------------------------------------------------------------- * Check if bullet tile must be displayed *-------------------------------------------------------------- OBULLC MOV @BULTAB(R2),R0 ; Is entry empty ? JEQ OBULLD ; Yes, skip entry CI R0,>FFFF ; Entry destroyed ? JEQ OBULLD ; Yes, skip entry MOV @BULTAB+10(R2),R0 ; VDP Target address MOV @BULTAB+8(R2),R1 ; Byte to write AI R1,33 ; Character offset *-------------------------------------------------------------- * Inline VSBW *-------------------------------------------------------------- SWPB R1 ; for VSBW ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP MOVB R1,@VDPW *-------------------------------------------------------------- * Some table housekeeping *-------------------------------------------------------------- OBULLD CI R2,BULMAX ; All bullets processed ? JEQ OBULLE ; Done. exit AI R2,BULSIZ JMP OBULLC ; Process next bullet *-------------------------------------------------------------- * Check if ZBULLET controller can be destroyed *-------------------------------------------------------------- OBULLE MOV @BULCNT,@BULCNT ; Bullet counter=0 ? JNE OBULLZ ; No, exit CLR @TSLT4 ; Destroy bullet controller OBULLZ B @POPRG4 ; Exit OBMASK BYTE >C0 ; X=0 11****** BYTE >60 ; X=1 *11***** BYTE >30 ; X=2 **11**** BYTE >18 ; X=3 ***11*** BYTE >0C ; X=4 ****11** BYTE >06 ; X=5 *****11* BYTE >03 ; X=6 ******11 BYTE >01 ; X=7 *******1 *************************************************************** * ZBULET - Bullets movement controller *************************************************************** * REMARKS * Runs in slot 4. *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** ZBULET INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV R4,*STACK CLR R2 ; R2 = offset in bullet table ZBULE1 MOV @BULTAB(R2),R0 ; Get bullet coordinates JEQ ZBULEA ; Next bullet *-------------------------------------------------------------- * Step 1: Check X: Destroy bullet if left boundary reached *-------------------------------------------------------------- LI R1,>0200 CB R0,R1 ; X > 2 ? JH ZBULE2 ; Yes, continue SETO R0 ; Destroy bullet DEC @BULCNT ; Bullet counter=-1 JMP ZBULEA ; Next bullet *-------------------------------------------------------------- * Step 2: Check X: Destroy bullet if right boundary reached *-------------------------------------------------------------- ZBULE2 LI R1,>B000 CB R0,R1 JLE ZBULE3 SETO R0 ; Destroy bullet DEC @BULCNT ; Bullet counter=-1 JMP ZBULEA ; Next bullet *-------------------------------------------------------------- * Step 3: Check Y: Destroy bullet if top boundary reached *-------------------------------------------------------------- ZBULE3 SZC @BITMSB,R0 ; Get rid of X JNE ZBULE4 ; Continue if Y > 0 SETO R0 ; Destroy bullet DEC @BULCNT ; Bullet counter=-1 JMP ZBULEA ; Next bullet *-------------------------------------------------------------- * Step 4: Check Y: Destroy bullet if bottom boundary reached *-------------------------------------------------------------- ZBULE4 LI R1,190 C R0,R1 JLE ZBULE5 ; Continue if Y <= 190 SETO R0 ; Destroy bullet DEC @BULCNT ; Bullet counter=-1 JMP ZBULEA ; Next bullet *-------------------------------------------------------------- * Step 5: Update XY coordinates depending on ship rotation *-------------------------------------------------------------- ZBULE5 MOV @BULTAB(R2),R0 ; Get XY coordinates AB @BULTAB+2(R2),R0 ; Add X direction SWPB R0 AB @BULTAB+3(R2),R0 ; Add Y direction SWPB R0 *-------------------------------------------------------------- * Some table housekeeping *-------------------------------------------------------------- ZBULEA MOV R0,@BULTAB(R2) ; Save XY position in table CI R2,BULMAX ; All bullets processed ? JEQ ZBULEB AI R2,BULSIZ ; Next bullet JMP ZBULE1 ; Process next bullet ZBULEB B @OBULET ; Show bullets and exit *************************************************************** * ZFIRE - Time Pilot shoot bullets *************************************************************** * INPUT * @RTOFF = Fighter target frame 0-27 * @BULCUR = Offset in bullets table ********@*****@*********************@************************** *-------------------------------------------------------------- * Constructor *-------------------------------------------------------------- IFIRE INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK *-------------------------------------------------------------- * Initialize controllers *-------------------------------------------------------------- MOV @STATUS,R0 CZC @BIT1,R0 ; Is ship fire salvo flag clear ? JEQ IFIRE1 ; Yes, so fire new salvo B @POPRG2 ; Exit IFIRE1 SOC @BIT1,@STATUS ; Set ship fire salvo flag MOV @BULCNT,@BULCNT JNE IFIRE2 BL @MKSLOT DATA 4,1,ZBULET ; Start bullets controller IFIRE2 BL @MKSLOT DATA 10,5,ZFIRE MOV @PLS4,@TPRV10 ; Fire 3 bullets JMP ZFIRE1 ; Kick-start now *-------------------------------------------------------------- * Controller *-------------------------------------------------------------- ZFIRE INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK *-------------------------------------------------------------- * Step 1: Check if all bullets fired *-------------------------------------------------------------- ZFIRE1 DEC @TPRV10 ; counter = counter - 1 JNE ZFIRF ; Not yet, add bullet CLR @TSLT10 ; Self-destruct slot 10 CLR @TSUB10 SZC @BIT1,@STATUS ; Clear ship fire salvo flag B @POPRG2 ; Exit *-------------------------------------------------------------- * Step 2: Add new bullet to table *-------------------------------------------------------------- ZFIRF INC @BULCNT ; Bullet counter=+1 MOV @RTOFF,R1 ; Get frame SLA R1,2 ; double word offset MOV @BULCUR,R2 ; Get current offset in bullets table MOV @FIREDR(R1),@BULTAB(R2) ; Set XY start position MOV @FIREDR+2(R1),@BULTAB+2(R2) ; Set XY direction *-------------------------------------------------------------- * Some table housekeeping *-------------------------------------------------------------- AI R2,BULSIZ ; Offset for next bullet CI R2,BULMAX ; Overflow ? JEQ ZFIRG MOV R2,@BULCUR ; Save new offset B @POPRG2 ; Exit ZFIRG CLR @BULCUR ; Next bullet is first entry in table B @POPRG2 ; Exit *************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot4.a99 * * This file contains the main game controllers *************************************************************** * SLOT 0: KBSCAN - Read keyboard * SLOT 1: PSGTCK - PSG player * SLOT 2: ZCLOUDS - Big clouds * SLOT 3: ZCLOUDS - Small clouds * SLOT 4: ZBULLETS - Control bullets * SLOT 5: ZSHIP - Time Pilot fighter * SLOT 6: GAME - Update SAT * SLOT 9: \ several animations * SLOT 10: / **************************************************************** *$$$$TART * Controller INTRO INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK SETO R2 JMP GAME4 *$$$END * Controller GAME INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK *-------------------------------------------------------------- * Check for 5th sprite *-------------------------------------------------------------- MOV @VDPSTA,R0 COC @BIT1,R0 ; 5th sprite flag set ? JNE GAME3 *-------------------------------------------------------------- * Rotate sprite order table *-------------------------------------------------------------- * MOV @PLS1,@MYORDR ; Overlay sprites 00-01 don't rotate -- NOT REQUIRED ? MOV @TPRV6,R0 ; Get sprite rotation counter MOV R0,R1 ; Work copy LI R2,4 ; Start with offset 4 GAME1 AI R1,>0202 ; Value for next 2 entries MOV R1,@MYORDR(R2) CI R1,>1314 ; Sprite 19-20. Wrap ? JLT GAME2 LI R1,>0405 ; Continue with sprite 2-3 GAME2 INCT R2 CI R2,20 ; All sprites processed ? JLT GAME1 AI R0,>0303 CI R0,>1314 ; Sprite 19-20. Wrap ? JLT AAA LI R0,>0203 AAA MOV R0,@TPRV6 ; Save for next run LI R2,MYORDR ; Use sprite order table JMP GAME4 GAME3 SETO R2 ; Default sprite order *-------------------------------------------------------------- * Dump SAT from RAM to VDP memory *-------------------------------------------------------------- GAME4 LI R0,VDPSAT LI R1,RAMSAT BL @PUTSAT B @POPRG2 ; Exit *************************************************************** * OSHIP - Display Time Pilot Fighter *************************************************************** * INPUT * @RTOFF = Offset in frame table ********@*****@*********************@************************** OSHIP INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK LI R0,>0606 ; SPT at VDP >3000 MOV @RTOFF,R1 CI R1,15 ; Show mirrored fighter ? JLT OSHIP1 LI R0,>0607 ; SPT at VDP >3800 AI R1,-15 ; Show mirrored fighter ! *-------------------------------------------------------------- * Switch VDP Sprite Pattern Table if necessary *-------------------------------------------------------------- OSHIP1 C R0,@VDPR6 JEQ OSHIP2 ; No change, no need to write register MOV R0,@VDPR6 ; Set Shadow register 6 BL @VWTR ; Write VDP register *-------------------------------------------------------------- * Update pattern names in SAT for fighter *-------------------------------------------------------------- OSHIP2 LI R0,2 MPY R0,R1 MOV R2,R1 ; R1=R1*3 SLA R1,10 ; R1=R1*4 and left justify OSHIP3 MOVB R1,@SPR1+2 ; Pattern fighter white AI R1,>0400 MOVB R1,@SPR2+2 ; Pattern fighter magenta *-------------------------------------------------------------- * Handle tile part of fighter (simulate 4x4 sprite) *-------------------------------------------------------------- MOV @RTOFF,R0 ; Create v,v+2,v+1,v+3 sequence SLA R0,2 ; R0 = R0 * 4 AI R0,124 MOV R0,R1 SWPB R1 AI R0,2 A R0,R1 ; R1=v,v+2 MOV R1,R2 AI R2,>0101 ; R2=v+1,v+3 *-------------------------------------------------------------- * Write first line *-------------------------------------------------------------- LI R0,>416B ; Setup VDP write address for >016B SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA MOVB R1,@VDPW ; Character 1 SWPB R1 MOVB R1,@VDPW ; Character 3 *-------------------------------------------------------------- * Write second line *-------------------------------------------------------------- LI R0,>418B ; Setup VDP write address for >018B SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA MOVB R2,@VDPW ; Character 2 SWPB R2 MOVB R2,@VDPW ; Character 4 *-------------------------------------------------------------- * Exit *-------------------------------------------------------------- B @POPRG2 ; Exit *$$$START TT BYTE 124,126,125,127 *************************************************************** * ZSHIP - Time Pilot fighter controller *************************************************************** * REMARKS * Runs in slot 5 *-------------------------------------------------------------- * INPUT * @RTOFF = Fighter target frame 0-27 ********@*****@*********************@************************** * Controller ZSHIP INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK MOV @VIRTKB,R0 MOV @STATUS,R1 * BL @DEBUG0 ; *DEBUG* - Show overlay sprites *-------------------------------------------------------------- * Check fire key *-------------------------------------------------------------- COC @BIT4,R0 ; Fire pressed ? JNE ZSHIP1 ; No, continue checking keys COC @BIT0,R1 ; Intro busy flag set ? JEQ ZSHIP1 ; Yes, skip fire BL @IFIRE ; Fire bullets *-------------------------------------------------------------- * Check direction keys *-------------------------------------------------------------- ZSHIP1 SZC @BIT4,R0 ; Clear fire button CLR R1 ; Offset counter ZSHIP2 C @DKEYS(R1),R0 ; Direction key match ? JEQ ZSHIP3 ; Yes, check direction INCT R1 CI R1,16 ; Last table in entry processed ? JLE ZSHIP2 ; Not yet, loop B @POPRG2 ; Exit *-------------------------------------------------------------- * Special checks * if (target frame = 20 and current frame <= 8) then rotate_left * if (target frame <= 5 and current frame >= 20) then rotate_right *-------------------------------------------------------------- ZSHIP3 MOV @RTOFF,R0 ; R0 = Current frame CI R0,8 JGT ZSHIP4 MOV @DIRCTN(R1),R0 ; Target frame CI R0,20 JEQ ZSHIP8 ; Rotate left ZSHIP4 C @DIRCTN(R1),@PLS5 JGT ZSHIP5 ; Check route1 if target frame > 5 MOV @RTOFF,R0 ; Current frame CI R0,20 JLT ZSHIP5 ; Check route1 if current frame < 20 JMP ZSHIP6 ; Rotate right *-------------------------------------------------------------- * route1 = target frame - current frame *-------------------------------------------------------------- ZSHIP5 MOV @DIRCTN(R1),R0 ; Target frame S @RTOFF,R0 JEQ ZSHIPY ; Exit if route1 = 0 *-------------------------------------------------------------- * route2 = 28 - target frame + current frame *-------------------------------------------------------------- LI R2,28 S @DIRCTN(R1),R2 A @RTOFF,R2 *-------------------------------------------------------------- * Decide on rotation *-------------------------------------------------------------- C R2,R0 JLE ZSHIP8 ; if route2 <= route1 then rotate_left MOV R0,R0 JLT ZSHIP8 ; if route1 < 0 then rotate_left otherwise rotate_right *-------------------------------------------------------------- * Rotate ship right *-------------------------------------------------------------- ZSHIP6 LI R0,27 C @RTOFF,R0 ; Wrap required ? JNE ZSHIP7 ; No, continue CLR @RTOFF ; Wrap around JMP ZSHIPY ZSHIP7 INC @RTOFF JMP ZSHIPY *-------------------------------------------------------------- * Rotate ship left *-------------------------------------------------------------- ZSHIP8 MOV @RTOFF,@RTOFF ; Wrap required ? JNE ZSHIP9 ; No, continue LI R0,27 ; Wrap around MOV R0,@RTOFF ZSHIP9 DEC @RTOFF ZSHIPY BL @OSHIP ; Draw fighter B @POPRG2 ; exit *-------------------------------------------------------------- * Driver table for ZSHIP controller * See time pilot rotation picture for frame details. * Frame 1 has offset 0 *-------------------------------------------------------------- DIRCTN DATA 24,0,5,20,8,17,14,11 DKEYS DATA KUPLFT, KUP, KUPRGT ; UL/24 U/0 UR/5 DATA KLFT, KRGT ; L/20 R/8 DATA KDNLFT, KDN, KDNRGT ; DL/17 D/14 DR/11 *************************************************************** * ZCLOUD - Cloud movement controller *************************************************************** * REMARKS * Big sprite clouds run in slot 2 * Small sprite clouds run in slot 3 *-------------------------------------------------------------- * INPUT * TPRV2 = VDP SAT offset for big sprite clouds * TPRV3 = VDP SAT offset for small sprite clouds ********@*****@*********************@************************** ZCLOUD INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV R4,*STACK CI R1,3 ; Is this slot 3 ? JNE ZCLOUE ; No, slot 2 MOV @TPRV3,R0 ; Get data for slot 3 LI R3,3 ; Process 3 clouds JMP ZCLOUF ZCLOUE MOV @TPRV2,R0 ; Get data for slot 2 LI R3,4 ; Process 4 clouds ZCLOUF MOV @RTOFF,R4 SLA R4,1 ; Offset in table MOV @CLOUDS(R4),R4 ; Get clouds direction *-------------------------------------------------------------- * Process Y of 1st sprite of cloud *-------------------------------------------------------------- ZCLOUG MOV *R0,R1 ; Get YX AB R4,R1 ; Y = Y + (direction offset Y) CB R1,@ZCLDAT ; Avoid VDP "End-Of-Sprites" >D0 JNE ZCLOUH AI R1,>0100 ; Skip >D0 *-------------------------------------------------------------- * Process X of 1st sprite of cloud *-------------------------------------------------------------- ZCLOUH SWPB R1 ; Switch to XY SWPB R4 ; Get direction offset 4 AB R4,R1 ; X = X + (direction offset X) SWPB R4 *-------------------------------------------------------------- * Wrap cloud if playfield boundary reached *-------------------------------------------------------------- CB R1,@ZCLDAT+1 ; Right part of playfield reached ? JL ZCLOUI MOVB @ZCLDAT+3,R1 ; Reset to left border of playfield JMP ZCLOUJ ZCLOUI CB R1,@NULL ; Left part of playfield reached ? JNE ZCLOUJ MOVB @ZCLDAT+1,R1 ; X = D8 ZCLOUJ SWPB R1 ; Switch to YX MOV R1,*R0 ; Write YX to RAMSAT *-------------------------------------------------------------- * Process 2nd sprite of cloud *-------------------------------------------------------------- ZCLOUK AI R0,4 ; Offset 2nd sprite MOV R1,*R0 ; Copy calculated XY to 2nd sprite *-------------------------------------------------------------- * Update Y position of overlay "block" *-------------------------------------------------------------- SWPB R1 ; Switch to XY CB R1,@ZCLDAT+2 ; Right playfield border reached ? JL ZCLOUN ; No, no block repositioning necessary SWPB R1 ; Switch to YX CI R0,SPR13 ; Decide on big cloud or small cloud block JL ZCLOUM MOVB R1,@SPR3 ; Update Y position of Block 1 JMP ZCLOUN ; ZCLOUM MOVB R1,@SPR4 ; Update Y position of Block 2 *-------------------------------------------------------------- * Avoid overlapping overlay blocks *-------------------------------------------------------------- ZCLOUN CLR R1 MOVB @SPR3,R1 SB @SPR4,R1 ABS R1 CI R1,>0F00 ; Distance between Y1 & Y2 > 15 ? JGT ZCLOUP ; Yes, skip processing MOVB @SPR3,R1 AI R1,>1000 ; Y2 = Y1 + 16 CI R1,>D000 ; Avoid End-of-Sprites JNE ZCLOUO AI R1,>0100 ZCLOUO MOVB R1,@SPR4 *-------------------------------------------------------------- * Prepare for next cloud *-------------------------------------------------------------- ZCLOUP AI R0,4 ; Offset for next cloud DEC R3 ; Next cloud JNE ZCLOUG ; Loop B @POPRG4 ZCLDAT DATA >D0D8,>C020 ; Cloud boundary: from YX -- to YX *************************************************************** * IRDY/ZRDY - Animation for showing "ready text" ********@*****@*********************@************************** * REMARKS * Text animator runs in slot 9 * Color blinking runs in slot 10 * * First controller chains to second controller *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** *-------------------------------------------------------------- * Constructor *-------------------------------------------------------------- IRDY INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK *-------------------------------------------------------------- * Load font *-------------------------------------------------------------- SOC @BIT0,@STATUS ; Set intro busy flag BL @VDPADR DATA GETPDT ; Get pattern descriptor table address MOV @OUTP0,R1 ; Result is in @OUTP0 AI R1,33*8 LI R0,ISVDP BL @XCPY DATA CPYROM,LA,7*8 ; 33-34-35-36-37-38-39 Copy A-B-C-D-E-F-G DATA CPYROM,LL,8 ; 40 Copy L DATA CPYROM,LP,8 ; 41 Copy P DATA CPYROM,LR,8*3 ; 42-43-44 Copy R-S-T DATA CPYROM,LY,8 ; 45 Copy Y DATA CPYROM,DIGITS,10*8 ; 46...55 Copy 0-1-2-3-4-5-6-7-8-9 DATA CPYROM,DIGITS,10*8 ; 56...65 Copy 0-1-2-3-4-5-6-7-8-9 DATA CPYROM,LA,8 ; 66 Copy A DATA CPYROM,AD,8*2 ; 67-68 Copy .D. DATA 0 *-------------------------------------------------------------- * Put text on screen *-------------------------------------------------------------- BL @PUTTX DATA >0809,TXT1 ; X=08/Y=09;'PLAYER 1' BL @PUTTX DATA >080D,T1910 ; X=08/Y=13;'A.D.1910' BL @PUTTX DATA >0811,TSTAGE ; X=08/Y=17;'STAGE 1' BL @MKSLOT DATA 9,300,ZRDY ; Wait 6 seconds before removing text BL @MKSLOT DATA 10,4,ZBLNK BL @OSHIP ; Show tile part of Time Pilot fighter B @POPRG1 ; Exit *-------------------------------------------------------------- * Controller part 1 - Remove text *-------------------------------------------------------------- ZRDY INCT STACK MOV R11,*STACK ; PUSH RET address BL @FIBOX DATA 8,9,8,1,32 ; Remove text BL @FIBOX DATA 8,13,8,5,32 ; Remove text BL @MKSLOT DATA 9,100,ZRDY2 ; Stop tune after approx. 1,5 seconds CLR @TSLT10 ; Self-destruct slot 10 SZC @BIT0,@STATUS ; Clear intro busy flag B @POPRET ; Exit TXT1 BYTE 8,41,40,33,45,37,42,32,47 ; 'PLAYER 1' TXT2 BYTE 5,42,37,33,36,45 ; 'READY' TSTAGE BYTE 7,43,44,33,39,37,32,47 ; 'STAGE 1' T1910 BYTE 7,66,67,68,57,65,57,56 ; 'A.D.1910' *-------------------------------------------------------------- * Controller part 2 - Stop playing tune *-------------------------------------------------------------- ZRDY2 INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK CLR R0 BL @EPSGMD ; Turn off tune CLR @TSLT9 ; Self-destruct slot 9 BL @MKSLOT DATA 6,1,GAME ; Controller 6 - Intro controller LI R0,>0001 MOV R0,@TPRV6 ; For sprite rotation B @POPRG0 ; Exit *************************************************************** * ZBLNK - Blink text in read/white/blue ********@*****@*********************@************************** ZBLNK INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK BL @VDPADR DATA GETPCT MOV @OUTP0,R0 AI R0,7 MOV @TPRV10,R1 MOVB @ZCOLOR(R1),R1 ; Color SRL R1,8 LI R2,2 BL @FVRAMX INC @TPRV10 ; Increase counter (private variable slot 10) C @TPRV10,@PLS3 JNE ZBLNKZ CLR @TPRV10 ; Reset counter (private variable slot 10) ZBLNKZ B @POPRG2 ZCOLOR BYTE >F4,>64,>54 *************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot5.a99 * * This file contains sprite defintions, character patterns, * color setup, etc. *************************************************************** *-------------------------------------------------------------- * Frame sequence for rotating ship (ROM) *-------------------------------------------------------------- ROTATE DATA FGHT1 ; Frame 0 DATA FGHT2 ; Frame 1 DATA FGHT3 ; Frame 2 DATA FGHT4 ; Frame 3 DATA FGHT5 ; Frame 4 DATA FGHT6 ; Frame 5 DATA FGHT7 ; Frame 6 DATA FGHT8 ; Frame 7 DATA FGHT9 ; Frame 8 DATA FGHTA ; Frame 9 DATA FGHTB ; Frame 10 DATA FGHTC ; Frame 11 DATA FGHTD ; Frame 12 DATA FGHTE ; Frame 13 DATA FGHTF ; Frame 14 DATA FGHTE ; Frame 15 DATA FGHTD ; Frame 16 DATA FGHTC ; Frame 17 DATA FGHTB ; Frame 18 DATA FGHTA ; Frame 19 DATA FGHT9 ; Frame 20 DATA FGHT8 ; Frame 21 DATA FGHT7 ; Frame 22 DATA FGHT6 ; Frame 23 DATA FGHT5 ; Frame 24 DATA FGHT4 ; Frame 25 DATA FGHT3 ; Frame 26 DATA FGHT2 ; Frame 27 *-------------------------------------------------------------- * Fighter shooting bullets - position and direction (ROM) *-------------------------------------------------------------- * Second table where values are multipled with 2 for faster * shooting is possible, e.g. for later level FIREDR DATA >5E55,>00FE ; Frame 0 x+0 y-2 DATA >6156,>01FE ; Frame 1 x+1 y-2 DATA >6356,>01FE ; Frame 2 x+1 y-2 DATA >6456,>02FE ; Frame 3 x+2 y-2 DATA >6856,>02FE ; Frame 4 x+2 y-2 DATA >6859,>02FF ; Frame 5 x+2 y-1 DATA >685B,>02FF ; Frame 6 x+2 y-1 DATA >685D,>02FF ; Frame 7 x+2 y-1 DATA >6860,>0200 ; Frame 8 x+2 y+0 DATA >6863,>0201 ; Frame 9 x+2 y+1 DATA >6863,>0201 ; Frame 10 x+2 y+1 DATA >6668,>0202 ; Frame 11 x+2 y+2 DATA >6668,>0102 ; Frame 12 x+1 y+2 DATA >6268,>0102 ; Frame 13 x+1 y+2 DATA >6068,>0002 ; Frame 14 x+0 y+2 DATA >5B68,>FF02 ; Frame 15 x-1 y+2 DATA >5A68,>FF02 ; Frame 16 x-1 y+2 DATA >5866,>FE02 ; Frame 17 x-2 y+2 DATA >5763,>FE01 ; Frame 18 x-2 y+1 DATA >5763,>FE01 ; Frame 19 x-2 y+1 DATA >5760,>FE00 ; Frame 20 x-2 y+0 DATA >575F,>FEFF ; Frame 21 x-2 y-1 DATA >575E,>FEFF ; Frame 22 x-2 y-1 DATA >575B,>FEFE ; Frame 23 x-2 y-2 DATA >5758,>FEFE ; Frame 24 x-2 y-2 DATA >5A55,>FFFE ; Frame 25 x-1 y-2 DATA >5C55,>FFFE ; Frame 26 x-1 y-2 DATA >5D55,>FFFE ; Frame 27 x-1 y-2 *-------------------------------------------------------------- * Clouds YX direction based on ship rotation (ROM) *-------------------------------------------------------------- CLOUDS DATA >0200 ; Frame 1 y+2 x+0 DATA >02FF ; Frame 2 y+2 x-1 DATA >02FF ; Frame 3 y+2 x-1 DATA >02FF ; Frame 4 y+2 x-1 DATA >02FE ; Frame 5 y+2 x-2 DATA >01FE ; Frame 6 y+1 x-2 DATA >01FE ; Frame 7 y+1 x-2 DATA >01FE ; Frame 8 y+1 x-2 DATA >00FE ; Frame 9 y+0 x-2 DATA >FFFE ; Frame 10 y-1 x-2 DATA >FFFE ; Frame 11 y-1 x-2 DATA >FEFE ; Frame 12 y-2 x-2 DATA >FEFF ; Frame 13 y-2 x-1 DATA >FEFF ; Frame 14 y-2 x-1 DATA >FE00 ; Frame 15 y-2 x+0 DATA >FE01 ; Frame 16 y-2 x+1 DATA >FE01 ; Frame 17 y-2 x+1 DATA >FE02 ; Frame 18 y-2 x+2 DATA >FF02 ; Frame 19 y-1 x+2 DATA >FF02 ; Frame 20 y-1 x+2 DATA >0002 ; Frame 21 y+0 x+2 DATA >0102 ; Frame 22 y+1 x+2 DATA >0102 ; Frame 23 y+1 x+2 DATA >0102 ; Frame 24 y+1 x+2 DATA >0202 ; Frame 25 y+2 x+2 DATA >0201 ; Frame 26 y+2 x+1 DATA >0201 ; Frame 27 y+2 x+1 DATA >0201 ; Frame 28 y+2 x+1 *************************************************************** * Game sprites in ROM ********@*****@*********************@************************** ROMSAT DATA >5758,>400F ; Sprite 1 - Y=57/X=58/Char 40/White Fighter White DATA >5758,>440D ; Sprite 2 - Y=57/X=58/Char 44/Magenta Fighter Magenta DATA >20D8,>888C ; Sprite 3 - Y=20/X=E0/Char 88/Black Overlay block 1 DATA >30D8,>888F ; Sprite 4 - Y=30/X=E0/Char 88/Black Overlay block 2 DATA >3030,>788F ; Sprite 5 - Y=30/X=30/Char 78/White Big cloud white DATA >3030,>7C8E ; Sprite 6 - Y=30/X=30/Char 7C/Gray Big cloud gray DATA >6590,>788F ; Sprite 7 - Y=65/X=90/Char 78/White Big cloud white DATA >6590,>7C8E ; Sprite 8 - Y=65/X=90/Char 7C/Gray Big cloud gray DATA >9550,>788F ; Sprite 9 - Y=95/X=50/Char 78/White Big cloud white DATA >9550,>7C8E ; Sprite 10 - Y=95/X=50/Char 7C/Gray Big cloud gray DATA >05A0,>788F ; Sprite 11 - Y=05/X=A0/Char 78/White Big cloud white DATA >05A0,>7C8E ; Sprite 12 - Y=05/X=A0/Char 7C/Gray Big cloud gray DATA >4040,>808F ; Sprite 13 - Y=40/X=40/Char 80/White Small cloud white DATA >4040,>848E ; Sprite 14 - Y=40/X=40/Char 84/Gray Small cloud gray DATA >10A8,>808F ; Sprite 15 - Y=10/X=A8/Char 80/White Small cloud white DATA >10A8,>848E ; Sprite 16 - Y=10/X=A8/Char 84/Gray Small cloud gray DATA >A570,>808F ; Sprite 17 - Y=A5/X=88/Char 80/White Small cloud white DATA >A570,>848E ; Sprite 18 - Y=A5/X=88/Char 84/Gray Small cloud gray DATA >E000,>0000 ; Sprite 19 - FREE DATA >E000,>0000 ; Sprite 20 - FREE DATA >E000,>0000 ; Sprite 21 - FREE DATA >E000,>0000 ; Sprite 22 - FREE DATA >E000,>0000 ; Sprite 23 - FREE DATA >E000,>0000 ; Sprite 24 - FREE DATA >E000,>0000 ; Sprite 25 - FREE DATA >E000,>0000 ; Sprite 26 - FREE DATA >E000,>0000 ; Sprite 27 - FREE DATA >E000,>0000 ; Sprite 28 - FREE DATA >E000,>0000 ; Sprite 29 - FREE DATA >E000,>0000 ; Sprite 30 - FREE DATA >E000,>0000 ; Sprite 31 - FREE DATA >E000,>0000 ; Sprite 32 - FREE *************************************************************** * SPRITE PATTERNS: Fighter (ROM) ********@*****@************************************************ FGHT1 BYTE >00,>01,>01,>01,>01,>01,>00,>00 White BYTE >00,>00,>08,>19,>3D,>01,>01,>00 BYTE >00,>00,>00,>80,>80,>80,>C0,>C0 BYTE >40,>40,>F0,>B8,>8C,>80,>00,>00 BYTE >00,>00,>00,>02,>02,>02,>06,>06 Magenta BYTE >04,>0C,>16,>26,>42,>66,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>20,>00,>40,>70,>4C,>00,>00 FGHT2 BYTE >00,>00,>00,>00,>01,>01,>02,>00 White BYTE >04,>0C,>1E,>3B,>07,>06,>02,>00 BYTE >00,>40,>C0,>C0,>C0,>C0,>C0,>80 BYTE >00,>00,>60,>70,>70,>60,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 Magenta BYTE >00,>00,>01,>04,>38,>01,>01,>00 BYTE >00,>00,>20,>20,>20,>20,>20,>40 BYTE >60,>F0,>90,>88,>8C,>9C,>8C,>00 FGHT3 BYTE >00,>00,>00,>00,>01,>01,>02,>00 White BYTE >00,>04,>0F,>1E,>0D,>00,>00,>00 BYTE >20,>60,>E0,>C0,>C0,>C0,>80,>00 BYTE >00,>40,>C0,>C0,>E0,>60,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>04 Magenta BYTE >1C,>38,>30,>01,>02,>01,>00,>00 BYTE >00,>10,>10,>30,>30,>20,>60,>E0 BYTE >E0,>A0,>20,>30,>10,>90,>20,>00 FGHT4 BYTE >00,>00,>00,>00,>00,>00,>00,>00 White BYTE >00,>06,>0F,>1E,>0D,>01,>00,>0 BYTE >00,>18,>30,>70,>70,>E0,>60,>20 BYTE >00,>40,>E0,>E0,>E0,>C0,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>02,>0E Magenta BYTE >1C,>39,>30,>21,>02,>00,>00,>00 BYTE >00,>00,>08,>08,>08,>10,>10,>50 BYTE >F0,>B0,>10,>10,>10,>30,>E0,>00 FGHT5 BYTE >00,>00,>00,>00,>00,>00,>00,>04 White BYTE >1C,>3F,>17,>07,>03,>02,>00,>00 BYTE >00,>00,>06,>1C,>78,>70,>60,>40 BYTE >00,>80,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>02,>1C,>78 Magenta BYTE >63,>00,>08,>18,>04,>01,>00,>00 BYTE >00,>00,>00,>02,>04,>08,>10,>A0 BYTE >E0,>40,>80,>80,>80,>00,>00,>00 FGHT6 BYTE >00,>00,>00,>00,>00,>00,>00,>3C White BYTE >7F,>37,>0F,>06,>04,>00,>00,>00 BYTE >00,>00,>00,>03,>1E,>3C,>38,>20 BYTE >80,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>3C,>03 Magenta BYTE >00,>08,>10,>0A,>03,>06,>00,>00 BYTE >00,>00,>00,>00,>01,>03,>46,>D8 BYTE >70,>C0,>80,>00,>00,>00,>00,>00 FGHT7 BYTE >00,>00,>00,>00,>00,>00,>00,>38 White BYTE >7C,>6F,>1F,>0E,>08,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>3F,>7C,>E0 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 Magenta BYTE >03,>10,>20,>11,>06,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>03,>1C BYTE >F0,>C0,>80,>80,>00,>00,>00,>00 FGHT8 BYTE >00,>00,>00,>00,>00,>60,>78,>3E White BYTE >6C,>1F,>1E,>0E,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>7F,>3C BYTE >E0,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>04,>40 Magenta BYTE >13,>20,>21,>11,>0E,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>02 BYTE >1C,>C0,>00,>00,>00,>00,>00,>00 FGHT9 BYTE >00,>00,>00,>00,>20,>30,>3C,>66 White BYTE >1C,>0F,>0E,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>3C BYTE >FF,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>40,>40,>40,>18 Magenta BYTE >23,>30,>11,>0E,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>FE,>00,>00,>00,>00,>00,>00 FGHTA BYTE >00,>00,>00,>10,>18,>3C,>3C,>06 White BYTE >3E,>1F,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>20 BYTE >78,>7E,>9F,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>20,>24,>02,>00,>38 Magenta BYTE >41,>20,>1F,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >80,>80,>60,>1E,>00,>00,>00,>00 FGHTB BYTE >00,>00,>00,>0C,>0E,>0E,>06,>3F White BYTE >1F,>06,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>10 BYTE >F8,>7C,>1E,>07,>00,>00,>00,>00 BYTE >00,>00,>00,>13,>11,>10,>39,>00 Magenta BYTE >60,>39,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>80,>00,>00,>C0 BYTE >00,>80,>60,>18,>06,>00,>00,>00 FGHTC BYTE >00,>00,>00,>0C,>0E,>0E,>1C,>3C White BYTE >3E,>03,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >20,>70,>F8,>78,>1C,>04,>00,>00 BYTE >00,>00,>00,>03,>11,>11,>22,>42 Magenta BYTE >C1,>7C,>03,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>80,>80,>80,>40,>40 BYTE >00,>80,>00,>80,>20,>18,>00,>00 FGHTD BYTE >00,>00,>01,>01,>0D,>1F,>1F,>01 White BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>80,>C0,>C0,>C0,>88,>80,>80 BYTE >68,>38,>38,>1C,>0C,>04,>04,>00 BYTE >00,>00,>02,>0E,>12,>20,>20,>1E Magenta BYTE >03,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>30,>38,>38,>50,>48,>48 BYTE >80,>C0,>60,>20,>10,>08,>00,>00 FGHTE BYTE >00,>00,>01,>01,>1D,>1F,>0F,>03 White BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>80,>C0,>C0,>C0,>00,>00,>00 BYTE >10,>70,>70,>30,>30,>30,>10,>00 BYTE >00,>00,>00,>0E,>22,>20,>10,>0C Magenta BYTE >07,>01,>01,>00,>00,>00,>00,>00 BYTE >00,>00,>30,>38,>38,>90,>90,>90 BYTE >C0,>80,>80,>C0,>40,>40,>20,>00 FGHTF BYTE >00,>00,>01,>31,>1D,>0F,>02,>02 White BYTE >03,>03,>01,>01,>01,>00,>00,>00 BYTE >00,>80,>80,>BC,>98,>10,>00,>00 BYTE >00,>00,>80,>80,>80,>80,>80,>00 BYTE >00,>00,>32,>0E,>02,>00,>04,>00 Magenta BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>00,>66,>42,>64,>68,>30,>20 BYTE >60,>60,>40,>40,>40,>00,>00,>00 *************************************************************** * TILE PATTERNS: Fighter (ROM) ********@*****@************************************************ TFGHT1 BYTE >00,>00,>00,>00,>00,>00,>01,>01 Blue BYTE >23,>23,>21,>00,>00,>00,>20,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >88,>88,>08,>00,>00,>00,>08,>00 TFGHT2 BYTE >00,>00,>00,>00,>00,>00,>01,>03 Blue BYTE >0B,>13,>00,>00,>00,>20,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >80,>04,>04,>04,>00,>00,>00,>08 TFGHT3 BYTE >00,>00,>00,>00,>00,>00,>01,>0B Blue BYTE >03,>02,>00,>20,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>08,>08,>00,>00,>00,>40,>00 TFGHT4 BYTE >00,>00,>00,>00,>00,>00,>05,>01 Blue BYTE >03,>00,>00,>00,>20,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>80,>80 BYTE >00,>00,>04,>08,>00,>00,>00,>80 TFGHT5 BYTE >00,>00,>00,>00,>00,>05,>03,>03 Blue BYTE >00,>40,>00,>00,>00,>00,>04,>00 BYTE >00,>00,>00,>00,>00,>80,>80,>00 BYTE >00,>00,>20,>40,>00,>00,>00,>00 TFGHT6 BYTE >00,>00,>00,>00,>00,>01,>03,>00 Blue BYTE >00,>00,>00,>00,>00,>08,>00,>00 BYTE >00,>00,>00,>00,>00,>C0,>80,>00 BYTE >00,>00,>40,>80,>00,>00,>00,>00 TFGHT7 BYTE >00,>00,>00,>00,>00,>00,>03,>07 Blue BYTE >00,>00,>00,>00,>20,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>80,>00 BYTE >00,>00,>60,>00,>00,>00,>00,>00 TFGHT8 BYTE >00,>00,>00,>00,>00,>00,>03,>01 Blue BYTE >00,>00,>00,>20,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>80,>C0 BYTE >00,>00,>C0,>00,>00,>00,>00,>00 TFGHT9 BYTE >00,>00,>00,>00,>00,>00,>03,>01 Blue BYTE >00,>00,>20,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>80,>C0 BYTE >00,>00,>E0,>00,>00,>00,>00,>00 TFGHTA BYTE >00,>00,>00,>00,>00,>00,>03,>41 Blue BYTE >00,>00,>00,>03,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>00,>80,>C0 BYTE >00,>00,>00,>00,>80,>00,>00,>00 TFGHTB BYTE >00,>00,>00,>00,>00,>01,>00,>40 Blue BYTE >00,>00,>03,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>C0,>E0,>20 BYTE >00,>00,>00,>00,>00,>00,>00,>00 TFGHTC BYTE >00,>00,>02,>00,>00,>00,>01,>81 Blue BYTE >00,>00,>10,>08,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>40,>A0,>80 BYTE >C0,>00,>00,>00,>00,>00,>00,>00 TFGHTD BYTE >00,>00,>00,>10,>00,>00,>00,>00 Blue BYTE >04,>02,>00,>00,>00,>00,>00,>00 BYTE >00,>20,>00,>00,>00,>24,>34,>30 BYTE >10,>00,>00,>00,>00,>00,>00,>00 TFGHTE BYTE >00,>00,>10,>00,>00,>00,>00,>00 Blue BYTE >08,>04,>04,>00,>00,>00,>00,>00 BYTE >00,>20,>00,>00,>00,>68,>68,>60 BYTE >20,>00,>00,>00,>00,>00,>00,>00 TFGHTF BYTE >00,>10,>00,>00,>00,>10,>11,>11 Blue BYTE >00,>00,>00,>00,>00,>00,>00,>00 BYTE >00,>04,>00,>00,>00,>84,>C4,>C4 BYTE >80,>80,>00,>00,>00,>00,>00,>00 *************************************************************** * SPRITE PATTERNS: Clouds (ROM) ********@*****@************************************************ * Large cloud BGCLD1 BYTE >00,>00,>00,>0C,>2D,>7F,>5F,>5F White BYTE >5E,>CF,>6F,>32,>40,>00,>00,>00 BYTE >00,>00,>00,>E0,>70,>E0,>BC,>7A BYTE >FD,>FF,>FF,>FE,>6C,>00,>00,>00 BGCLD2 BYTE >00,>00,>00,>00,>12,>00,>20,>20 Gray BYTE >21,>30,>10,>4D,>32,>00,>00,>00 BYTE >00,>00,>00,>00,>80,>10,>40,>84 BYTE >02,>00,>00,>01,>92,>EC,>00,>00 * Small cloud BGCLD3 BYTE >00,>00,>00,>07,>0B,>1D,>0E,>0E White BYTE >35,>17,>03,>00,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>80,>A0,>F0,>F8 BYTE >7C,>F0,>00,>00,>00,>00,>00,>00 BGCLD4 BYTE >00,>00,>00,>00,>04,>02,>11,>11 Gray BYTE >0A,>28,>1C,>03,>00,>00,>00,>00 BYTE >00,>00,>00,>00,>00,>40,>00,>00 BYTE >80,>0C,>D0,>00,>00,>00,>00,>00 *************************************************************** * SPRITE PATTERNS: Utilities and Enemies (ROM) ********@*****@************************************************ BLOCK BYTE >FF,>FF,>FF,>FF,>FF,>FF,>FF,>FF BYTE >FF,>FF,>FF,>FF,>FF,>FF,>FF,>FF BYTE >FF,>FF,>FF,>FF,>FF,>FF,>FF,>FF BYTE >FF,>FF,>FF,>FF,>FF,>FF,>FF,>FF *************************************************************** * KONAMI Game Font - from Konami's Athletic Land for MSX * Letter A-Z ********@*****@************************************************ LA BYTE >00,>1C,>36,>63,>63,>7F,>63,>63 A LB BYTE >00,>7E,>63,>63,>7E,>63,>63,>7E B LC BYTE >00,>3E,>63,>60,>60,>60,>63,>3E C LD BYTE >00,>7C,>66,>63,>63,>63,>66,>7C D LE BYTE >00,>7F,>60,>60,>7E,>60,>60,>7F E LF BYTE >00,>7F,>60,>60,>7E,>60,>60,>60 F LG BYTE >00,>3E,>63,>60,>67,>63,>63,>3F G LH BYTE >00,>63,>63,>63,>7F,>63,>63,>63 H LI BYTE >00,>3C,>18,>18,>18,>18,>18,>3C I LJ BYTE >00,>1F,>06,>06,>06,>06,>66,>3C J LK BYTE >00,>63,>66,>6C,>78,>7C,>6E,>67 K LL BYTE >00,>60,>60,>60,>60,>60,>60,>7F L LM BYTE >00,>63,>77,>7F,>7F,>6B,>63,>63 M LN BYTE >00,>63,>73,>7B,>7F,>6F,>67,>63 N LO BYTE >00,>3E,>63,>63,>63,>63,>63,>3E O LP BYTE >00,>7E,>63,>63,>63,>7E,>60,>60 P LQ BYTE >00,>3E,>63,>63,>63,>6F,>66,>3D Q LR BYTE >00,>7E,>63,>63,>62,>7C,>66,>63 R LS BYTE >00,>3E,>63,>60,>3E,>03,>63,>3E S LT BYTE >00,>7E,>18,>18,>18,>18,>18,>18 T LU BYTE >00,>63,>63,>63,>63,>63,>63,>3E U LV BYTE >00,>63,>63,>63,>63,>36,>1C,>08 V LW BYTE >00,>63,>63,>6B,>6B,>7F,>77,>22 W LX BYTE >00,>63,>76,>3C,>1C,>1E,>37,>63 X LY BYTE >00,>66,>66,>7E,>3C,>18,>18,>18 Y LZ BYTE >00,>7F,>07,>0E,>1C,>38,>70,>7F Z LETTRS EQU LA *************************************************************** * KONAMI Game Font - from Konami's Athletic Land for MSX * Digits 0-9, SPACE and HYPHEN ********@*****@************************************************ D0 BYTE >00,>1C,>22,>63,>63,>63,>22,>1C 0 D1 BYTE >00,>18,>38,>18,>18,>18,>18,>7E 1 D2 BYTE >00,>3E,>63,>03,>0E,>3C,>70,>7F 2 D3 BYTE >00,>3E,>63,>03,>0E,>03,>63,>3E 3 D4 BYTE >00,>0E,>1E,>36,>66,>66,>7F,>06 4 D5 BYTE >00,>7F,>60,>7E,>63,>03,>63,>3E 5 D6 BYTE >00,>3E,>63,>60,>7E,>63,>63,>3E 6 D7 BYTE >00,>7F,>63,>06,>0C,>18,>18,>18 7 D8 BYTE >00,>3E,>63,>63,>3E,>63,>63,>3E 8 D9 BYTE >00,>3E,>63,>63,>3F,>03,>63,>3E 9 DA BYTE >00,>00,>00,>00,>00,>00,>00,>00 SPACE DB BYTE >00,>00,>00,>7E,>00,>00,>00,>00 - DIGITS EQU D0 *************************************************************** * Special characters for building the 'A.D.1910' string ********@*****@************************************************ AD BYTE >00,>0F,>0C,>0C,>0C,>0C,>6C,>6F .D BYTE >00,>80,>C0,>60,>60,>60,>CC,>8C D. BETA BYTE >CE,>A8,>A8,>CE,>A8,>A8,>CE,>00 Beta pattern - BE CHAR >F3 BYTE >E4,>4A,>4A,>4E,>4A,>4A,>4A,>00 Beta pattern - TA CHAR >F4 BYTE >06,>09,>09,>E9,>09,>09,>06,>00 Beta pattern - -0 CHAR >F5 * BYTE >04,>0C,>14,>04,>04,>04,>4E,>00 Beta pattern - .1 CHAR >F6 * BYTE >0C,>12,>02,>04,>08,>10,>5E,>00 Beta pattern - .2 CHAR >F6 BYTE >0C,>12,>02,>0C,>02,>12,>4C,>00 Beta pattern - .3 CHAR >F6 * BYTE >28,>28,>28,>3C,>08,>08,>48,>00 Beta pattern - .4 CHAR >F6 *************************************************************** * Color table during game play ********@*****@************************************************ * 00-0F >380->381 >F1,>F1 White/Black * 10-27 >382->383 >61,>61,>3C Medium red/Black * 28-2F >385 >C7 **FREE BUT BCKGR MUST BE CYAN** * 30-3F >386->387 >37,>37 Light green/Cyan * 40-47 >388 >98 Light red/Medium red * 48-4F >389 >80 Medium red/Black * 50-57 >38A >87 Medium red/Cyan * 58-5F >38B >8F Medium red/White * 60-67 >38C >1B Black/Light yellow * 68-87 >38D->390 >C7,>C7,>C7,>C7 Dark green/Cyan * 88-97 >391->392 >F0,>F0 White/Transparant * 98-9F >393 >1B Black/Light yellow * A0-BF >394->397 >7B,>7B,>7B,>7B Cyan/Light yellow -> fg color gets overwritten: water/quicksand * C0-C7 >398 >6B Medium red/Light yellow * C8-CF >399->39B >00,>00,>00 Transparant/Transparant (Not used) * E0-EF >39C->39D >1C,>1C Dark yellow/Dark green * F0-FF >39E->39F >1C,>1C Black/Dark green ********@*****@************************************************ COLORS BYTE >F1,>F1,>61,>F1,>F4,>F4,>F4,>F4 BYTE >F4,>C1,>C1,>C1,>C1,>C1,>C1,>C4 BYTE >C4,>C4,>C4,>C4,>C4,>C4,>C4,>C4 BYTE >C4,>C4,>C4,>C4,>C4,>C4,>C4,>C4 *************************************************************** * Strings to display ********@*****@************************************************ STR1 BYTE 4,17,18,16,17 ; 'HIGH' STR2 BYTE 4,22,24,20,19 ; '1-UP' STR3 BYTE 6,0,0,0,0,0,0 ; 000000 STR4 BYTE 5,25,26,27,28,29 ; BETA-0.x *************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot5.a99 * * This file contains game music and sound effects *************************************************************** *************************************************************** * Game introduction tune ********@*****@************************************************ SND1 BYTE >0D,>00,>FF,>00,>08,>80,>00,>08,>80,>00,>08,>80 BYTE >00,>08,>80,>00,>FF,>80,>FF,>00,>08,>80,>00,>08 BYTE >80,>00,>08,>80,>00,>08,>80,>00,>FF,>80,>FF,>00 BYTE >08,>80,>00,>08,>80,>00,>08,>80,>00,>08,>80,>00 BYTE >FF,>80,>FF,>00,>08,>80,>00,>08,>80,>00,>08,>80 BYTE >00,>08,>80,>00,>FF,>80,>FF,>00,>08,>80,>00,>08 BYTE >80,>00,>08,>80,>00,>08,>80,>00,>FF,>80,>FF,>00 BYTE >08,>80,>00,>08,>80,>00,>08,>80,>00,>08,>80,>00 BYTE >FF,>80,>FF,>00,>08,>80,>00,>08,>80,>00,>08,>80 BYTE >00,>08,>80,>00,>FF,>80,>FF,>00,>08,>80,>00,>08 BYTE >80,>00,>08,>80,>00,>08,>80,>00,>FF,>80,>FF,>00 BYTE >08,>80,>00,>08,>80,>00,>08,>80,>00,>08,>80,>00 BYTE >FF,>80,>FF,>00,>08,>80,>00,>08,>80,>00,>08,>80 BYTE >00,>08,>80,>00,>FF,>80,>FF,>00,>08,>80,>00,>08 BYTE >80,>00,>08,>80,>00,>08,>80,>00,>FF,>80,>FF,>00 BYTE >08,>80,>00,>08,>80,>00,>08,>80,>00,>08,>80,>00 BYTE >FF,>80,>FF,>00,>08,>80,>00,>08,>80,>00,>08,>80 BYTE >00,>08,>80,>00,>FF,>80,>FF,>00,>08,>80,>00,>08 BYTE >80,>00,>08,>80,>00,>08,>80,>00,>FF,>80,>FF,>00 BYTE >08,>80,>00,>08,>80,>00,>08,>80,>00,>08,>80,>00 BYTE >FF,>80,>FF,>00,>08,>80,>00,>08,>80,>00,>08,>80 BYTE >00,>08,>80,>00,>FF,>80,>08,>FF,>00,>00,>6E,>01 BYTE >6E,>01,>37,>02,>BB,>02,>76,>01,>76,>01,>41,>02 BYTE >BB,>02,>7B,>01,>D9,>01,>4E,>02,>BB,>02,>81,>01 BYTE >DF,>01,>5C,>02,>BB,>02,>88,>01,>E6,>01,>68,>02 BYTE >BB,>02,>8F,>01,>ED,>01,>77,>02,>BB,>02,>9E,>01 BYTE >FC,>01,>83,>02,>BB,>02,>76,>01,>76,>01,>92,>02 BYTE >BB,>02,>A5,>01,>03,>02,>9F,>02,>BB,>02,>B3,>01 BYTE >11,>02,>AA,>02,>BB,>02,>C0,>01,>1E,>02,>76,>01 BYTE >BB,>02,>CC,>01,>2A,>02,>B1,>02,>BB,>02,>D5,>01 BYTE >33,>02,>B7,>02,>C0,>02,>C4,>02,>20,>20,>E1,>1E BYTE >02,>C0,>C4,>02,>20,>1E,>1E,>CA,>02,>20,>1E,>14 BYTE >A0,>CD,>02,>20,>0C,>40,>E1,>1E,>C4,>02,>20,>1E BYTE >10,>85,>62,>C4,>02,>20,>02,>26,>27,>28,>29,>2A BYTE >2B,>EC,>06,>E4,>08,>25,>EB,>02,>20,>00,>E0,>1E BYTE >0E,>C4,>02,>20,>18,>2E,>2F,>30,>31,>F2,>00,>4D BYTE >2E,>2F,>70,>C4,>02,>20,>00,>F3,>00,>F4,>6D,>2E BYTE >6F,>ED,>00,>35,>C4,>02,>20,>0A,>64,>36,>77,>E4 BYTE >00,>F8,>79,>3A,>C4,>02,>20,>7B,>F9,>00,>F8,>E4 BYTE >F9,>18,>03,>01,>20,>1B,>03,>20,>1E,>14,>A0,>1E BYTE >03,>20,>0C,>40,>E1,>1E,>C7,>02,>20,>1E,>10,>9F BYTE >7C,>DC,>02,>20,>02,>39,>3A,>3B,>3C,>3D,>3E,>FF BYTE >06,>F7,>08,>38,>3C,>03,>20,>00,>E0,>1E,>0E,>EE BYTE >02,>20,>18,>3B,>3C,>3D,>3E,>FF,>00,>5A,>3B,>3C BYTE >7D,>F7,>02,>20,>00,>FD,>00,>FE,>77,>38,>79,>F7 BYTE >00,>3F,>06,>03,>20,>0A,>69,>3B,>7C,>E9,>00,>FD BYTE >7E,>3F,>09,>03,>20,>7F,>FD,>00,>FC,>E8,>FD,>69 BYTE >03,>01,>20,>6C,>03,>20,>20,>E1,>1E,>02,>22,>23 BYTE >84,>2D,>03,>20,>0C,>5A,>3B,>BC,>5D,>3E,>FF,>06 BYTE >57,>38,>1B,>03,>20,>BF,>5D,>3E,>FF,>06,>5D,>3E BYTE >BF,>5D,>3E,>5F,>1B,>03,>20,>10,>5D,>3E,>BF,>5D BYTE >3E,>FF,>06,>3D,>1B,>03,>20,>00,>3E,>BF,>5D,>3E BYTE >FF,>06,>5D,>3E,>BF,>5D,>3E,>1B,>03,>20,>FF,>06 BYTE >5D,>3E,>BF,>5D,>3E,>FF,>04,>39,>03,>20,>00,>53 BYTE >34,>B5,>5C,>3D,>FE,>06,>5C,>3D,>BE,>3F,>99,>03 BYTE >20,>00,>20,>E1,>06,>E2,>00,>43,>24,>E5,>00,>51 BYTE >03,>20,>04,>FE,>00,>54,>35,>F6,>06,>FF,>B1,>03 BYTE >20,>00,>E0,>1E,>0E,>B4,>03,>20,>1E,>10,>E0,>C4 BYTE >02,>01,>00,>B7,>03,>20,>1E,>1E,>B7,>03,>01,>00 BYTE >00,>F0,>00,>00,>F1,>00,>0D,>F0,>0F,>00,>F0,>0F BYTE >0D,>FE,>0F,>00,>FE,>0F,>0C,>F0,>0F,>0B,>F0,>0F BYTE >0A,>F0,>0F,>09,>F0,>0F,>08,>F0,>0F,>07,>F0,>0F BYTE >06,>F0,>0F,>0D,>F6,>0D,>0B,>F6,>0D,>09,>F6,>0D BYTE >07,>F6,>0D,>05,>F6,>0D,>03,>F6,>0D,>0D,>F4,>0B BYTE >0D,>FE,>0B,>0D,>F2,>0E,>0B,>FE,>0F,>09,>FE,>0F BYTE >0D,>FD,>10,>0D,>F0,>14,>0B,>F0,>14,>09,>F0,>14 BYTE >00,>F0,>14,>0B,>FF,>0E,>00,>FF,>0E,>0B,>FD,>0F BYTE >00,>FD,>0F,>0A,>FF,>0E,>09,>FF,>0E,>08,>FF,>0E BYTE >07,>FF,>0E,>06,>FF,>0E,>05,>FF,>0E,>04,>FF,>0E BYTE >0B,>F5,>0D,>09,>F5,>0D,>07,>F5,>0D,>05,>F5,>0D BYTE >03,>F5,>0D,>01,>F5,>0D,>0B,>F3,>0B,>0B,>FD,>0B BYTE >0B,>F1,>0E,>09,>FD,>0F,>07,>FD,>0F,>0B,>FC,>10 BYTE >0B,>FF,>13,>09,>FF,>13,>07,>FF,>13,>00,>FF,>13 BYTE >00,>F0,>00,>00,>F1,>00,>0C,>F1,>28,>09,>F1,>28 BYTE >06,>F1,>28,>0D,>F7,>2A,>0A,>F7,>2A,>07,>F7,>2A BYTE >0D,>F1,>28,>0A,>F1,>28,>07,>F1,>28,>0C,>F7,>35 BYTE >09,>F7,>35,>06,>F7,>35,>0C,>F8,>3F,>09,>F8,>3F BYTE >06,>F8,>3F,>00,>F8,>0F,>0C,>FF,>3B,>09,>FF,>3B BYTE >06,>FF,>3B,>00,>FF,>0B,>00,>F7,>05,>00,>F0,>06 BYTE >00,>F6,>00,>00 *************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot_debug.a99 * * This file contains routines used for debugging *************************************************************** *************************************************************** * DEBUG0 - Make overlay sprites visible ********@*****@*********************@************************** DEBUG0 LI R3,>8F00 ; Set to white MOVB R3,@SPR1+3 MOVB R3,@SPR2+3 RT * * COPY 'D:\Projekte\spectra\tms9900\spectra_base.a99' * *************************************************************** * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * This file: spectra_base.a99 *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * X=No input D=Data variant R=Register variant * * * BASE UTILITIES * ============== * POPRG. - X - Pop registers & return to caller * POPRX. - X - Pop registers & return to caller *************************************************************** * ATTENTION! * You have to set the below equates in your main program * after allocating the required memory. * * TIMER EQU ??? ; Timer table * RAMBUF EQU ??? ; RAM buffer for temporary storage * RAMSAT EQU ??? ; Shadow SAT in RAM. **************************************************************** *////////////////////////////////////////////////////////////// * SPECTRA SCRATCH-PAD MEMORY USAGE *////////////////////////////////////////////////////////////// SCRPAD EQU >8300 ; \ 256 bytes scratch-pad SBLOC1 EQU SCRPAD ; | Length 32 bytes SBLOC2 EQU SCRPAD+>20 ; | Length 32 bytes SBLOC3 EQU SCRPAD+>40 ; | Length 128 bytes -> FREE FOR OWN USE SBLOC4 EQU SCRPAD+>C0 ; | Length 32 bytes \ -> SBLOC4 can extend to 64 bytes SBLOC5 EQU SCRPAD+>D0 ; / Length 32 bytes / *////////////////////////////////////////////////////////////// * BLOCK 1 *////////////////////////////////////////////////////////////// WSSPC1 EQU SCRPAD ; 32: SPECTRA workspace 1 *////////////////////////////////////////////////////////////// * BLOCK 2 *////////////////////////////////////////////////////////////// VIRTKB EQU SBLOC2 ; 2: Virtual keyboard VDPREG EQU SBLOC2+2 ; 16: VDP shadow registers VDPSTA EQU SBLOC2+18 ; 2: VDP shadow status register VDPCOL EQU SBLOC2+20 ; 2: VDP screen columns TCOUNT EQU SBLOC2+22 ; 2: Timer Tick counter THIGH EQU SBLOC2+24 ; 2: Timer highest slot in use OUTP0 EQU SBLOC2+26 ; 2: Return parameter 0 OUTP1 EQU SBLOC2+28 ; 2: Return parameter 1 OUTP2 EQU SBLOC2+30 ; 2: Return parameter 2 *////////////////////////////////////////////////////////////// * BLOCK 3 *////////////////////////////////////////////////////////////// FREE EQU SBLOC3 ; 128: Free for own use *////////////////////////////////////////////////////////////// * BLOCK 4 - 5 *////////////////////////////////////////////////////////////// STKBUF EQU SBLOC4 ; 32: Stack (extends to 64!) WSSPC2 EQU SBLOC5 ; 32: SPECTRA workspace 2 *////////////////////////////////////////////////////////////// * EQUATES *////////////////////////////////////////////////////////////// ********@*****@*********************@************************** R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 ********@*****@*********************@************************** ISROM EQU 0 ; Memory Address is in ROM/RAM ISGROM EQU 1 ; Memory Address is in GROM ISVDP EQU 2 ; Memory Address is in VDP ISRAM EQU 3 ; Memory Address is in RAM STACK EQU R8 ; R8 is stack pointer! BE PREPARED! SWAP EQU 1 ; MIRRV: Swap 4x4 patterns 0123 to 2301 NOSWAP EQU 0 ; MIRRV: Don't swap 4x4 patterns ********@*****@*********************@************************** SOUND EQU >8400 ; Sound generator address VDPR EQU >8800 ; VDP read data window address VDPW EQU >8C00 ; VDP write data window address VDPS EQU >8802 ; VDP status register VDPA EQU >8C02 ; VDP address register GRMWA EQU >9C02 ; GROM set write address GRMRA EQU >9802 ; GROM set read address GRMRD EQU >9800 ; GROM read byte GRMWD EQU >9C00 ; GROM write byte *************************************************************** * Virtual keyboard status (VIRTKB). Controlled by KBSCAN ********@*****@*********************@************************** * bit 0: Left ; 0=no 1=yes * bit 1: Right ; 0=no 1=yes * bit 2: Up ; 0=no 1=yes * bit 3: Down ; 0=no 1=yes * bit 4: Space / fire / Q ; 0=no 1=yes * bit 5: ALPHA LOCK down ; 0=no 1=yes * bit 6: Pause ; 0=no 1=yes * bit 7: -Not used- ; 0=no 1=yes * bit 8: REDO ; 0=no 1=yes * bit 9: BACK ; 0=no 1=yes * bit 10: QUIT ; 0=no 1=yes * bit 11: -Not used- ; 0=no 1=yes * bit 12: -Not used- ; 0=no 1=yes * bit 13: -Not used- ; 0=no 1=yes * bit 14: -Not used- ; 0=no 1=yes * bit 15: -Not used- ; 0=no 1=yes ********@*****@*********************@************************** KLFT EQU >8000 ; Virtual key left KRGT EQU >4000 ; Virtual key right KUP EQU >2000 ; Virtual key up KDN EQU >1000 ; Virtual key down KUPLFT EQU >A000 ; Virtual key up + left KUPRGT EQU >6000 ; Virtual key up + right KDNLFT EQU >9000 ; Virtual key down + left KDNRGT EQU >5000 ; Virtual key down + right KFIRE EQU >800 ; Virtual key fire KALPHA EQU >400 ; Virtual key alpha lock KPAUSE EQU >200 ; Virtual key pause KREDO EQU >80 ; Virtual key redo KBACK EQU >40 ; Virtual key back KQUIT EQU >20 ; Virtual key quit *////////////////////////////////////////////////////////////// * SPECTRA ROM *////////////////////////////////////////////////////////////// *************************************************************** * ROM: Constants ********@*****@*********************@************************** BIT0 DATA >8000 ; Binary 1000000000000000 BIT1 DATA >4000 ; Binary 0100000000000000 BIT2 DATA >2000 ; Binary 0010000000000000 BIT3 DATA >1000 ; Binary 0001000000000000 BIT4 DATA >800 ; Binary 0000100000000000 BIT5 DATA >400 ; Binary 0000010000000000 BIT6 DATA >200 ; Binary 0000001000000000 BIT7 DATA >100 ; Binary 0000000100000000 BIT8 DATA >80 ; Binary 0000000010000000 BIT9 DATA >40 ; Binary 0000000001000000 BIT10 DATA >20 ; Binary 0000000000100000 BIT11 DATA >10 ; Binary 0000000000010000 BIT12 DATA >8 ; Binary 0000000000001000 BIT13 DATA >4 ; Binary 0000000000000100 BIT14 DATA >2 ; Binary 0000000000000010 BIT15 DATA >1 ; Binary 0000000000000001 BITMSB DATA >FF00 ; Binary 1111111100000000 BITLSB DATA >00FF ; Binary 0000000011111111 NULL DATA 0 ; Easy compare / assign PLS1 DATA 1 ; Easy compare / assign PLS2 DATA 2 ; Easy compare / assign PLS3 DATA 3 ; Easy compare / assign PLS4 DATA 4 ; Easy compare / assign PLS5 DATA 5 ; Easy compare / assign PLS6 DATA 6 ; Easy compare / assign PLS7 DATA 7 ; Easy compare / assign PLS8 DATA 8 ; Easy compare / assign PLS9 DATA 9 ; Easy compare / assign PLS10 DATA 10 ; Easy compare / assign MIN1 DATA -1 ; Easy compare / assign MIN2 DATA -2 ; Easy compare / assign MIN3 DATA -3 ; Easy compare / assign MIN4 DATA -4 ; Easy compare / assign MIN5 DATA -5 ; Easy compare / assign MIN6 DATA -6 ; Easy compare / assign MIN7 DATA -7 ; Easy compare / assign MIN8 DATA -8 ; Easy compare / assign MIN9 DATA -9 ; Easy compare / assign MIN10 DATA -10 ; Easy compare / assign *////////////////////////////////////////////////////////////// * RAM LOW LEVEL UTILITIES *////////////////////////////////////////////////////////////// *************************************************************** * POPRG. - Pop registers & return to caller *************************************************************** * B @POPRG. *-------------------------------------------------------------- * REMARKS * R11 must be at stack bottom ********@*****@*********************@************************** POPRG9 MOV *STACK,R9 DECT STACK POPRG8 MOV *STACK,R8 DECT STACK POPRG7 MOV *STACK,R7 DECT STACK POPRG6 MOV *STACK,R6 DECT STACK POPRG5 MOV *STACK,R5 DECT STACK POPRG4 MOV *STACK,R4 DECT STACK POPRG3 MOV *STACK,R3 DECT STACK POPRG2 MOV *STACK,R2 DECT STACK POPRG1 MOV *STACK,R1 DECT STACK POPRG0 MOV *STACK,R0 DECT STACK POPRET MOV *STACK,R11 DECT STACK RT *************************************************************** * POPRX. - Pop registers & return to caller *************************************************************** * B @POPRX. *-------------------------------------------------------------- * INPUT * R11= RET address ********@*****@*********************@************************** POPRX9 MOV *STACK,R9 DECT STACK POPRX8 MOV *STACK,R8 DECT STACK POPRX7 MOV *STACK,R7 DECT STACK POPRX6 MOV *STACK,R6 DECT STACK POPRX5 MOV *STACK,R5 DECT STACK POPRX4 MOV *STACK,R4 DECT STACK POPRX3 MOV *STACK,R3 DECT STACK POPRX2 MOV *STACK,R2 DECT STACK POPRX1 MOV *STACK,R1 DECT STACK POPRX0 MOV *STACK,R0 DECT STACK RT * * COPY 'D:\Projekte\spectra\tms9900\spectra_memcpy.a99' * *************************************************************** * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * This file: spectra_memcpy.a99 *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * X=No input D=Data variant R=Register variant * * * MEMORY COPY UTILITIES * ===================== * FILMEM - D - Fill memory range with byte * CPYM - D - Copy memory range * CPYMX - R - Copy memory range * G2VDP - D - Copy GROM memory range to VDP memory * G2VDPX - R - Copy GROM memory range to VDP memory * G2MEM - D - Copy GROM memory range to RAM memory * G2MEMX - R - Copy GROM memory range to RAM memory *************************************************************** *************************************************************** * FILMEM - Fill memory range with byte *************************************************************** * BL @FILMEM * DATA P0,P1,P2 *-------------------------------------------------------------- * INPUT * P0 = Memory start address * P1 = Memory end address * P2 = Byte to fill ********@*****@*********************@************************** FILMEM INCT STACK MOV R0,*STACK+ ; Push R0 MOV R1,*STACK+ ; Push R1 MOV R2,*STACK ; Push R2 MOV *R11+,R0 ; Memory start MOV *R11+,R1 ; Memory end MOV *R11+,R2 ; Byte to fill SWPB R2 FILME1 MOVB R2,*R0+ C R0,R1 JLE FILME1 FILME2 JMP POPRX2 ; Pop registers (R11 set!) and return *************************************************************** * CPYM - Copy memory range (data variant) *************************************************************** * BL @CPYM * DATA P0,P1,P2 *-------------------------------------------------------------- * INPUT * P0 = Memory source address * P1 = Memory target address * P2 = Number of bytes to copy ********@*****@*********************@************************** CPYM INCT STACK MOV R0,*STACK+ ; Push R0 MOV R1,*STACK+ ; Push R1 MOV R2,*STACK ; Push R2 MOV *R11+,R0 ; Memory source address MOV *R11+,R1 ; Memory target address MOV *R11+,R2 ; Bytes to copy CPYM1 MOVB *R0+,*R1+ DEC R2 JNE CPYM1 JMP POPRX2 ; Pop registers (R11 set) and return *************************************************************** * CPYMX - Copy memory range (register variant) *************************************************************** * BL @CPYMX *-------------------------------------------------------------- * INPUT * R0 = Memory source address * R1 = Memory target address * R2 = Number of bytes to copy ********@*****@*********************@************************** CPYMX INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ ; Push R0 MOV R1,*STACK+ ; Push R1 MOV R2,*STACK ; Push R2 CPYMX1 MOVB *R0+,*R1+ DEC R2 JNE CPYMX1 JMP POPRG2 *////////////////////////////////////////////////////////////// * GROM LOW LEVEL UTILITIES *////////////////////////////////////////////////////////////// *************************************************************** * G2VDP - Copy GROM memory range to VDP memory (data variant) *************************************************************** * BL @G2VDP * DATA P0,P1,P2 *-------------------------------------------------------------- * REMARKS * This subroutine overwrites the current GROM address *-------------------------------------------------------------- * INPUT * P0 = GROM source address * P1 = VDP target address * P2 = Number of bytes to copy ********@*****@*********************@************************** G2VDP INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK MOV *R11+,R0 ; GROM source address MOV *R11+,R1 ; VDP target address MOV *R11+,R2 ; Bytes to copy * Set GROM source address G2VDP1 MOVB R0,@GRMWA SWPB R0 MOVB R0,@GRMWA ; Destroys R0. Doesn't matter * Set VDP target address ORI R1,>4000 SWPB R1 MOVB R1,@VDPA SWPB R1 MOVB R1,@VDPA ; Set VDP target address NOP * Copy from GROM to VDP G2VDP2 MOVB @GRMRD,@VDPW ; Copy byte from GROM to VDP DEC R2 JNE G2VDP2 ; Loop until all bytes copied B @POPRX2 ; Exit *************************************************************** * G2VDPX - Copy GROM memory range to VDP memory (register variant) *************************************************************** * BL @G2VDPX *-------------------------------------------------------------- * REMARKS * This subroutine overwrites the current GROM address *-------------------------------------------------------------- * INPUT * R0 = GROM source address * R1 = VDP target address * R2 = Number of bytes to copy ********@*****@*********************@************************** G2VDPX INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK JMP G2VDP1 ; Rest is the same as data variant *************************************************************** * G2MEM - Copy GROM memory range to RAM memory (data variant) *************************************************************** * BL @G2MEM * DATA P0,P1,P2 *-------------------------------------------------------------- * REMARKS * This subroutine overwrites the current GROM address *-------------------------------------------------------------- * INPUT * P0 = GROM source address * P1 = RAM target address * P2 = Number of bytes to copy ********@*****@*********************@************************** G2MEM INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK MOV *R11+,R0 ; GROM source address MOV *R11+,R1 ; VDP target address MOV *R11+,R2 ; Bytes to copy * Set GROM source address G2MEM1 MOVB R0,@GRMWA SWPB R0 MOVB R0,@GRMWA ; Destroys R0. Doesn't matter * Copy from GROM to VDP G2MEM2 MOVB @GRMRD,*R1+ ; Copy byte from GROM to RAM DEC R2 JNE G2MEM2 ; Loop until all bytes copied B @POPRX2 ; Exit *************************************************************** * G2MEMX - Copy GROM memory range to RAM memory (register variant) *************************************************************** * BL @G2MEMX *-------------------------------------------------------------- * REMARKS * This subroutine overwrites the current GROM address *-------------------------------------------------------------- * INPUT * R0 = GROM source address * R1 = RAM target address * R2 = Number of bytes to copy ********@*****@*********************@************************** G2MEMX INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK JMP G2MEM1 ; Rest is the same as data variant *************************************************************** * XCPY - Extended copy *************************************************************** * BL @XCPY * DATA P0,P1,P2 * DATA .... * DATA 0 *-------------------------------------------------------------- * INPUT * R0 = Type of destination memory (ISVDP) * R1 = Destination address * * P0 = Command (CPYROM, CPYGRM, FILL) * P1 = Value depends on command type in P0 * P2 = Value depends on command type in P0 * * For CPYROM, CPYGRM * P1 = Source address * P2 = Number of bytes to copy *-------------------------------------------------------------- * REMARKS * Input list must be terminated with DATA 0 *-------------------------------------------------------------- * OUTPUT * @OUTP0 = Highest target address after processing command list *-------------------------------------------------------------- * EXAMPLE * LI R0,ISVDP * LI R1,>2000 ; Target address in VDP * BL @XCPY * DATA CPYROM,LETTRS,8*8 ; Copy letters A-H from ROM * DATA CPYGRM,STUFF,120 ; Copy some stuff from GROM * DATA CPYROM,DIGITS,10*8 ; Copy digits 0-9 from ROM * DATA 0 ; End-of-list * MOV @OUTP0,R0 ; VDP memory address after block copy *-------------------------------------------------------------- * Equates for commands CPYROM EQU 10 ; Copy ROM/RAM CPYGRM EQU 11 ; Copy GROM/GRAM ********@*****@*********************@************************** XCPY INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV R4,*STACK+ MOV R5,*STACK+ MOV R6,*STACK+ MOV R7,*STACK+ MOV R0,R3 ; Work with copy in R3 MOV R1,R4 ; Work with copy in R4 *-------------------------------------------------------------- * Check on what type of memory to copy *-------------------------------------------------------------- XCPY1 MOV *R11+,R5 ; Memory source type (ISROM, ISGROM) MOV *R11+,R6 ; Memory source address MOV *R11+,R7 ; Number of bytes to copy CI R3,ISVDP ; Target in VDP ? JNE XCPYZ ; Not yet supported *-------------------------------------------------------------- * Copy to VDP *-------------------------------------------------------------- CI R5,CPYROM ; Copy from ROM/RAM ? JNE XCPYZ ; Not yet supported MOV R11,*STACK ; Save RET address MOV R4,R0 ; Target address in VDP MOV R6,R1 ; Memory source address MOV R7,R2 ; Number of bytes to copy BL @VMBW MOV *STACK,R11 ; Restore RET address A R7,R4 ; Set VDP address for next run *-------------------------------------------------------------- * Prepare for next copy *-------------------------------------------------------------- XCPYY MOV *R11,*R11 ; Last entry processed ? JNE XCPY1 ; No, so loop *-------------------------------------------------------------- * Finished processing copies *-------------------------------------------------------------- XCPYZ MOV R4,@OUTP0 ; Memory address after processing command list DECT STACK B @POPRX7 ; Exit * * COPY 'D:\Projekte\spectra\tms9900\spectra_vdp.a99' * *************************************************************** * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * This file: spectra_sprites.a99 *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * X=No input D=Data variant R=Register variant * * VDP LOW LEVEL UTILITIES * ======================= * FVRAM - D - Fill VDP memory with byte * FVRAMX - R - Fill VDP memory with byte * PVRAM - D - Copy memory range to VDP memory * VSBR - R - VDP single byte read * VSBW - R - VDP single byte write * VMBW - R - VDP multiple byte write * VWTR - R - VDP write to register * LVDPSH - R - Load VDP shadow registers * WVDPSH - X - Write shadow registers to VDP * VDPADR - R - Calculate VDP table address * XY2OF - R - Calculate screen offset for X/Y character position * VIDOFF - X - Disable screen display * VIDON - X - Enable screen display * INTOFF - X - Disable VDP interrupt * INTON - X - Enable VDP interrupt *************************************************************** *************************************************************** * Shadow addresses for VDP write-only registers ********@*****@*********************@************************** VDPR0 EQU VDPREG+1 ; Value in Shadow VDP register 0 VDPR1 EQU VDPREG+3 ; Value in Shadow VDP register 1 VDPR2 EQU VDPREG+5 ; Value in Shadow VDP register 2 VDPR3 EQU VDPREG+7 ; Value in Shadow VDP register 3 VDPR4 EQU VDPREG+9 ; Value in Shadow VDP register 4 VDPR5 EQU VDPREG+11 ; Value in Shadow VDP register 5 VDPR6 EQU VDPREG+13 ; Value in Shadow VDP register 6 VDPR7 EQU VDPREG+15 ; Value in Shadow VDP register 7 *************************************************************** * ROM: VDP graphics mode 1 (values for shadow registers) ********@*****@*********************@************************** * VDP#0 Control bits * bit 6=0: M3 | Graphics 1 mode * bit 7=0: Disable external VDP input * VDP#1 Control bits * bit 0=1: 16K selection * bit 1=1: Enable display * bit 2=1: Enable VDP interrupt * bit 3=0: M1 \ Graphics 1 mode * bit 4=0: M2 / * bit 5=0: reserved * bit 6=1: 16x16 sprites * bit 7=0: Sprite magnification (1x) * * VDP#2 PNT (Pattern name table) at >0000 (>00 * >400) * VDP#3 PCT (Pattern color table) at >0380 (>0E * >040) * VDP#4 PDT (Pattern descriptor table) at >0800 (>01 * >800) * VDP#5 SAT (sprite attribute list) at >0300 (>06 * >080) * VDP#6 SPT (Sprite pattern table) at >0400 (>80 * >008) * VDP#7 Set background color to black *************************************************************** VMODE1 DATA >0000,>01E2,>0200,>030E,>0401,>0506,>0680,>0700,32 *************************************************************** * ROM: VDP text mode (values for shadow registers) ********@*****@*********************@************************** * VDP#0 Control bits * bit 6=0: M3 | Graphics 1 mode * bit 7=0: Disable external VDP input * VDP#1 Control bits * bit 0=1: 16K selection * bit 1=1: Enable display * bit 2=1: Enable VDP interrupt * bit 3=1: M1 \ TEXT MODE * bit 4=0: M2 / * bit 5=0: reserved * bit 6=1: 16x16 sprites * bit 7=0: Sprite magnification (1x) * * VDP#2 PNT (Pattern name table) at >0000 (>00 * >400) * VDP#3 PCT (Pattern color table) at >0380 (>0E * >040) * VDP#4 PDT (Pattern descriptor table) at >0800 (>01 * >800) * VDP#5 SAT (sprite attribute list) at >0300 (>06 * >080) * VDP#6 SPT (Sprite pattern table) at >0400 (>80 * >008) * VDP#7 Set foreground color to white/Background color to black *************************************************************** VMODET DATA >0000,>01F2,>0200,>030E,>0401,>0506,>0680,>07F0,40 *////////////////////////////////////////////////////////////// * VDP LOW LEVEL UTILITIES *////////////////////////////////////////////////////////////// *************************************************************** * FVRAM - Fill VDP memory with byte (data variant) *************************************************************** * BL @FVRAM * DATA P0,P1,P2 *-------------------------------------------------------------- * INPUT * P0 = VDP start address * P1 = Byte to fill * P2 = Number of bytes to fill ********@*****@*********************@************************** FVRAM INCT STACK MOV R0,*STACK+ ; Push R0 MOV R1,*STACK+ ; Push R1 MOV R2,*STACK+ ; Push R2 MOV *R11+,R0 ; VDP start address MOV *R11+,R1 ; Byte to fill MOV *R11+,R2 ; Repeat count MOV R11,*STACK *-------------------------------------------------------------- * Inline VSBW *-------------------------------------------------------------- FVRAM1 SWPB R1 ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP FVRAM2 MOVB R1,@VDPW ; Write byte to VDP *-------------------------------------------------------------- * List housekeeping *-------------------------------------------------------------- DEC R2 JNE FVRAM2 MOV *STACK,R11 DECT STACK B @POPRX2 ; Pop registers (R11 set) and return *************************************************************** * FVRAMX - Fill VDP memory with byte (register variant) *************************************************************** * BL @FVRAMX *-------------------------------------------------------------- * INPUT * R0 = VDP start address * R1 = Byte to fill * R2 = Number of bytes to fill ********@*****@*********************@************************** FVRAMX INCT STACK MOV R0,*STACK+ ; Push R0 MOV R1,*STACK+ ; Push R1 MOV R2,*STACK+ ; Push R2 MOV R11,*STACK ; Push R11 JMP FVRAM1 ; Rest is same as FVRAM *************************************************************** * PVRAM - Copy memory range to VDP memory *************************************************************** * BL @PVRAM * DATA P0,P1,P2 *-------------------------------------------------------------- * INPUT * P0 = VDP start address * P1 = RAM/ROM start address * P2 = Number of bytes to copy ********@*****@*********************@************************** PVRAM INCT STACK MOV R0,*STACK+ ; Push R0 MOV R1,*STACK+ ; Push R1 MOV R2,*STACK ; Push R2 MOV *R11+,R0 ; VDP target address MOV *R11+,R1 ; Starting address in RAM MOV *R11+,R2 *-------------------------------------------------------------- * Inline VMBW *-------------------------------------------------------------- ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP PVRAM1 MOVB *R1+,@VDPW DEC R2 JNE PVRAM1 B @POPRX2 ; Pop registers (R11 set) and return *************************************************************** * VSBR - VDP single byte read * Same function as in Editor Assembler module *************************************************************** * BL @VSBR *-------------------------------------------------------------- * INPUT * R0 = VDP source address * R1 = RAM target address * * OUTPUT * R1 = MSB, the byte read from VDP ********@*****@*********************@************************** VSBR SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP MOVB @VDPR,R1 RT *************************************************************** * VSBW - VDP single byte write * Same function as in Editor Assembler module *************************************************************** * BL @VSBW *-------------------------------------------------------------- * INPUT * R0 = VDP target address * R1 = MSB, byte to write to VDP ********@*****@*********************@************************** VSBW INCT STACK MOV R0,*STACK ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP MOVB R1,@VDPW B @POPRX0 ; Pop registers (R11 set) and return *************************************************************** * VMBR - VDP multiple byte read * Same function as in Editor Assembler module *************************************************************** * BL @VMBR *-------------------------------------------------------------- * INPUT * R0 = VDP source address * R1 = RAM target address * R2 = Number of bytes to read ********@*****@*********************@************************** VMBR INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP VMBR1 MOVB @VDPR,*R1+ DEC R2 JNE VMBR1 B @POPRG2 *************************************************************** * VMBW - VDP multiple byte write * Same function as in Editor Assembler module *************************************************************** * BL @VMBW *-------------------------------------------------------------- * INPUT * R0 = VDP target address * R1 = RAM/ROM source address * R2 = Number of bytes to write ********@*****@*********************@************************** VMBW INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP VMBW1 MOVB *R1+,@VDPW DEC R2 JNE VMBW1 B @POPRG2 *************************************************************** * VWTR - VDP write to register * Same function as in Editor Assembler module *************************************************************** * BL @VWTR *-------------------------------------------------------------- * INPUT * R0 = MSB is the VDP target register * LSB is the value to write ********@*****@*********************@************************** VWTR INCT STACK MOV R11,*STACK+ MOV R0,*STACK ORI R0,>8000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA B @POPRG0 *************************************************************** * LVDPSH - Load VDP shadow registers *************************************************************** * BL @LVDPSH *-------------------------------------------------------------- * INPUT * R0 = Address of video mode table, e.g. VMODE1 ********@*****@*********************@************************** LVDPSH INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK LI R1,VDPREG LI R2,16 *-------------------------------------------------------------- * Load shadow registers. Inline CPYMX for speed *-------------------------------------------------------------- LVDPS1 MOVB *R0+,*R1+ DEC R2 JNE LVDPS1 MOV *R0,@VDPCOL ; Set columns in row MOV @VDPS,@VDPSTA ; Set shadow status register B @POPRG2 *************************************************************** * WVDPSH - Write shadow registers to VDP *************************************************************** * BL @WVDPSH *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** WVDPSH INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK LI R1,VDPREG LI R2,8 WVDPS1 MOV *R1,R0 ; Write shadow register to VDP ORI R0,>8000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA INCT R1 DEC R2 JNE WVDPS1 ; Loop over next register B @POPRG2 *************************************************************** * VDPADR - Calculate VDP table address *************************************************************** * BL @VDPADR * DATA P0 *-------------------------------------------------------------- * INPUT * P0 = Constant representing table to look for *-------------------------------------------------------------- * OUTPUT * @OUTP0 = VDP address of table *-------------------------------------------------------------- * REMARKS * Valid input values for P0: * GETPNT (Pattern name table) * GETPCT (Pattern color table) * GETPDT (Pattern descriptor table) * GETSAT (Sprite attribute list) * GETSPT (Sprite pattern table) *-------------------------------------------------------------- * EXAMPLE * BL @VDPADR ; On return @OUTP0 has address * DATA GETPDT ; Get address of pattern descriptor table ********@*****@*********************@************************** VDPADR INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV *R11+,R3 ; Avoid warning 'R0 is symbolic addressing' MOV R11,*STACK MOVB @VDPREG+1(R3),R1 ; Get base value in shadow register SRL R1,8 ; Right justify MPY @VADTAB(R3),R1 ; Multiply factor with base value. Result is in R2 MOV R2,@OUTP0 ; Store table address in @OUTP0 MOV *STACK,R11 DECT STACK B @POPRX3 ; Exit VADTAB DATA >0000,>0000,>0400,>0040,>0800,>0080,>0008 GETPNT EQU 4 ; Offset in shadow VDP#2 & VADTAB (Pattern name table) GETPCT EQU 6 ; Offset in shadow VDP#3 & VADTAB (Pattern color table) GETPDT EQU 8 ; Offset in shadow VDP#4 & VADTAB (Pattern descriptor table) GETSAT EQU 10 ; Offset in shadow VDP#5 & VADTAB (Sprite attribute list) GETSPT EQU 12 ; Offset in shadow VDP#6 & VADTAB (Sprite pattern table) *************************************************************** * XY2OF - Calculate screen offset of X/Y character position *************************************************************** * BL @XY2OF *-------------------------------------------------------------- * INPUT * R0 = X column 0-31 * R1 = Y row 0-23 * * or alternative * * R0 = MSB (X column 0-31) * LSB (Y row 0-23) *-------------------------------------------------------------- * OUTPUT * @OUTP0 = Calculated screen offset *-------------------------------------------------------------- * REMARKS * Offset = (ROWS * @VDPCOL + COL) * Note you must add PNT base address yourself ********@*****@*********************@************************** XY2OF INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK CI R0,31 JLE XY2OF1 ; Calculate with R0=X and R1=Y *-------------------------------------------------------------- * Calculate with R0 having both X & Y *-------------------------------------------------------------- MOV R0,R1 SWPB R0 SZC @BITMSB,R0 ; Clear MSB SZC @BITMSB,R1 ; Clear MSB *-------------------------------------------------------------- * Calculate offset *-------------------------------------------------------------- XY2OF1 MOV @VDPCOL,R2 ; Get columns in a row MPY R1,R2 A R0,R3 MOV R3,@OUTP0 ; Store result in OUTP0 B @POPRG3 ; Exit *************************************************************** * VIDOFF - Disable screen display * VIDON - Enable screen display * INTOFF - Disable VDP interrupt * INTON - Enable VDP interrupt *************************************************************** * BL .... *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** VIDOFF SZCB @BIT1,@VDPR1 ; bit 1=0 (Disable screen display) RT VIDON SOCB @BIT1,@VDPR1 ; bit 1=1 (Enable screen display) RT INTOFF SZCB @BIT1,@VDPR1 ; bit 2=0 (Disable VDP interrupt) RT INTON SOCB @BIT1,@VDPR1 ; bit 2=1 (Enable VDP interrupt) RT * * COPY 'D:\Projekte\spectra\tms9900\spectra_sprites.a99' * *************************************************************** * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * This file: spectra_sprites.a99 *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * X=No input D=Data variant R=Register variant * * * VDP SPRITE UTILITIES * ==================== * S8X8 - X - Set sprite size 8x8 * S16X16 - X - Set sprite size 16x16 * SMAG1X - X - Set sprite magnification 1x * SMAG2X - X - Set sprite magnification 2x * PUTSAT - R - Write shadow SAT to VDP SAT * SPRORD - R - Initialize default sprite order 0..31 * SPRITE - D - Put sprite on screen *************************************************************** *************************************************************** * Memory structure for shadow SAT (RAMSAT) ********@*****@*********************@************************** SPR1 EQU RAMSAT ; Sprite 1 SPR2 EQU RAMSAT+4 ; Sprite 2 SPR3 EQU RAMSAT+8 ; Sprite 3 SPR4 EQU RAMSAT+12 ; Sprite 4 SPR5 EQU RAMSAT+16 ; Sprite 5 SPR6 EQU RAMSAT+20 ; Sprite 6 SPR7 EQU RAMSAT+24 ; Sprite 7 SPR8 EQU RAMSAT+28 ; Sprite 8 SPR9 EQU RAMSAT+32 ; Sprite 9 SPR10 EQU RAMSAT+36 ; Sprite 10 SPR11 EQU RAMSAT+40 ; Sprite 11 SPR12 EQU RAMSAT+44 ; Sprite 12 SPR13 EQU RAMSAT+48 ; Sprite 13 SPR14 EQU RAMSAT+52 ; Sprite 14 SPR15 EQU RAMSAT+56 ; Sprite 15 SPR16 EQU RAMSAT+60 ; Sprite 16 SPR17 EQU RAMSAT+64 ; Sprite 17 SPR18 EQU RAMSAT+68 ; Sprite 18 SPR19 EQU RAMSAT+72 ; Sprite 19 SPR20 EQU RAMSAT+76 ; Sprite 20 SPR21 EQU RAMSAT+80 ; Sprite 21 SPR22 EQU RAMSAT+84 ; Sprite 22 SPR23 EQU RAMSAT+88 ; Sprite 23 SPR24 EQU RAMSAT+92 ; Sprite 24 SPR25 EQU RAMSAT+96 ; Sprite 25 SPR26 EQU RAMSAT+100 ; Sprite 26 SPR27 EQU RAMSAT+104 ; Sprite 27 SPR28 EQU RAMSAT+108 ; Sprite 28 SPR29 EQU RAMSAT+112 ; Sprite 29 SPR30 EQU RAMSAT+116 ; Sprite 30 SPR31 EQU RAMSAT+120 ; Sprite 31 SPR32 EQU RAMSAT+124 ; Sprite 32 *////////////////////////////////////////////////////////////// * VDP SPRITE UTILITIES *////////////////////////////////////////////////////////////// *************************************************************** * S8X8 - Set sprite size 8x8 bits * S16X16 - Set sprite size 16x16 bits * SMAG1X - Set sprite magnification 1x * SMAG2X - Set sprite magnification 2x *************************************************************** * BL @.... *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** S8X8 SZCB @PLS2+1,@VDPR1 ; bit 6=0 (Sprite size 8x8) RT S16X16 SOCB @PLS2+1,@VDPR1 ; bit 6=1 (Sprite size 16x16) RT SMAG1X SZCB @BIT7,@VDPR1 ; bit 7=0 (Sprite magnification 1x) RT SMAG2X SOCB @BIT7,@VDPR1 ; bit 7=1 (Sprite magnification 2x) RT *************************************************************** * PUTSAT - Write shadow SAT to VDP SAT *************************************************************** * BL @PUTSAT *-------------------------------------------------------------- * INPUT * R0=VDP target address or >FFFF if address must be derived * R1=Address of shadow SAT in RAM/ROM * R2=Address of sprite order table in RAM/ROM or >FFFF * for default 0..31 order *-------------------------------------------------------------- * OUTPUT * NONE *-------------------------------------------------------------- * REMARKS * Has inline VMBW for speed *-------------------------------------------------------------- * EXAMPLE * NONE ********@*****@*********************@************************** PUTSAT INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK *-------------------------------------------------------------- * Get SAT address *-------------------------------------------------------------- CI R0,>FFFF JNE PUTSA1 BL @VDPADR ; Get VDP SAT address to @OUTP0 DATA GETSAT MOV @OUTP0,R0 *-------------------------------------------------------------- * Setup VDP write address *-------------------------------------------------------------- PUTSA1 ORI R0,>4000 ; Start of inline VMBW SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA *-------------------------------------------------------------- * Check if sprite order table *-------------------------------------------------------------- CI R2,>FFFF JEQ PUTSA4 ; Do default sprite order *-------------------------------------------------------------- * Dump shadow SAT to VDP SAT using sprite order table *-------------------------------------------------------------- PUTSA2 INCT STACK MOV R3,*STACK * LI R3,32 LI R3,6 PUTSA3 CLR R0 MOVB *R2+,R0 ; Get sprite order entry SRL R0,6 ; R0=R0*4 (shift right 8 and then shift left 2) A R1,R0 ; Add table base to R0 MOVB *R0+,@VDPW ; Write SAT entry byte 0 to VDP MOVB *R0+,@VDPW ; Write SAT entry byte 1 to VDP MOVB *R0+,@VDPW ; Write SAT entry byte 2 to VDP MOVB *R0,@VDPW ; Write SAT entry byte 3 to VDP DEC R3 JNE PUTSA3 B @POPRG3 ; Exit *-------------------------------------------------------------- * Dump shadow SAT to VDP SAT using default 0..31 sprite order *-------------------------------------------------------------- PUTSA4 LI R2,24 ; SAT length = 128 bytes PUTSA5 MOVB *R1+,@VDPW DEC R2 JNE PUTSA5 ; End of inline VMBW B @POPRG2 ; Exit *************************************************************** * SPRORD - Initialize default sprite order 0..31 *************************************************************** * BL @SPRORD *-------------------------------------------------------------- * INPUT * R0=Address of sprite order table in RAM *-------------------------------------------------------------- * OUTPUT * NONE *-------------------------------------------------------------- * REMARKS * NONE *-------------------------------------------------------------- * EXAMPLE * NONE ********@*****@*********************@************************** SPRORD INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK LI R1,>0001 ; First 2 entries LI R2,16 SPROR1 MOV R1,*R0+ ; Write 2 entries to sprite order table AI R1,>0202 ; Value for next 2 entries DEC R2 JNE SPROR1 B @POPRG2 ; Exit *************************************************************** * SPRITE - Put object sprite on screen *************************************************************** * BL @SPRITE *-------------------------------------------------------------- * INPUT * R1 = Pointer to sprite table entry *-------------------------------------------------------------- * FORMAT sprite table entry * DATA P0,P1,P2,P3,P4 * * P0 = VDP target address for entry in SAT * P1 = MSB is Y position of sprite * LSB is X position of sprite * P2 = MSB is sprite character code * LSB is sprite color * P3 = ROM/RAM source address of sprite pattern data * P4 = Additional subroutine to call via BL @xxxx *-------------------------------------------------------------- * REMARKS * Set P3 to 0 if no pattern must be loaded * Set P4 to 0 if no additional subroutines must be called *-------------------------------------------------------------- * EXAMPLE * LI R1,ABC * BL @SPRITE * .... * ABC DATA VDPSAT+40,>A280,>A40F,SCORP1,MYSUB ********@*****@*********************@************************** SPRITE INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R1,*STACK+ MOV R0,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV R4,*STACK MOV R1,R3 ; Pointer to sprite data is in register 1 of caller SPRIT2 MOV *R3,R0 ; BYTE 00-01 = VDP target address for SAT data INCT R3 ; MOV R3,R1 ; BYTE 02-03 = RAM address where SAT data is stored LI R2,4 ; 1 sprite=4 bytes BL @VMBW * Calculate VDP pattern table target address MOV @2(R3),R2 SRL R2,8 ; Only interested in high byte AI R2,->80 ; Subtract >80 (pattern >80 is at start of pattern table) SLA R2,3 ; Multiply by 8 AI R2,VDPSPT ; Calculate target address in VDP pattern table * Set VDP target address and source address MOV @4(R3),R1 ; RAM source address JEQ SPRIT3 ; No pattern data to load MOV R2,R0 ; VDP target address LI R2,32 ; 32 bytes = 4x4 sprite BL @VMBW * Set controller SPRIT3 MOV @6(R3),R4 ; Do we have a sprite controller routine ? JEQ SPRIT4 ; No, exit BL *R4 ; Yes, setup controller SPRIT4 B @POPRG4 * * COPY 'D:\Projekte\spectra\tms9900\spectra_tiles.a99' * *************************************************************** * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * This file: spectra_tiles.a99 *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * X=No input D=Data variant R=Register variant * * * VDP TILE/PATTERN UTILITIES * ========================== * TIFONT - X - Load title screen font from GROM0 into VDP * FIBOX - D - Fill box with character * FIBOXX - R - Fill box with character * FILSCR - R - Fill screen with character * PUTTX - D - Put length-byte prefixed string on screen * MIRRV - D - Mirror patterns in membuf around vertical axis *************************************************************** *////////////////////////////////////////////////////////////// * VDP TILE/PATTERN UTILITIES *////////////////////////////////////////////////////////////// *************************************************************** * TIFONT - Load TI-99/4A title screen font from GROM0 into VDP ** ADD POSSIBILITY TO SPECIFY TITLE SCREEN FONT, NORMAL FONT ** OR TEXT-MODE FONT OR SPECIFY ADDRESS WHERE FONT IS STORED ** RENAME TO LDFONT *************************************************************** * BL @TIFONT *-------------------------------------------------------------- * INPUT * NONE ********@*****@*********************@************************** TIFONT INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK BL @VDPADR ; Get address of Pattern Descriptor Table (PDT) DATA GETPDT MOV @OUTP0,R1 AI R1,32*8 ; Offset for starting with ASCII 32 BL @G2MEM DATA >004C,OUTP0,2 ; Read GROM address >0048 (pointer to 1st built-in font) MOV @OUTP0,R0 LI R2,>200 ; Copy font patterns BL @G2VDPX ; Copy >200 bytes from GROM TO VDP B @POPRG2 ; Exit *************************************************************** * FIBOX - Fill box with character (data variant) * ADD POSSIBILITY TO SPECIFY BOUNDARY-CHECK AND TARGET * VDP-ADDRESS *************************************************************** * BL @FIBOX *-------------------------------------------------------------- * INPUT * P0 = Upper left corner X1 * P1 = Upper left corner Y1 * P2 = Width * P3 = Height * P4 = Character to fill ********@*****@*********************@************************** FIBOX INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV R4,*STACK+ MOV *R11+,R0 ; P0 MOV *R11+,R1 ; P1 MOV *R11+,R2 ; P2 MOV *R11+,R3 ; P3 MOV *R11+,R4 ; P4 MOV R11,*STACK FIBOX1 BL @XY2OF ; R0=X R1=Y *-------------------------------------------------------------- * Boundary check *-------------------------------------------------------------- A R0,R2 ; P2 (width) + P0 C R2,@VDPCOL ; P2 + P0 <= 32 ? JLE FIBOX2 ; Yes, continue MOV @VDPCOL,R2 ; P2 (width) = 32 - P0 FIBOX2 S R0,R2 ; *-------------------------------------------------------------- * Calculate PNT base address *-------------------------------------------------------------- FIBOX3 MOV @OUTP0,R0 ; Store output from 'BL @XY2OF' in R0 BL @VDPADR ; Get address of Pattern Name Table (PNT) DATA GETPNT ; @OUTP0 has table address A @OUTP0,R0 MOV R4,R1 ; Character to fill INC R3 *-------------------------------------------------------------- * Start filling box *-------------------------------------------------------------- FIBOX4 BL @FVRAMX ; Fill with caracter. R2 has width already A @VDPCOL,R0 ; Next row DEC R3 ; JNE FIBOX4 ; Repeat until last row MOV *STACK,R11 DECT STACK B @POPRX4 ; Exit *************************************************************** * FIBOXX - Fill box with character (register variant) *************************************************************** * BL @FIBOXX *-------------------------------------------------------------- * INPUT * R0 = Upper left corner X1 * R1 = Upper left corner Y1 * R2 = Width * R3 = Height * R4 = Character to fill ********@*****@*********************@************************** FIBOXX INCT STACK MOV R0,*STACK+ ; Push R0 MOV R1,*STACK+ ; Push R1 MOV R2,*STACK+ ; Push R2 MOV R3,*STACK+ ; Push R3 MOV R4,*STACK+ ; Push R4 MOV R11,*STACK ; Push R11 JMP FIBOX1 ; Rest is same as FIBOX *************************************************************** * FILSCR - Fill screen with character * ADD POSSIBILITY TO SUPPLY TARGET VDP ADDRESS !!!!! *************************************************************** * BL @FILSCR *-------------------------------------------------------------- * INPUT * R0 = Character to fill ********@*****@*********************@************************** FILSCR INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK LI R1,24 MPY @VDPCOL,R1 ; COLS * ROWS. Result is in R2 MOV R0,R1 ; Fill character BL @VDPADR ; Get address of Pattern Name Table (PNT) DATA GETPNT MOV @OUTP0,R0 *-------------------------------------------------------------- * Inline VSBW *-------------------------------------------------------------- SWPB R1 ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP FILSCS MOVB R1,@VDPW ; Write byte to VDP *-------------------------------------------------------------- * Loop housekeeping *-------------------------------------------------------------- DEC R2 JNE FILSCS B @POPRG2 ; Exit *************************************************************** * Put length-byte prefixed string on screen * USE 0-TERMINATED STRING INSTEAD OF LENGTH-BASED STRING !!!! * ADD POSSIBILITY TO SPECIFY VDP TARGET ADDRESS !!!! *************************************************************** * BL @PUTTX * DATA P0,P1,P2 *-------------------------------------------------------------- * INPUT * P0 = X column (0-31) * P1 = Y column (0-23) * P2 = Pointer to string * * or alternative * * P0 = MSB (X column 0-31) * LSB (Y column 0-23) * P1 = Pointer to string *-------------------------------------------------------------- * REMARKS * First byte of string must contain length *-------------------------------------------------------------- * EXAMPLE * BL @PUTTX * DATA 12,0,TX6 * ... * BL @PUTTX * DATA >0C00,TX6 ********@*****@*********************@************************** PUTTX INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV *R11+,R0 ; X position C R0,@VDPCOL JLE PUTTX1 JMP PUTTX2 PUTTX1 MOV *R11+,R1 ; Y position PUTTX2 MOV *R11+,R3 ; Text to display MOV R11,*STACK MOVB *R3+,R2 ; First byte is length SRL R2,8 ; Right justify BL @XY2OF ; Set Offset in @OUTP0 MOV @OUTP0,R0 ; VDP Target address *-------------------------------------------------------------- * Inline VMBW *-------------------------------------------------------------- ORI R0,>4000 SWPB R0 MOVB R0,@VDPA SWPB R0 MOVB R0,@VDPA NOP PUTTX3 MOVB *R3+,@VDPW *-------------------------------------------------------------- * Loop housekeeping *-------------------------------------------------------------- DEC R2 JNE PUTTX3 MOV *STACK,R11 DECT STACK B @POPRX3 ; Pop registers (R11 set) and return *************************************************************** * MIRRV - Mirror patterns in membuf around vertical axis *************************************************************** * BL @MIRRV * DATA P0,P1,P2 *-------------------------------------------------------------- * INPUT * P0 = Pointer to pattern data in RAM * P1 = Number of bytes to mirror * P2 = Swap patterns 0123 to 2301 (for 4x4 sprites) if SWAP ********@*****@*********************@************************** MIRRV INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R3,*STACK+ MOV R4,*STACK+ MOV R5,*STACK+ MOV R6,*STACK+ MOV R7,*STACK+ MOV *R11+,R1 ; Pointer MOV *R11+,R2 ; Bytes MOV *R11+,R0 ; Swap MOV R11,*STACK CLR R7 ; Reset byte counter MIRRV1 CI R0,SWAP JNE MIRRV3 CI R7,32 JNE MIRRV2 CLR R7 ; Reset byte counter JMP MIRRV3 MIRRV2 CI R7,16 JHE MIRRV3 MOVB *R1,R5 ; Duplicate byte MOV R1,R6 ; Copy pointer address AI R6,16 ; Added 16 to pointer address MOVB *R6,*R1 ; Swap byte MOVB R5,*R6 ; Swap byte MIRRV3 LI R3,>80 ; Counter and work register 3 (Bit 8 set) MOVB *R1,R4 ; Copy byte to work register 4 * Next bit MIRRV4 SRL R3,1 ; Shift right logical 1 bit JOC MIRRV5 SLA R4,1 ; Shift left arithmetic 1 bit JNC MIRRV4 ORI R3,>8000 ; Set bit 16 JMP MIRRV4 * Next byte MIRRV5 SLA R4,1 ; Process last bit before proceeding with next byte JNC MIRRV6 ORI R3,>8000 MIRRV6 MOVB R3,*R1+ ; Store MSB of R3 in memory pointed to by R1 and increase pointer INC R7 DEC R2 JGT MIRRV1 ; Process next byte MOV *STACK,R11 DECT STACK B @POPRX7 ; Pop registers (R11 set) and return * * COPY 'D:\Projekte\spectra\tms9900\spectra_timers.a99' * *************************************************************** * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * This file: spectra_timers.a99 *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * X=No input D=Data variant R=Register variant * * TIMER LOW LEVEL UTILITIES * ========================= * MKSLOT - D - Allocate timer slot * ANIMTR - X - Scheduler 1. Control timers via ISR *************************************************************** *************************************************************** * Memory structure for timers ********@*****@*********************@************************** * SLOT MEMORY STRUCTURE (TIMER) * TIMER+0 0000 Target tick count * TIMER+2 0000 Address of routine to call * TIMER+4 0000 Tick counter * TIMER+6 0000 2 bytes available for private use ********@*****@*********************@************************** TSLT0 EQU TIMER ; Timer slot 0 TSLT1 EQU TIMER+8 ; Timer slot 1 TSLT2 EQU TIMER+16 ; Timer slot 2 TSLT3 EQU TIMER+24 ; Timer slot 3 TSLT4 EQU TIMER+32 ; Timer slot 4 TSLT5 EQU TIMER+40 ; Timer slot 5 TSLT6 EQU TIMER+48 ; Timer slot 6 TSLT7 EQU TIMER+56 ; Timer slot 7 TSLT8 EQU TIMER+64 ; Timer slot 8 TSLT9 EQU TIMER+72 ; Timer slot 9 TSLT10 EQU TIMER+80 ; Timer slot 10 TSLT11 EQU TIMER+88 ; Timer slot 11 TSLT12 EQU TIMER+96 ; Timer slot 12 TSLT13 EQU TIMER+104 ; Timer slot 13 TSLT14 EQU TIMER+112 ; Timer slot 14 TSLT15 EQU TIMER+120 ; Timer slot 15 TSLT16 EQU TIMER+128 ; Timer slot 16 TSLT17 EQU TIMER+136 ; Timer slot 17 TSLT18 EQU TIMER+142 ; Timer slot 18 TSLT19 EQU TIMER+150 ; Timer slot 19 TSUB0 EQU TIMER+2 ; Subroutine for slot 0 TSUB1 EQU TIMER+10 ; Subroutine for slot 1 TSUB2 EQU TIMER+18 ; Subroutine for slot 2 TSUB3 EQU TIMER+26 ; Subroutine for slot 3 TSUB4 EQU TIMER+34 ; Subroutine for slot 4 TSUB5 EQU TIMER+42 ; Subroutine for slot 5 TSUB6 EQU TIMER+50 ; Subroutine for slot 6 TSUB7 EQU TIMER+58 ; Subroutine for slot 7 TSUB8 EQU TIMER+66 ; Subroutine for slot 8 TSUB9 EQU TIMER+74 ; Subroutine for slot 9 TSUB10 EQU TIMER+82 ; Subroutine for slot 10 TSUB11 EQU TIMER+90 ; Subroutine for slot 11 TSUB12 EQU TIMER+98 ; Subroutine for slot 12 TSUB13 EQU TIMER+106 ; Subroutine for slot 13 TSUB14 EQU TIMER+114 ; Subroutine for slot 14 TSUB15 EQU TIMER+122 ; Subroutine for slot 15 TSUB16 EQU TIMER+130 ; Subroutine for slot 16 TSUB17 EQU TIMER+138 ; Subroutine for slot 17 TSUB18 EQU TIMER+144 ; Subroutine for slot 18 TSUB19 EQU TIMER+152 ; Subroutine for slot 19 TPRV0 EQU TIMER+6 ; Private variable slot 0 TPRV1 EQU TIMER+14 ; Private variable slot 1 TPRV2 EQU TIMER+22 ; Private variable slot 2 TPRV3 EQU TIMER+30 ; Private variable slot 3 TPRV4 EQU TIMER+38 ; Private variable slot 4 TPRV5 EQU TIMER+46 ; Private variable slot 5 TPRV6 EQU TIMER+54 ; Private variable slot 6 TPRV7 EQU TIMER+62 ; Private variable slot 7 TPRV8 EQU TIMER+70 ; Private variable slot 8 TPRV9 EQU TIMER+78 ; Private variable slot 9 TPRV10 EQU TIMER+86 ; Private variable slot 10 TPRV11 EQU TIMER+94 ; Private variable slot 11 TPRV12 EQU TIMER+102 ; Private variable slot 12 TPRV13 EQU TIMER+110 ; Private variable slot 13 TPRV14 EQU TIMER+118 ; Private variable slot 14 TPRV15 EQU TIMER+126 ; Private variable slot 15 TPRV16 EQU TIMER+134 ; Private variable slot 16 TPRV17 EQU TIMER+140 ; Private variable slot 17 TPRV18 EQU TIMER+148 ; Private variable slot 18 TPRV19 EQU TIMER+156 ; Private variable slot 19 *////////////////////////////////////////////////////////////// * TIMER LOW LEVEL UTILITIES *////////////////////////////////////////////////////////////// *************************************************************** * MKSLOT - Allocate timer slot *************************************************************** * BL @MKSLOT * DATA P0,P1,P2 *-------------------------------------------------------------- * INPUT * P0 = Slot number 0-19 * P1 = Run slot every XX ticks * P2 = Subroutine to call via BL @xxx if slot is fired *-------------------------------------------------------------- * REMARKS * Set P1 to 0 for disabling/skipping slot ********@*****@*********************@************************** MKSLOT INCT STACK MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK MOV *R11+,R0 ; Move slot number to R0 LI R1,8 ; Length of slot in timer structure MPY R0,R1 ; Calculate offset. Result is in R2! MOV *R11+,@TIMER+0(R2) ; Move ticks -> timer structure MOV *R11+,@TIMER+2(R2) ; Move routine -> timer structure CLR @TIMER+4(R2) ; Timer structure. Reset tick counter CLR @TIMER+6(R2) ; Timer structure. Initialise for private use MKSLO1 B @POPRX2 ; Pop registers (R11 set) and return ***** * TMGR performance optimierung / Doku * Timer Table in scratch-pad ram legen * * Für doku: * Kein automatischer sound processing möglich. Dafür Eigener Controller * verwenden. Prüfung ob ticks per second can be set (50 or 60) ****** *************************************************************** * TMGR - X - Start Timer/Task scheduler *************************************************************** * B @TMGR *-------------------------------------------------------------- * REMARKS * Timer/Task scheduler. Normally called once on program startup. * Don't forget to set THIGH to highest slot in use *-------------------------------------------------------------- * EXAMPLE * MOV @PLS8,@THIGH ; Highest slot in use is 8 * B @TMGR ; Start task scheduler ********@*****@*********************@************************** TMGR LIMI 0 ; No interrupt processing *-------------------------------------------------------------- * Wait for VDP interrupt flag to be set *-------------------------------------------------------------- TMGR1 MOV @VDPS,R0 ; Get VDP status register COC @BIT0,R0 ; Interupt flag set ? JNE TMGR1 ; No, so loop *-------------------------------------------------------------- * Do some internal housekeeping *-------------------------------------------------------------- MOV R0,@VDPSTA ; Save copy in shadow VDP status register MOV @TCOUNT,R0 CI R0,60 ; 1 second reached ? JLT TMGR2 ; No, continue CLR @TCOUNT ; Yes, now reset tick counter TMGR2 INC @TCOUNT ; Increment tick counter *-------------------------------------------------------------- * Loop over slots *-------------------------------------------------------------- CLR R1 ; Start with slot 0 CLR R2 ; Offset in timer structure for slot 0 TMGR3 C @TIMER(R2),@NULL ; Is slot empty? JEQ TMGR4 ; Yes, so get next slot *-------------------------------------------------------------- * Do slot housekeeping tasks *-------------------------------------------------------------- INC @TIMER+4(R2) ; Update tick count in slot C @TIMER(R2),@TIMER+4(R2) ; Execute slot? JNE TMGR4 ; No, get next slot *-------------------------------------------------------------- * Run task in slot *-------------------------------------------------------------- MOV @TIMER+2(R2),R0 ; Get routine BL *R0 ; Call routine CLR @TIMER+4(R2) ; Reset tick count in slot *-------------------------------------------------------------- * Prepare for next slot *-------------------------------------------------------------- TMGR4 INC R1 ; Next slot C R1,@THIGH ; Last slot done ? JGT TMGR1 ; yes, Wait for next VDP interrupt AI R2,8 ; Offset for next slot JMP TMGR3 ; no, process next slot * * COPY 'D:\Projekte\spectra\tms9900\spectra_epsgmod.a99' * ******************************************** ******************* * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * spectra_epsgmod - EPSGMOD playback code *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * EPSGMOD playback code for TI-99/4A orginially * by Mike Brent aka Tursi http://harmlesslion.com * * Adapted by Retroclouds to fit SPECTRA library. * * Thanks to Martin at http://mod2psg2.kontechs.com * Released freely and without restriction as per * the terms of MOD2PSG. **************************************************************** * X=No input D=Data variant R=Register variant * * SOUND PLAYER UTILITIES * ====================== * EPSGMD - R - Prepare for playing EPGSMOD tune * PSGTCK - X - Play tune. Expects to be called as animator slot **************************************************************** *////////////////////////////////////////////////////////////// * EQUATES *////////////////////////////////////////////////////////////// ********@*****@*********************@************************** VIBTAB EQU 0 ; Fake vibrato using pulse vibrato *////////////////////////////////////////////////////////////// * SPECTRA EPSGMOD PLAYER MEMORY LAYOUT *////////////////////////////////////////////////////////////// ********@*****@*********************@************************** BACKUP BSS 4 ; Total of 128 bytes including PLMASK PMOD DATA 0 NUMSEQ BSS 2 SEQCNT BSS 2 SPEED BSS 2 SPCNT BSS 2 SEQLEN BSS 2 NDELAY BSS 8 NCHLEN BSS 8 NFREQ BSS 8 NIDX BSS 2 NTMP BSS 2 NTMP2 BSS 2 NCHAN BSS 2 CALLBA DATA 0 CALLBB DATA 0 PSEQ BSS 2 PRPT BSS 2 PCHSEQ BSS 8 PNOTES BSS 8 PINST BSS 8 PVIB BSS 8 PVBASE BSS 8 PTMP BSS 2 NVOL BSS 4 PULVIB BSS 4 PULSIZ BSS 4 NINLEFT BSS 4 NINDELAY BSS 4 NINSTEP BSS 4 NINVOL BSS 4 NVCNT BSS 4 *-------------------------------------------------------------- * Four byte array of channel priorities. * For today, 0 means don't play and >FF means do *-------------------------------------------------------------- PLMASK BSS 4 ********@*****@*********************@************************** SETNIDXFREQ MOV @NIDX,R2 MOV R2,R3 ; NIDX A R3,R3 ; NIDX*2 MOV R3,R0 AI R0,NFREQ MOV *R0,@NTMP MOV R2,R0 AI R0,PULVIB MOVB *R0,R1 COC @BIT0,R1 JNE NOVIB1 MOV R2,R0 AI R0,PULSIZ CLR R1 MOVB *R0,R1 SWPB R1 A R1,@NTMP ********@*****@*********************@************************** NOVIB1 MOV R3,R0 AI R0,PVIB MOV *R0,R1 JEQ NV118 MOVB *R1,R0 SRA R0,8 A R0,@NTMP *************************************************************** * Send audio to sound chip ********@*****@*********************@************************** NV118 MOV R2,R0 ; Check channel play mask (skip if 0) AI R0,PLMASK MOVB *R0,R0 JEQ EQ158 MOV @NTMP,R0 ANDI R0,>000F ORI R0,>0080 SOC @NCHAN,R0 SWPB R0 MOVB R0,@SOUND MOV @NTMP,R0 SRL R0,4 SWPB R0 MOVB R0,@SOUND EQ158 B *R11 ********@*****@*********************@************************** READINSTRUMENTATPTMP MOV @NIDX,R2 MOV R2,R3 ; NIDX A R3,R3 ; NIDX*2 MOV @PTMP,R4 ; Holding pTmp in R4 CLR R0 MOVB *R4+,R0 MOV R2,R1 AI R1,NINSTEP MOVB R0,*R1 MOVB *R4+,R0 MOV R2,R1 AI R1,NINDELAY MOVB R0,*R1 MOVB *R4+,R5 MOV R3,R0 AI R0,PINST MOV R4,*R0 MOV R5,R0 ANDI R0,>C000 CI R0,>8000 JEQ EQ176 MOV R3,R0 AI R0,PVIB CLR *R0 JMP AL181 ********@*****@*********************@************************** EQ176 ANDI R5,>3f00 LI R0,VIBTAB JNE NE188 MOV R5,R0 ANDI R0,>3000 CI R0,>3000 JNE NE194 MOV R2,R1 AI R1,PULVIB LI R0,>AA00 MOVB R0,*R1 JMP GOTVIB ********@*****@*********************@************************** NE194 CI R0,>2000 JNE NE206 MOV R2,R1 AI R1,PULVIB LI R0,>CC00 MOVB R0,*R1 JMP GOTVIB ********@*****@*********************@************************** NE206 MOV R2,R1 AI R1,PULVIB LI R0,>F000 MOVB R0,*R1 ********@*****@*********************@************************** GOTVIB MOV R2,R0 AI R0,PULSIZ NE188 MOVB R5,*R0 JMP AL228 SWPB R5 SLA R5,5 AI R5,VIBTAB MOV R3,R0 AI R0,PVIB MOV R5,*R0 MOV R3,R0 AI R0,PVBASE MOV R5,*R0 MOV R2,R0 AI R0,NVCNT LI R1,>2000 MOVB R1,*R0 AL228 AL181 B *R11 *************************************************************** * EPSGMD - Setup memory for playing EPSGMOD tune *************************************************************** * LI R0,MYTUNE * BL @EPSGMD *-------------------------------------------------------------- * REMARKS * Set R0=0 to turn off tune * * Callbacks can be embedded in the tune. When * they are found, if an address other than >0000 * is loaded at these addresses, they will be called * with the player's workspace and the argument in * R0. You may use any registers, although you must * keep it short (you're being called on th7e interrupt), * don't mess with GPL or ROM settings, and return to * R11. Best advised to set a flag rather than take action. *-------------------------------------------------------------- * INPUT * R0 = Address of tune to play * CALLBA = Address of callback hook A * CALLBA = Address of callback hook B ********@*****@*********************@************************** EPSGMD INCT STACK MOV R11,*STACK+ ; PUSH RET address MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK *-------------------------------------------------------------- * Turn of sound generators *-------------------------------------------------------------- LI R1,>9F00 MOVB R1,@SOUND LI R1,>BF00 MOVB R1,@SOUND LI R1,>DF00 MOVB R1,@SOUND LI R1,>FF00 MOVB R1,@SOUND MOV R0,@PMOD ; Store tune JNE EPSGM1 B @POPRG2 ; Exit *-------------------------------------------------------------- * Setup memory for playing tune *-------------------------------------------------------------- EPSGM1 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 MOV R1,@NUMSEQ MOV R1,@SEQCNT AI R0,256 ; 256 cause of the autoinc above MOVB *R0,R1 SRA R1,8 MOV R1,@SPEED MOV R1,@SPCNT INCT R0 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 S R1,@NUMSEQ SLA R1,3 MOV R1,@PRPT MOV R0,@PSEQ A R0,@PRPT LI R2,PCHSEQ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2+ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2+ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2+ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2 MOV @PCHSEQ,R0 LI R2,PNOTES MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2+ CLR R1 MOVB *R0+,R1 SWPB R1 MOV R1,@SEQLEN MOV R0,@PCHSEQ MOV @PCHSEQ+2,R0 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2+ INC R0 MOV R0,@PCHSEQ+2 MOV @PCHSEQ+4,R0 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2+ INC R0 MOV R0,@PCHSEQ+4 MOV @PCHSEQ+6,R0 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A @PMOD,R1 MOV R1,*R2+ INC R0 MOV R0,@PCHSEQ+6 LI R0,1 MOV R0,@NDELAY MOV R0,@NDELAY+2 MOV R0,@NDELAY+4 MOV R0,@NDELAY+6 CLR @NVOL CLR @NVOL+2 CLR @NFREQ CLR @NFREQ+2 CLR @NFREQ+4 CLR @NFREQ+6 LI R0,>5555 MOV R0,@PULVIB MOV R0,@PULVIB+2 CLR @PULSIZ CLR @PULSIZ+2 CLR @PINST CLR @PINST+2 CLR @PINST+4 CLR @PINST+6 CLR @PVIB CLR @PVIB+2 CLR @PVIB+4 CLR @PVIB+6 CLR @PVBASE CLR @PVBASE+2 CLR @PVBASE+4 CLR @PVBASE+6 CLR @NVCNT CLR @NVCNT+2 CLR @NINLEFT CLR @NINLEFT+2 CLR @NINDELAY CLR @NINDELAY+2 CLR @NINSTEP CLR @NINSTEP+2 CLR @NINVOL CLR @NINVOL+2 SETO @PLMASK SETO @PLMASK+2 CLR @CALLBA CLR @CALLBB B @POPRG2 ; Exit *************************************************************** * Play mod tune. Should be called as slot ********@*****@*********************@************************** PSGTCK MOV @PMOD,@PMOD JNE NE530 ; RT ; Nothing to play. exit NE530 LWPI WSSPC2 MOV @PMOD,R10 MOV @SPCNT,R0 AI R0,>FFF8 JNC OC519 ; Went negative JEQ OC519 ; Went to zero MOV R0,@SPCNT B @EACYC ********@*****@*********************@************************** OC519 A @SPEED,R0 MOV R0,@SPCNT MOV @SEQLEN,R0 JEQ EQ529 DEC @SEQLEN JEQ EQ529 B @JM594 *-------------------------------------------------------------- * new sequence - reset values (same as above after pTmp=pSeq) *-------------------------------------------------------------- EQ529 DEC @NUMSEQ JNE NE543 MOV @SEQCNT,@NUMSEQ MOV @PRPT,@PSEQ JMP AL544 NE543 LI R0,8 A R0,@PSEQ AL544 RPTSEQ MOV @PSEQ,R0 LI R3,PCHSEQ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ MOV @PCHSEQ,R0 LI R3,PNOTES MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ CLR R1 MOVB *R0+,R1 SWPB R1 MOV R1,@SEQLEN JNE NE604 MOV @SEQCNT,@NUMSEQ MOV @PRPT,@PSEQ JMP RPTSEQ NE604 MOV R0,@PCHSEQ MOV @PCHSEQ+2,R0 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ INC R0 MOV R0,@PCHSEQ+2 MOV @PCHSEQ+4,R0 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ INC R0 MOV R0,@PCHSEQ+4 MOV @PCHSEQ+6,R0 MOVB *R0+,R1 SWPB R1 MOVB *R0+,R1 A R10,R1 MOV R1,*R3+ INC R0 MOV R0,@PCHSEQ+6 LI R0,1 MOV R0,@NDELAY MOV R0,@NDELAY+2 MOV R0,@NDELAY+4 MOV R0,@NDELAY+6 JM594 CLR @NIDX FOR668 MOV @NIDX,R6 CI R6,4 JLT LT677 B @HE671 LT677 MOV R6,R7 A R7,R7 MOV R6,R0 SLA R0,5 MOV R0,@NCHAN MOV R7,R0 AI R0,NDELAY DEC *R0 JEQ EQ695 B @EALINE *-------------------------------------------------------------- * Next byte *-------------------------------------------------------------- EQ695 NEXTBYTE ********@*****@*********************@************************** MOV R7,R0 AI R0,PCHSEQ MOV *R0,R1 INC *R0 MOV R1,R0 CLR R1 MOVB *R0,R1 MOV R1,R0 ANDI R0,>E000 JEQ EQ702 *-------------------------------------------------------------- * Process note *-------------------------------------------------------------- MOV R1,R2 SRL R2,13 MOV R7,R0 AI R0,NDELAY MOV R2,*R0 ANDI R1,>1F00 SWPB R1 MOV R1,R2 A R1,R1 CI R6,3 JEQ NE721 A R2,R1 NE721 MOV R7,R3 AI R3,PNOTES MOV *R3,R3 A R1,R3 *-------------------------------------------------------------- * Instrument and volume *-------------------------------------------------------------- CLR R1 MOVB *R3+,R1 MOV R1,R0 ANDI R0,>F000 SWPB R0 A R10,R0 INCT R0 MOV R7,R2 AI R2,PINST MOV R0,*R2 ANDI R1,>0F00 MOV R6,R2 AI R2,NVOL MOVB R1,*R2 MOVB *R3+,R1 ANDI R1,>0F00 SWPB R1 MOV R7,R2 AI R2,NFREQ MOV R1,*R2 CI R6,3 JEQ EQ764 MOVB *R3,R1 ANDI R1,>3F00 SWPB R1 SLA R1,4 MOV R7,R0 AI R0,NFREQ SOC R1,*R0 EQ764 MOV R7,R0 AI R0,PINST MOV *R0,R0 MOV R6,R1 AI R1,NINVOL MOVB *R0+,*R1 MOV R0,@PTMP BL @READINSTRUMENTATPTMP LI R0,>0400 MOV R6,R1 AI R1,NINLEFT MOVB R0,*R1 B @EALINE EQ702 MOV R1,R0 ANDI R0,>0100 JEQ EQ801 CI R6,3 JNE NE804 *-------------------------------------------------------------- * Noise channel *-------------------------------------------------------------- MOV R7,R0 AI R0,PCHSEQ MOV *R0,R3 CLR R2 MOVB *R3+,R2 MOV R3,*R0 MOV R1,R0 ANDI R0,>0200 JEQ EQ816 *-------------------------------------------------------------- * Noise channel - Speed *-------------------------------------------------------------- SWPB R2 MOV R2,@SPEED MOV R2,@SPCNT B @CHECKE *-------------------------------------------------------------- * Noise channel - Stereo, ignored & volume *-------------------------------------------------------------- EQ816 MOV R1,R0 ANDI R0,>0800 JEQ EQ832 ANDI R2,>0F00 MOV R6,R0 AI R0,NVOL MOVB R2,*R0 B @CHECKE EQ832 CHECKE MOV R1,R0 ANDI R0,>1000 JEQ EQ848 MOV R7,R0 AI R0,PCHSEQ MOV *R0,R4 CLR R3 MOVB *R4+,R3 MOV R4,*R0 MOV R2,R0 ANDI R0,>0100 JEQ EQ862 *-------------------------------------------------------------- * Noise channel - Pulse vibrato mask *-------------------------------------------------------------- MOV R6,R0 AI R0,PULVIB MOVB R3,*R0 EQ862 MOV R2,R0 ANDI R0,>0200 JEQ EQ873 MOV @CALLBA,R1 JEQ EQ876 *-------------------------------------------------------------- * Callback A *-------------------------------------------------------------- MOV R2,@BACKUP MOV R3,@BACKUP+2 MOV R3,R0 BL *R1 MOV @BACKUP+2,R3 MOV @BACKUP,R2 EQ876 EQ873 MOV R2,R0 ANDI R0,>0400 JEQ EQ896 MOV @CALLBB,R1 JEQ EQ899 *-------------------------------------------------------------- * Callback B *-------------------------------------------------------------- MOV R2,@BACKUP MOV R3,@BACKUP+2 MOV R3,R0 BL *R1 MOV @BACKUP+2,R3 MOV @BACKUP,R2 EQ899 EQ896 EQ848 JMP EL915 *-------------------------------------------------------------- * Tone channel *-------------------------------------------------------------- NE804 MOV R7,R0 AI R0,PCHSEQ MOV *R0,R3 CLR R2 MOVB *R3+,R2 MOV R3,*R0 MOV R1,R0 ANDI R0,>0200 JEQ EQ930 *-------------------------------------------------------------- * Tone channel - Volume *-------------------------------------------------------------- ANDI R2,>0F00 MOV R6,R0 AI R0,NVOL MOVB R2,*R0 EQ930 MOV R1,R0 ANDI R0,>0400 JEQ EQ942 *-------------------------------------------------------------- * Tone channel - Pulse vibrato *-------------------------------------------------------------- ANDI R2,>0F00 MOV R6,R0 AI R0,PULSIZ MOVB R2,*R0 EQ942 EL915 B @NEXTBYTE *-------------------------------------------------------------- * Tone channel - Delay *-------------------------------------------------------------- EQ801 SWPB R1 SRL R1,1 INC R1 MOV R7,R0 AI R0,NDELAY MOV R1,*R0 EALINE CI R6,3 JEQ EQ974 MOV R6,R0 AI R0,PULVIB MOVB *R0,R1 SWPB R1 MOVB *R0,R1 SRC R1,1 MOVB R1,*R0 JMP JM987 *-------------------------------------------------------------- * Pulse vibrato - Noise version ? *-------------------------------------------------------------- EQ974 MOV R6,R2 AI R2,PLMASK MOVB *R2,R3 JEQ EQ1064 MOV R7,R0 AI R0,NFREQ MOV *R0,R1 ORI R1,>00E0 SWPB R1 CB R1,R3 JEQ EQ1099 MOVB R1,@SOUND MOVB R1,*R2 EQ1099 EQ1064 JM987 END668 INC @NIDX B @FOR668 HE671 EACYC CLR @NIDX FR1012 MOV @NIDX,R6 CI R6,4 JHE HE1015 MOV R6,R7 A R7,R7 MOV R6,R0 SLA R0,5 MOV R0,@NCHAN *-------------------------------------------------------------- * Handle instruments *-------------------------------------------------------------- MOV R6,R0 AI R0,NVOL CLR R1 MOVB *R0,R1 MOV R6,R0 AI R0,NINVOL CLR R2 MOVB *R0,R2 SRL R2,4 AB R2,R1 LI R3,>0F00 SB R3,R1 JOC OC1041 CLR R1 OC1041 SB R1,R3 MOV R6,R0 AI R0,PLMASK MOVB *R0,R0 JEQ EQ1126 ORI R3,>9000 MOV @NCHAN,R0 SWPB R0 SOCB R0,R3 MOVB R3,@SOUND *-------------------------------------------------------------- * Update instruments *-------------------------------------------------------------- EQ1126 MOV R6,R0 AI R0,NINSTEP MOVB *R0,R1 MOV R6,R0 AI R0,NINVOL AB R1,*R0 CI R6,3 JEQ EQ1065 BL @SETNIDXFREQ MOV R7,R0 AI R0,PVIB MOV *R0,R4 JEQ EQ1073 INC R4 MOV R6,R1 AI R1,NVCNT MOVB *R1,R2 AI R2,>FF00 MOVB R2,*R1 JNE NE1083 MOV R7,R3 AI R3,PVBASE MOV *R3,R4 LI R5,>2000 MOVB R5,*R1 NE1083 MOV R4,*R0 EQ1073 EQ1065 MOV R6,R0 AI R0,NINLEFT MOVB *R0,R1 JEQ NE1103 MOV R6,R2 AI R2,NINDELAY MOVB *R2,R3 AI R3,>FF00 MOVB R3,*R2 JNE NE1113 MOV R7,R2 AI R2,PINST MOV *R2,@PTMP MOV R0,@BACKUP BL @READINSTRUMENTATPTMP MOV @BACKUP,R0 MOVB *R0,R1 AI R1,>FF00 MOVB R1,*R0 NE1113 NE1103 EN1012 INC @NIDX B @FR1012 HE1015 LWPI WSSPC1 ; Load main workspace again RT * * COPY 'D:\Projekte\spectra\tms9900\spectra_misc.a99' * *************************************************************** * SPECTRA! * Homebrew Game & Utilities Library * for * the Texas Instruments TI-99/4A * 2009 by Filip Van Vooren * * This file: spectra_misc.a99 *************************************************************** * v0.1 - 2009/01/16 Initial version *************************************************************** * X=No input D=Data variant R=Register variant * * * UTILITY CONTROLLERS * =================== * KBSCAN - Controller: Read keyboard and joystick *************************************************************** *////////////////////////////////////////////////////////////// * UTILITY CONTROLLERS *////////////////////////////////////////////////////////////// *************************************************************** * KBSCAN - Controller: Read keyboard and joystick *************************************************************** * BL @MKSLOT * DATA P0,P1,KBSCAN *-------------------------------------------------------------- * INPUT * P0 = Slot number 0-19 * P1 = Run slot every XX ticks *-------------------------------------------------------------- * EXAMPLE * BL @MKSLOT * DATA 0,3,KBSCAN ; Scan keyboard every 3 ticks *-------------------------------------------------------------- * REMARKS * Keyboard 8x8 matrix: If 0 then bit is set * * COLUMN 0 1 2 3 4 5 6 7 * +---------------------------------+------+ * ROW 7 | = . , M N / JS1 JS2 | Fire | * ROW 6 | SPACE L K J H ; JS1 JS2 | Left | * ROW 5 | ENTER O I U Y P JS1 JS2 | Right| * ROW 4 | 9 8 7 6 0 JS1 JS2 | Down | * ROW 3 | FCTN 2 3 4 5 1 JS1 JS2 | Up | * ROW 2 | SHIFT S D F G A +------| * ROW 1 | CTRL W E R T Q | * ROW 0 | X C V B Z | * +----------------------------------------+ * See MG smart programmer 1986 * September/Page 15 and November/Page 6 * * Also see virtual keyboard status for bits to check ********@*****@*********************@************************** KBSCAN INCT STACK MOV R11,*STACK+ MOV R0,*STACK+ MOV R1,*STACK+ MOV R2,*STACK+ MOV R12,*STACK MOV @PLS1,@>83D6 ; Deactivate "screen saver" CLR @VIRTKB ; Reset virtual keyboard CLR R1 ; Value in MSB! Start with column 0 *-------------------------------------------------------------- * Scan keyboard/joystick matrix *-------@-----@---------------------@-------------------------- KBSCA1 LI R12,>0024 ; Scan whole 8x8 keyboard matrix. R12 Required by LDCR LDCR R1,3 ; Set keyboard column with a value from 0-7 (3=3 bits) LI R12,>0006 ; Load CRU base for row. R12 required by STCR STCR R2,8 ; Bring 8 row bits into MSB of R2 SWPB R1 MOVB R2,@RAMBUF(R1) ; Store BYTE in rambuffer INC R1 SWPB R1 CI R1,>0600 ; Finished ? JLE KBSCA1 ; No, scan next column *-------------------------------------------------------------- * Process column 0 (FCTN QUIT) *-------@-----@---------------------@-------------------------- KBSCA2 MOVB @RAMBUF,R0 CZC @BIT3,R0 ; FCTN key pressed ? JNE KBSCA5 CZC @BIT7,R0 ; QUIT key pressed ? JNE KBSCA5 BLWP @0 ; Reset computer *-------------------------------------------------------------- * Process column 0 (spacebar) *-------@-----@---------------------@-------------------------- KBSCA5 CZC @BIT6,R0 ; spacebar pressed ? JNE KBSCA6 SOC @BIT4,@VIRTKB ; Set space/fire/Q *-------------------------------------------------------------- * Process column 1 (9,S,X) *-------@-----@---------------------@-------------------------- KBSCA6 MOVB @RAMBUF+1,R0 CZC @BIT4,R0 ; 9 pressed ? JNE KBSCA7 SOC @BIT9,@VIRTKB ; set BACK KBSCA7 CZC @BIT2,R0 ; S pressed ? JNE KBSCA8 SOC @BIT0,@VIRTKB ; set LEFT KBSCA8 CZC @BIT0,R0 ; X pressed ? JNE KBSCA9 SOC @BIT3,@VIRTKB ; set DOWN *-------------------------------------------------------------- * Process column 2 (8,D,E) *-------@-----@---------------------@-------------------------- KBSCA9 MOVB @RAMBUF+2,R0 CZC @BIT4,R0 ; 8 pressed ? JNE KBSCAA SOC @BIT8,@VIRTKB ; set REDO KBSCAA CZC @BIT2,R0 ; D pressed ? JNE KBSCAB SOC @BIT1,@VIRTKB ; set RIGHT KBSCAB CZC @BIT1,R0 ; E pressed ? JNE KBSCAC SOC @BIT2,@VIRTKB ; set UP *-------------------------------------------------------------- * Process column 5 (P,Q) *-------@-----@---------------------@-------------------------- KBSCAC MOVB @RAMBUF+5,R0 CZC @BIT5,R0 ; P pressed ? JNE KBSCAD SOC @BIT6,@VIRTKB ; set PAUSE KBSCAD CZC @BIT1,R0 ; Q pressed ? JNE KBSCAE SOC @BIT4,@VIRTKB ; Set space/fire/Q *-------------------------------------------------------------- * Process column 6 (joystick 1) *-------@-----@---------------------@-------------------------- KBSCAE MOVB @RAMBUF+6,R0 ; Joystick 1 CZC @BIT7,R0 ; FIRE pressed ? JNE KBSCAF SOC @BIT4,@VIRTKB ; Set space/fire/Q KBSCAF CZC @BIT6,R0 ; Moved left ? JNE KBSCAG SOC @BIT0,@VIRTKB ; set LEFT KBSCAG CZC @BIT5,R0 ; Moved right ? JNE KBSCAH SOC @BIT1,@VIRTKB ; set RIGHT KBSCAH CZC @BIT4,R0 ; Moved down ? JNE KBSCAI SOC @BIT3,@VIRTKB ; set DOWN KBSCAI CZC @BIT3,R0 ; Moved up ? JNE KBSCAJ ; No, exit SOC @BIT2,@VIRTKB ; set UP *-------------------------------------------------------------- * Exit *-------@-----@---------------------@-------------------------- KBSCAJ MOV *STACK,R12 ; Pop R12 DECT STACK B @POPRG2 * * COPY 'D:\Projekte\time pilot\tms9900\tpilot_end.a99' * *************************************************************** * TIME PILOT! for the TI-99/4A DISK VERSION * by Filip Van Vooren * * FILE: tpilot_end.a99 * * This file contains game music and sound effects *************************************************************** *-------@-----@---------------------@-------------------------- SLAST * END ; For use with SAVE utility END SFIRST ; For autostart