* 1830 040784 * ** FSM.S ** ** ASTEROIDS FOR THE ATARI 3600 ** ** THIS FILE CONTAINS THE FINITE STATE MACHINE FOR ASTEROIDS. ** ** GAME SEQUENCER TO HANDLE INDIVIDUAL PLAYER'S EVENT TIMING. ** FSM: LDX PLAYER ;PLAYER MUST CONTAIN CURRENT PLAYER LDA STATE,X ;CURRENT STATE OF PLAYER BEQ CKCOMPLY ;CHECK IF COMP PLAY BPL DECTIMER ;IF IN ACTIVE STATE THEN TAKE ACTION RTS ;IF MINUS, RTS (I GUESS) DECTIMER: DEC TIMER,X ;DECREMENT EVENT TIMER CMP #BIRTH ;BIRTH STATE? BEQ BIRTHD CMP #HYPER ;HYPERSPACE STATE? BNE ZCKCOMP JMP HYPERD ZCKCOMP: CMP #COMPOVER ;COMP PLAY OVER? BNE ZCKDTH JMP COVERD ZCKDTH: CMP #DEATH ;DEATH STATE? BNE FSMRTS JMP DEATHD FSMRTS: RTS CKCOMPLY: LDA COMPFLAG ;CHECK IF ANYBODY DIED YET BEQ FSMRTS JSR CMPSCOR ;COMPARE SCORES BMI FSMRTS CMP PLAYER ;HISCORE = FIRST TO DIE? BNE FSMRTS ;YES, CONTINUE PLAY TAX LDA #COMPOVER STA STATE,X ;STATE IS REZ OUT VICTOR LDA #$FF STA COMPFLAG LDA #0 STA MENLEFT,X ;NO MORE LIVES LDA #$0D STA FLASH LDA #$0 JSR DOTUNE ;VICTOR REZOUT SOUND RTS CMPSCOR: LDX #0 ;COMPARE SCORES CMPSLOOP: LDA SCORE,X ;FIRST SCORE CMP SCORE2,X ;SECOND SCORE BCC P2BIGGR ;SCORE < SCORE2 BEQ BUMPX BCS P1BIGGR ;SCORE > SCORE2 BUMPX: INX ;LOOK AT NEXT BYTE CPX #5 BNE CMPSLOOP LDA #$FF ;SCORE = SCORE2 RTS P2BIGGR: LDA #1 RTS P1BIGGR: LDA #0 RTS ** BIRTH DISPACHER - HANDLES TIMING OF BIRTH EVENTS. ** BIRTHD: LDY OFFPLAY2 ;IF PLAYER IS NOT THERE, DON'T LDA STATUS+24,Y ; DO REZ TWINKLE BMI ZNOREZ ;DO REZ TWINKLE LDA #$05 ;DEFAULT LUME FOR AUTOPLAY LDY GAMSTATE CPY #PLAYST BNE ZREZGO ;IF NOT IN PLAY STATE, DO AUTO REZ LDA FRMCNT ;USE FRAME COUNT LO BITS FOR LUME ASL ZREZGO: JSR PAINTSHP ;PAINT THE SHIP, BODY AND DEJAG COLORS LDX PLAYER ZNOREZ: LDA TIMER,X ;CHECK TIMER TO DISPATCH CMP #PMSGT ;TIME TO PUT UP PLAYER MESSAGE? BEQ PMSG ; YES, PUT IT UP CMP #PMSGOFFT ;TIME TO TAKE DOWN MESSAGE? BEQ PMSGOFF ; YES, TAKE IT DOWN CMP #RESINT ;TIME TO RES IN? BEQ RESIN ; YES, RES IN. IF LATER THAN RESINT, BCC OPTENTER ; CHECK FOR OPTIONAL ENTER (JSTICK) RTS ;OTHERWISE, JUST RTS * ROUTINE TO PUT UP THE PLAYER X MESSAGE IF NEEDED. * PMSG: LDA MODE ;NO MESSAGES IN TEAM MODES CMP #1 BPL ZPLRTS JSR SETMSG ZPLRTS: RTS * ROUTINE TO TURN PLAYER X MESSAGE OFF. * PMSGOFF: LDA #$FF ;TURN OFF HIGH MESSAGE STA STATUS+34 RTS * ROUTINE TO ENTER THE SHIP IF DESIRED OR NEEDED. * OPTENTER: LDA GAMSTATE ;DO ONLY IF GAMEPLAY STATE CMP #PLAYST BNE ZCKTIMM ;FIRST CHECK TO SEE IF PLAYER IS FORCING SHIP IN LDA FIREBUT1,X ;FIRE BUTTON AND HYPBUT1,X ;HYPERSPACE BUTTON BPL ENTSHIP ; IS PRESSED! ENTER HIM LDA SWCHA ;JOYSTICK EOR #$FF ; (INVERTED) AND JOYTBL,X ; (LOOK AT ONLY CORRECT PLAYER'S BITS) BNE ENTSHIP ; IS HIT! ENTER HIM ;NOW CHECK IF IT IS TIME, AND IS SAFE. ZCKTIMM: LDA TIMER,X ;CHECK TIMER CMP #ENTERT BCS ENTRTS ;NOT TIME YET, DON'T BOTHER LDA OFFPLAY2 ;CHECK SAFTEY CLC ADC #24 TAX JSR ISSAFE ;CHECK IF AREA SAFE TO ENTER BEQ ENTSHIP ;YES, CONTINUE ;NOT SAFE, HOLD TIMER HERE INDEFINITELY LDX PLAYER INC TIMER,X ENTRTS: RTS ENTSHIP: LDA #2 ;KILL TWINKLING JSR KILLTUNE LDA #$3 ;ADD BUZZING IN JSR DOTUNE LDA PLAYER ;CHANGE BODY COLOR ASL ASL TAX LDA COLORS+2,X STA SOFTCOLR+2,X LDA COLORS+3,X STA SOFTCOLR+3,X LDX PLAYER LDA #1 ;DEBOUNCE ENTER/FIRE BUTTON STA FIRESTAT,X LDA #OK ;SET STATE AS OK STA STATE,X RTS ** ROUTINE TO RESIN AND TWINKLE SHIP AT ENTERING. ** RESIN: LDA STATUS+25 ;CHECK STATUS OF UFO BMI ZGONOW ;DON'T BRING SHIP IN IF UFO INC TIMER,X RTS ZGONOW: LDA GAMSTATE ;DON'T DECREMENT IF AUTOPLAY CMP #AUTOST BEQ ZNODECM LDA MODE ;CHECK TO DEC FROM COMMON POOL CMP #1 BNE ZNOPOOL LDA MENLEFTC ;CHECK: IF NO MENLEFT, JUST HANG OUT CMP #1 ; AND WAIT; PERHAPS OTHER PLAYER WILL BCS ZYESMEN ; BRING HIM IN A LIFE. INC TIMER,X ; (HOLD TIMER AT THIS POINT IN TIME) RTS ZYESMEN: LDX #2 ;2 = COMMON POOL ZNOPOOL: DEC MENLEFT,X ;DEC FROM PLAYERS LIVES JSR UPDATMEN ZNODECM: LDA #2 ;TWINKLING SOUND JSR DOTUNE ZINITPOS: LDX OFFPLAY2 ;INITIALIZE THE SHIP'S POSITION LDA #0 STA XVELH+24,X STA YVELH+24,X STA XVELL+24,X STA YVELL+24,X STA GOATMILK ;?? LDA MODE CMP #1 BMI ZCENTERS LDY PLAYER LDA INITSX,Y ;GET X POS VALUE FOR PLAYER BPL ZSTORSX ;BPL = JMP HERE. ZCENTERS: LDA #$50 ZSTORSX: STA XPOSH+24,X CLC ADC DELTAX+3 ;COULD SQUEEZE A BYTE HERE: USE IMMED. STA COLXPOSH+24,X LDA #$50 STA YPOSH+24,X CLC ADC DELTAY+3 ;COULD SQUEEZE HERE TOO. STA COLYPOSH+24,X LDX PLAYER ;STORE FIRST ANIMATION LDA SHIPDIR,X LSR LSR LSR AND #$FE CLC ADC #SHIP1 & 255 LDX OFFPLAY2 STA ACYC+24,X LDA #SHIP ;STORE STATUS AS SHIP STA STATUS+24,X RTS INITSX: .DC.B $30,$70 ;XPOS VALUES FOR INITIAL SHIP POS JOYTBL: .DC.B $F0,$0F ;JSTICK MASKS, INDEXED BY PLAYER. ** HYPER SPACE DISPACHER - HANDLES TIMING OF HYPER SPACE EVENTS. ** HYPERD: LDA TIMER,X ;CURRENT PLAYERS EVENT TIMER CMP #HYPERT ;TIME TO JUMP HYPERSPACE? BEQ HYPERGO ; YES, DO IT. CMP #HYPENDT ;TIME TO END HYPERSPACE BEQ HYPEND ; YES, DO IT. RTS ;OTHERWISE, JUST RTS * ROUTINE TO HANDLE THE JUMP TO HYPERSPACE. * HYPERGO: LDA #$01 ;SOUND JSR DOTUNE LDX OFFPLAY2 ;NULL OUT SHIP LDA #$FF STA STATUS+24,X LDA #0 ;NULL VELOCITY STA XVELL+24,X STA XVELH+24,X STA YVELL+24,X STA YVELH+24,X RTS * ROUTINE TO HANDLE THE RETURN FROM HYPERSPACE. * HYPEND: LDA #24 CLC ADC OFFPLAY2 TAX JSR NEWRAND ;GET NEW SHIP POSITION LSR ; AVOID EXTREME SIDES ADC #$D ; (BETWEEN $D AND $8C) STA XPOSH,X JSR NEWRAND ;GET Y POSITION; AVOID TOP AND BOTTOM LSR ADC #$10 ; (BETWEEN $10 AND $90) STA YPOSH,X JSR ISSAFE ;SAFE TO ENTER BEQ GOBIGRED ;YOU BET LDX PLAYER ;SORRY CHARLIE INC TIMER,X RTS GOBIGRED: JSR NEWRAND ;GET RANDOM VALUE CMP #50 ;SOMETIMES LET THE SHIP EXPLODE BCS NOBLOW ;OTHERWISE SET NEW POSITION ;EXPLODE HIM! LDA #24 ;WITHOUT THIS X = 'FF' SOMETIMES CLC ADC OFFPLAY2 TAX LDA #$A3 ;BOOM !! SET HIGH BIT OF STATUS STA STATUS,X LDA ELBOUND+3 ;SET ANIMATION STAMP STA ACYC,X LDA #5 ;START SHIP EXPLOSION SOUND JSR DOTUNE LDX PLAYER BLOW: LDA #DEATH ;SET STATE LDX PLAYER STA STATE,X LDA #DIET+$28 ;ENTER TIMELINE AT TOP STA TIMER,X RTS NOBLOW: LDA #3 ;BUZZ SOUND JSR DOTUNE LDA #SHIP ;RESTORE SHIP LDX TEMP STA STATUS,X LDX PLAYER LDA #OK ;RETURN STATE TO OK. STA STATE,X RTS ** COMP PLAY OVER DISPACHER - HANDLES TAKING SHIP OUT. ** COVERD: * LDX PLAYER LDA FLASH INC FLASH CMP #$20 BEQ ZTAB CMP #$2E BNE CCONTIN ;ALL DONE JMP BLOW ;JUMP INTO HYPER CODE CCONTIN: BIT BPLOP BEQ DOPAINT EOR #$1F DOPAINT: JSR PAINTSHP RTS ZTAB: LDX OFFPLAY2 ;NUKE SHIP LDA #$FF STA STATUS+24,X RTS ** DEATH DISPACHER - HANDLES TIMING OF DEATH SEQUENCE. ** DEATHD: LDA TIMER,X ;CURRENT PLAYERS EVENT TIMER CMP #DIET ;TOP OF DEATH TIMELINE? BEQ DIE ; YES, GO TO DIE HANDLER CMP #SWITCHT ;TIME TO SWITCH PLAYER? BNE ZCKPOT JMP SWITCH ; YES, SWITCH. ZCKPOT: CMP #POMSGT ;TIME TO DISPLAY PLAYERX OVER? BNE ZCOKE JMP POMSG ; YES, DO IT. ZCOKE: CMP #POMSGOFT ;TIME TO TURN OFF MESSAGE? BEQ POMSGOFF ; YES, DO IT. CMP #GOVERT ;TIME TO DISPLAY GAME OVER MESSAGE? BEQ GOVER ; YES, DO IT. CMP #NEWGAMET ;END OF DEATH TIMELINE? BNE DEATHRTS ;YES, SET UP FOR HIGH SCORE CART JSR CLEARTUN ;GET RID OF ANY TUNES JSR NULLOBJS ;GET RID OF ANY OBJECTS JSR HSCDOENT JMP DOTITLE DEATHRTS: RTS * ROUTINE TO TAKE DOWN THE ABOVE * POMSGOFF: LDA #$FF ;NULL OUT BOTH MESSAGES STA STATUS+34 STA STATUS+35 TXA ;CHECK OTHER PLAYER FOR GAME OVER COND. EOR #$01 ; HERE'S HOW IT WORKS: ONLY ONE PLAYER TAY ; ACTUALLY MAKES IT TO THE GAME OVER LDA #DEAD ; MESSAGE TIME. SO, THE FIRST PLAYER CMP STATE,Y ; TO MAKE IT TO POMSGOFF BECOMES DEAD BEQ DEATHRTS ; THE OTHER LIVES ON TO GET TO GOVER! STA STATE,X ;MAKE PLAYER DEAD, SINCE OTHER IS LIVE. LDA MODE ;IN TWO PLAYER MODE, SWITCH DATA NOW BNE DEATHRTS ; SO WE DON'T GET STUCK PLAYING JMP SWITCH ; A DEAD PLAYER (FSM WON'T RUN ON HIM) RTS * ROUTINE TO PUT UP GAME OVER MESSAGE * GOVER: LDX #2 ;GAME OVER MESSAGE JSR SETMSG JSR HIGHSCOR RTS * ROUTINE TO HANDLE DEATH OF A SHIP. * * ALL DEATHS GO HERE. THIS ROUTINE FIGURES OUT WHERE WE SHOULD BE GOING. * DIE: JSR INITHUMP ;REINIT THUMP RATE LDA #$11 ;KILL THRUST SOUND JSR KILLTUNE LDX PLAYER ;RESTORE X, TRASHED BY KILLTUNE ;HANDLE MODES DIFFERENTLY LDY MODE LDA MENLEFTC ;LOAD TEAMPLAY MENLEFT AS DEFAULT CPY #1 BEQ ZDIEMN1 ;IF NOT TEAMPLAY MODE LDA MENLEFT,X ; USE CURRENT MENLEFT ZDIEMN1: CMP #1 ;IF WE HAVE NO MEN LEFT BCC NOMENLFT ; HANDLE THIS SITUATION CPY #0 ;ELSE IF NOT TWO PLAYER MODE BNE GIVEBRTH ; SIMPLY TRY TO GIVE BIRTH. TXA ;ELSE TWO PLAYER MODE: EOR #$01 ; CHECK OTHER PLAYER'S MENLEFT. TAX LDA MENLEFT,X CMP #1 ; IF HE HAS MEN LEFT THEN BCS DEATHRTS ; SIMPLY RTS. SWITCH WILL DO THE TRICK JMP GIVBRTH2 ; ELES SKIP THE SWITCH. GIVE BIRTH NOW NOMENLFT: CPY #$FF ;ELSE, IF ONE PLAYER MODE BEQ DIEGOVER ; DIE WITH SIMPLE GAMEOVER (NO PMSG) CPY #$1 ;ELSE, IF NOT IN TEAM PLAY MODE BNE DIEPOVER ; DIE WITH PLAYER OVER MESSAGE TXA ;ELSE CHECK OTHER PLAYER'S STATE EOR #$01 ; TO SEE WHETHER TO END THE GAME TAX LDA STATE,X CMP #BIRTH ; IF OTHER PLAYER IS NOT IN BIRTH BNE GIVEBRTH ; THEN TRY TO GIVE BIRTH. LDA OFFPLAY2 ; OTHERWISE, EOR #$08 ; (TOGGLE OFFPLAY2) TAY LDA STATUS+24,Y ; IF HE IS NOT YET BORN, THEN CMP #SHIP ; FORGET IT BUD. AIN'T NO LIVES LEFT BEQ GIVEBRTH ; FOR EITHER OF THEM. LDA #DEAD ; NUKE OTHER PLAYER OUT OF BIRTHST STA STATE,X ; TO PREVENT A NEW RACK FROM STARTING DIEGOVER: LDA #GOVERT+3 ;DIE WITH GAME OVER MESSAGE ONLY BNE ZDIEOVER ; BNE = JMP DIEPOVER: LDA #POMSGT+3 ;DIE WITH PLAYER N GAME OVER MESSAGE ZDIEOVER: LDX PLAYER STA TIMER,X RTS GIVEBRTH: LDX PLAYER LDA #BIRTH ;GIVE BIRTH STA STATE,X LDA #RESINT+3 ;AT TIMER RESIN+3 STA TIMER,X RTS * ROUTINE TO PUT UP PLAYERX GAME OVER MESSAGE * POMSG: LDX PLAYER ;PLAYERX MESSAGE LDA COMPFLAG BMI PVICTOR BEQ PPLAYER JSR CMPSCOR ;COMPARE SCORES TAX BPL PVICTOR ; TIE SCORE LDA GOATMILK ;CHECK FLAG BNE PUNTTHIS ;SHIP TO SHIP LDX PLAYER ;NO, PUT MESSAGE FOR THIS GUY BPL PVICTOR ; = JMP PUNTTHIS: LDA #$FF ;RETURN W/OUT MSG IF EQUAL STA STATUS+34 ;TAKE MSG DOWN BEFORE SEEN STA STATUS+35 RTS PPLAYER: JSR SETMSG LDX #2 DOMSG: JSR SETMSG LDX MODE CPX #2 BNE ZPORTS STX COMPFLAG ZPORTS: RTS PVICTOR: JSR SETMSG ;X HAS PLAYER LDX #3 BPL DOMSG ;BPL = JMP * ROUTINE TO SWITCH THE TWO DATA SETS WHEN NEEDED. * SWITCH: TXA ;TOGGLE CURRENT PLAYER # AND OFFSET EOR #$01 TAX STA PLAYER BEQ ZSTOFFP2 LDA #8 ZSTOFFP2: STA OFFPLAY2 LDA #$FF ;NULL OUT SPACE OBJECTS LDX #7 ; (31-23=8 OBJECTS) SWCHNULL: STA STATUS+24,X DEX BPL SWCHNULL LDA #0 STA RACKDLY ;NO DELAY AFTER SWITCH LDA #$50 STA RTIMER ;RESET UFO FREQUENCY AND TIMER LDA #$92 STA SDELAY STA EDELAY JSR CLEARTUN ;KILL TUNES, ESP. UFO LDY #23 SWCHLOOP: LDX STATUS,Y LDA STATUS2,Y STA STATUS,Y TXA STA STATUS2,Y * LDX ACYC,Y LDA ACYC2,Y STA ACYC,Y TXA STA ACYC2,Y * LDX PALS,Y LDA PALS2,Y STA PALS,Y TXA STA PALS2,Y * LDX XVELH,Y LDA XVELH2,Y STA XVELH,Y TXA STA XVELH2,Y * LDX YVELH,Y LDA YVELH2,Y STA YVELH,Y TXA STA YVELH2,Y * LDX XVELL,Y LDA XVELL2,Y STA XVELL,Y TXA STA XVELL2,Y * LDX YVELL,Y LDA YVELL2,Y STA YVELL,Y TXA STA YVELL2,Y * LDX XPOSH,Y LDA XPOSH2,Y STA XPOSH,Y TXA STA XPOSH2,Y * LDX YPOSH,Y LDA YPOSH2,Y STA YPOSH,Y TXA STA YPOSH2,Y DEY BPL SWCHLOOP GIVBRTH2: LDX PLAYER ;GIVE BIRTH, TWO PLAYER STYLE (PMSG) LDA #BIRTH ;GIVE BIRTH STA STATE,X LDA #PMSGT+$20 ;AT TIMER PMSGT+20 STA TIMER,X RTS