* 1850 030784 * ** UTILS.S * ** ASTEROIDS FOR THE ATARI 3600 ** ** THIS FILE CONTAINS UTILITY PROGRAMS. ** * ** PRESENTLY CONTAINS - * * GAME PLAY LOOP * * DIFFICULTY LEVEL INC ROUTINE * * RANDOM NUMBER ROUTINES * * SAFETY BOX CHECK ROUTINE * * FLIP PLAYER ROUTINE * * STAR TWINKLER * * ICON SETUP ROUTINE * * PAINT SHIP ROUTINE * * WAIT FOR LOADER ROUTINE * * ** BASIC GAME PLAY LOOP. ** GAMELOOP: ;SET DIFFICULTY LEVELS LDX PLAYER LDA LEVEL,X STA MINYVEL ;SET MINYVEL AND MINXVEL LSR STA MINXVEL LDA ROCKTOT,X ;CONTINUE UNTIL ROCKTOT = 0 BNE GAMEPLAY LDA STATUS+25 ;WAIT FOR UFO TO LEAVE BEFORE NEW RACK CMP #$FF ;FF = NON-EXISTANT BNE GAMEPLAY ;IF HE EXISTS, JUST WAIT IN GAMEPLAY LDA STATE ;IF EITHER PLAYER IS IN STATE 0 OR 1 AND STATE+1 ; (THAT IS, OK OR BIRTH) CMP #2 ; THEN THIS 'AND' WILL BE LESS THAN 2 BCS GAMEPLAY ; IF IT ISN'T, THEN WAIT IN GAMEPLAY LDA MODE BNE ZDECRDLY ;IN TWO PLAYER, DON'T CREATE ROCKS LDY OFFPLAY2 ; IF CURRENT PLAYER IS DEAD, SO AS LDA STATUS+24,Y ; NOT TO CREATE ROCKS AND IMMEDIATELY BMI GAMEPLAY ; SWITCH THEM OUT. ZDECRDLY: DEC RACKDLY ;DON'T DO NEW RACK 'TILL DLY OVER BPL GAMEPLAY ;LET THE SHOW GO ON ! LDA #RACKDLYC ;PRIME TIMER FOR NEXT RACK STA RACKDLY INC RACKNUM,X ;WHEN =0 NEW RACK LDA RACKNUM,X ;SET NUM OF ROCKS TO BE RACKNUM CLC ADC #2 ; PLUS TW0 ADC DIFF ; PLUS DIFF (NOVICE=0,EXPERT=3) STA ROCKTOT,X LDY DIFF ;DETERMINE MAX NUMBER OF ROCKS LDA MAXROCKS,Y CMP ROCKTOT,X ; UP TO A MAXIMUM BCS NEWRACK STA ROCKTOT,X NEWRACK: STA STARTNUM,X JSR LOADSTAR ;LOAD STARS INTO DISPLAY HEADERS. LDA #1 ;TYPE 1 INCREMENT FOR RACK JSR INCLVL LDA #$50 ;5.2 SEC COUNTER FOR UFO STA RTIMER LDX DIFF LDA UTIMES,X ;UFO LDX PLAYER SEC SBC RACKNUM,X SBC RACKNUM,X SBC RACKNUM,X STA SDELAY STA EDELAY LDA #9 STA UFOACC ;SET ACCURACY DOWN TO MINIMUM LDA #$28 ;INITIALIZE UFO SHOT COUNTDOWN STA USHOTCNT JSR INITHUMP ;RESET THE HUMP RATE. JSR INITROCK ;INITIALIZE THE ROCKS GAMEPLAY: JSR FSM ;FINITE STATE MACHINE JSR JOY ;EXECUTE JOYSTICK INPUTS LDA MODE ;REPEAT FOR TEAM PLAY MODES CMP #1 BMI NOTEAM JSR FLIPPLAY ;FLIP PLAYER JSR FSM ;REPEAT FOR OTHER PLAYER JSR JOY JSR FLIPPLAY NOTEAM: JSR ROCKMOVE ;UPDATE OBJECT MOVEMENT JSR SHOTMOVE ;UPDATE SHOT MOVEMENT JSR COLLIDE ;CHECK COLLISIONS JSR EXPLODE ;CHECK EXPLOSIONS JSR UFO ;UPDATE UFO JSR BACKSNDS ;ADD BACKGROUND SOUNDS RTS MAXROCKS: .DC.B 8,12,14,16 ;MAX NUM ROCKS FOR EACH DIFF UTIMES: .DC.B 0,$A7,$95,$8F ** DIFFICULTY LEVEL INCREMENT ROUTINE ** ** CALLED WITH TYPE OF INCREMENT IN AC, TRASHES Y ** ** TYPES: 0 = POINTS, 1 = RACKS, 2 = MR. BILL, 3 = SLUGGO ** INCLVL: TAY LDA LVLINC,Y LDY PLAYER CLC ADC LEVEL,Y CMP MAXLVL ;THERE IS ONLY ONE MAX FOR BOTH PLAYERS BCC LVLOK LDA MAXLVL LVLOK: STA LEVEL,Y RTS ** RANDOM NUMBER ROUTINES, >NOT< PREVIOUSLY IN RANDOM.S ** * NEWRAND: A WHOLESOME RANDOM NUMBER JENERATER FROM KNUTH (NOTABLE PEDIGREE) NEWRAND: LDY RANDPTR0 ;LOAD Y WITH CONTENTS OF RANDPTR0 LDA RAND,Y ;LOAD AC WITH RAND INDEXED BY Y CLC ;CLEAR THE CARRY LDY RANDPTR1 ;LOAD Y WITH CONTENTS OF RANDPTR1 ADC RAND,Y ;ADD RAND INDEXED BY Y TO AC LDY RANDPTR0 ;GET THE DRIFT? STA RAND,Y DEC RANDPTR0 BPL ZR1 LDY #54 STY RANDPTR0 ZR1: DEC RANDPTR1 BPL ZR2 LDY #54 STY RANDPTR1 ZR2: RTS RANDPOS: JSR NEWRAND LSR BCC HBORDER LDA #YPOSMAX STA YPOSH,X XRANDLOP: JSR NEWRAND CMP #XPOSMAX-6 BCS XRANDLOP STA XPOSH,X RTS HBORDER: LDA #XPOSMAX STA XPOSH,X YRANDLOP: JSR NEWRAND CMP #YPOSMAX BCS YRANDLOP STA YPOSH,X RTS RANDVEL: JSR NEWRAND ROL ;USE SIGN BIT FOR DIRECTION (L OR R) BCC RNDVXPOS ;X VELOCITY IS POSITIVE SBC MINXVEL ;ADD IN MINIMUM VELOCITY STA XVELL,X LDA #$FF ;VELOCITY IS NEGATIVE SBC #0 ;TAKE AWAY THE BORROW, IF ANY STA XVELH,X BCS RANDVY ;UNCOND. BRANCH RNDVXPOS: ADC MINXVEL ;ADD IN MINIMUM VELOCITY STA XVELL,X LDA #0 ROL ;ROL IN THE CARRY, IF ANY STA XVELH,X RANDVY: JSR NEWRAND ROL BCC RNDVYPOS SBC MINYVEL STA YVELL,X LDA #$FF SBC #0 STA YVELH,X BCS RANDVRTS RNDVYPOS: ADC MINYVEL STA YVELL,X LDA #0 ROL STA YVELH,X RANDVRTS: RTS * CHECK IF ANY OBJECT IS IN SAFETY BOX. * RETURNS WITH ZERO (Z) BIT SET IF ALL IS CLEAR. * WE DON'T WORRY ABOUT CARRIES (LOW PRECISION). * DESTROYS: X, Y, AND FIRST 7 BYTES OF TEMP * TEMP LAYOUT: TEMP X (OBJECT INDEX) * TEMP+1 BOXR (RIGHT HAND BOUNDARY) * TEMP+2 BOXL (LEFT HAND BOUNDARY) * TEMP+3 BOXTOP (TOP BOUNDARY) * TEMP+4 BOXBOT (BOTTOM BOUNDARY) * TEMP+5 X WRAP FLAG (1 = WRAP) * TEMP+6 Y WRAP FLAG (1 = WRAP) ISSAFE: STX TEMP ;SAVE X WHERE IT MAY BE COMPARED TO Y LDA #0 ;0 MEANS "NO WRAP OF BOX" STA TEMP+5 STA TEMP+6 LDA XPOSH,X ;CHECK RIGHT HAND SIDE OF BOX. ADC BOXWIDTH ; (SHOULD CLC HERE....) STA TEMP+1 ;BOXR SBC #XPOSMAX ;CHECK FOR WRAPAROUND. BCC BOXROK ; BOX'S RIGHT HAND SIDE: NO WRAP. INC TEMP+5 ; YES WRAP: SET FLAG STA TEMP+1 BOXROK: LDA XPOSH,X ;CHECK LEFT HAND SIDE OF BOX. SBC BOXWIDTH BCS BOXLOK ;CHECK FOR WRAPAROUND. INC TEMP+5 ; YES WRAP: SET FLAG ADC #XPOSMAX ; MOD INTO RANGE BOXLOK: STA TEMP+2 ; AND SAVE IT (BOXL). LDA YPOSH,X ;CHECK TOP OF BOX. ADC BOXHIGHT STA TEMP+3 SBC #YPOSMAX BCC BOXTOK INC TEMP+6 STA TEMP+3 BOXTOK: LDA YPOSH,X ;CHECK BOTTOM OF BOX. SBC BOXHIGHT BCS BOXBOK INC TEMP+6 ADC #YPOSMAX BOXBOK: STA TEMP+4 LDX #32 ;START WITH LAST OBJECT (#32) NEXTSAFE: LDA STATUS,X ;CHECK ITS STATUS: BMI SAFEOK ; IF OBJECT DOESN'T EXIST, IT IS SAFE. ;FIRST CHECK X COORDS LDA #0 ;CLEAR OUT COMPARISON REGISTER "A" LDY XPOSH,X ;GET OBJECT X'S HORIZ. POSITION CPY TEMP+1 ;COMPARE TO BOXR ROL ;ROL BIT INTO A CPY TEMP+2 ;COMPARE TO BOXL ADC #0 ;ADD BIT INTO A EOR TEMP+5 ;FLIP LOW BIT WITH X WRAP BIT ROR ;ROR BIT INTO CARRY BCC SAFEOK ;NO BIT MEANS SAFE (OUTSIDE OF BOX). ;THEN CHECK Y COORDS LDA #0 LDY YPOSH,X CPY TEMP+3 ROL CPY TEMP+4 ADC #0 EOR TEMP+6 ROR BCC SAFEOK ;FINALLY, CHECK IF IT IS THE OBJECT SPECIFIED ITSELF. CPX TEMP BEQ SAFEOK ;OBJECT IN BOX! UNSAFE TO ENTER! ; LDY #1 ;CLEAR Z BIT TO SIGNIFY NOT CLEAR. ;NOT NEEDED (BEQ ABOVE) RTS SAFEOK: DEX ;GET NEXT OBJECT BPL NEXTSAFE ;AND CONTINUE CHECKING LDY #0 ;SET Z BIT TO SIGNIFY ALL CLEAR. RTS BOXWIDTH: .DC.B $10 BOXHIGHT: .DC.B $1A * ROUTINE TO PUT UP SCORES. WHATEVER IS IN PLAYER OR HIGH SCORES GOES. * DOSCORE: JSR CLSCORE ;ERASE ALL SCORES FIRST JSR PUTHISCR ;HIGH SCORE UP LDA MODE CMP #1 ;COMBINED SCORE BNE ZPLRSCOR LDA #2 STA SCORER JSR PUTSCORE JSR PUTMEN LDA #0 STA SCORER JSR PUTSCORE LDA #1 STA SCORER JSR PUTSCORE RTS ZPLRSCOR: LDA #0 STA SCORER JSR PUTSCORE ;PLAYER 1 SCORE UP JSR PUTMEN LDA MODE BMI NOP2SCOR LDA #1 STA SCORER JSR PUTSCORE ;PLAYER 2 SCORE UP JSR PUTMEN NOP2SCOR: RTS * ROUTINE TO ERASE SCORES. * CLSCORE: LDX #56 ;CLEAR MAPS LDA #0 ZCLRLOOP: STA CHARMAPS,X DEX BPLOP: BPL ZCLRLOOP ;LABLED TO ACCESS BPL OPCODE ($10) RTS ** ROUTINE USED IN GAME LOOP TO TOGGLE PLAYER BACK AND FORTH. ** FLIPPLAY: LDA PLAYER ;CHANGE PLAYER EOR #1 STA PLAYER BEQ STOROFF ;ESTABLISH DATA OFFSET LDA #8 ;SECOND PLAYER POINTS TO END STOROFF: STA OFFPLAY2 RTS * ROTATE THROUGH THE COLORS TO TWINKLE THE STARS. TWINKLE: JSR NEWRAND ;DECIDE WHICH STARS TO TW'INC'LE LSR BCC NOINC2 LSR BCC NOINC2 INC SOFTCOLR+14 NOINC2: LSR BCC LOGODO LSR BCC LOGODO INC SOFTCOLR+15 LOGODO: LDA GAMSTATE ;DON'T DO LOGOBARS WHILE PLAYING CMP #PLAYST BEQ LOGORTS CMP #AUTOST BEQ LOGORTS LOGOBARS: LDA FRMCNT ;DO IT ONLY ON EVEN FRAMES LSR BCS LOGORTS INC TEMP+11 ;MOVE THIS!! LDA TEMP+11 BIT BPLOP ;(BPLOP: OPCODE $10 IS BPL) BNE LOGOGO EOR #$1F LOGOGO: STA SOFTCOLR+10 ;UPDATE HARDWARE REGISTER LOGORTS: RTS * SET UP AN ICON: * ON ENTRY: Y SHOULD CONTAIN ICON NUMBER * X SHOULD CONTAIN INDEX NUMBER OF NEW OBJECT DOICON: LDA ICONACYC,Y STA ACYC,X LDA ICONXPOS,Y STA XPOSH,X LDA ICONYPOS,Y STA YPOSH,X LDA ICONPALS,Y STA PALS,X LDA #ICON CPY #22 ;ICONS > 22 ARE SHIPS BCC ZISICON LDA #SHIP ZISICON: STA STATUS,X RTS * PAINTSHP -- PAINT THE SHIP, BODY AND DEJAG AND FLAME COLORS * ARGUMENTS: X CONTAINS THE PLAYER TO PAINT * A CONTAINS THE DESIRED LUME OF THE BODY PAINTSHP: AND #$0F ;KNOCK OFF EXTRANEOUS BITS ORA BODYHUES,X ;OR IN THE CORRECT BODY HUE PHA ;PUSH BODY COLOR LSR ;LOWER INTENSITY FOR DEJAG LUME AND #$07 ;KNOCK OFF EXTRANEOUS BITS ORA BODYHUES,X ;OR IN THE CORRECT BODY HUE CPX #0 ;WHICH PLAYER? BEQ ZPAINTGO ;FOR 1ST PLAYER, USE 1ST PALETTE LDX #4 ;FOR 2ND PLAYER, USE 2ND PALETTE ZPAINTGO: STA SOFTCOLR+3,X ;STORE DEJAG COLOR PLA ;PULL BODY COLOR STA SOFTCOLR+2,X ;STORE BODY COLOR LDA #0 ;TURN OFF SHIP'S THRUST FLAME STA SOFTCOLR+1,X RTS * REFRESH COLOR RAM, UPPER 4 PALETTES FROM ROM, LOWER 4 FROM RAM REFRESH: LDX #$1F ZEFRESH: LDA COLORS,X STA BACKGRND,X DEX LDA COLORS,X STA BACKGRND,X DEX LDA COLORS,X STA BACKGRND,X DEX DEX ;SKIP OVER OTHER HARDWARE REGISTERS CPX #$10 ;$10 - $1F FROM ROM (COLORS) BCS ZEFRESH * NOW DO RAM PART: Z2FRESH: LDA SOFTCOLR,X STA BACKGRND,X DEX LDA SOFTCOLR,X STA BACKGRND,X DEX LDA SOFTCOLR,X STA BACKGRND,X DEX DEX ;SKIP OVER OTHER HARDWARE REGISTERS BPL Z2FRESH INX ;$FF + 1 = $00 STX BACKGRND ;FORCE BLACK BACKGROUND RTS WAITLOAD: LDA #1 ;SET LOAD FLAG STA LOADFLAG ZWAIT: LDA LOADFLAG ;WAIT FOR LOADER TO FINISH BEQ ZWRTS ;IF LOADER FINISHED THEN RTS BIT MSTAT ;IF OFF SCREEN FORCE LOAD BPL ZWAIT BIT MSTAT ;PROTECTION BPL ZWAIT JSR REFRESH ;MAKE SURE COLORS ARE RIGHT FIRST JSR LOADER ZWRTS: RTS