* 1515 030784 * * ** COLLIDE.S ** ** ASTEROIDS FOR THE ATARI 3600 ** ** THIS FILE CONTAINS THE COLLISION HANDLING ROUTINE. ** ** ** INDEXING - ROCKS 0 THRU 23 ** SHIP 24 ** UFO 25 ** UFOSHOT 26 THRU 27 ** SHIPSHOT 28 THRU 31 ** SHIP2 32 ** ** STATUS - LO NYBBLE - OBJECT TYPE - 0 - SMALL ROCK ** 1 - MEDIUM ROCK ** 2 - LARGE ROCK ** 3 - SHIP ** 4 - SMALL UFO ** 5 - LARGE UFO ** 6 - SHOT ** 7 - SHIP'S PARTS (+MISC JUNK) ** HI NYBBLE - OBJECT SIZE - INDEX INTO SIZE TABLES ** (UNUSED, I BELIEVE) ** ** < 0 - NULL OBJECT ** ** USES TEMP LOCATIONS AS FOLLOWS: ** TEMP DX (REUSED LATER) ** TEMP+1 DY ** TEMP+2 DX+DY (MANHATTAN DISTANCE) ** TEMP+3,TEMP+4 SAVE AREA FOR INDEX REGISTERS X & Y ** TEMP+5,TEMP+6 SAVE AREA FOR 'TYPE NYBBLES' ** (IE, LO NYBBLE OF STATUS BYTE) ** TEMP+7 ROCK TYPE, IN THE EVENT OF AN EXPLOSION ** TEMP+8,TEMP+9 SHORT TERM SCRATCH TEMP ** TEMP+10 SHIP'S DIRECTION INDEX ** ******************************************************************************** COLLIDE: LDA RUBFLAG ;DECREMENT RUBBER SHIP FLAG IF NEEDED BMI ZNODERUB DEC RUBFLAG ZNODERUB: LDX #32 ;START CHECKING WITH SHIP2 COLNXTX: LDA STATUS,X ;IF OBJECT X DOESN'T EXIST THEN BMI DECX ;GO ON TO NEXT X LDY COLTAB-24,X ;FETCH FIRST OBJECT TO CHECK COLNXTY: LDA STATUS,Y ;IF OBJECT Y DOESN'T EXIST THEN BMI DECY ;GO ON TO NEXT Y STX TEMP+3 ;SAVE X AND Y STY TEMP+4 JMP COLCHK ;CHECK FOR COLLISION RESTORE: LDX TEMP+3 ;RESTORE X AND Y LDY TEMP+4 DECY: DEY BPL COLNXTY DECX: DEX CPX #24 BPL COLNXTX COLRTS: RTS * CHECK FOR AN ACTUAL COLLISION BETWEEN OBJECTS WHOSE INDICES ARE IN X AND Y. COLCHK: LDA COLXPOSH,X ;COMPUTE DX SEC SBC COLXPOSH,Y BCS DXPOS ;TAKE ABSOLUTE VALUE EOR #$FF ; CLC ;CARRY MUST ALREADY BE CLR (BCS ABOVE) ADC #1 DXPOS: CMP #XPOSMAX-13 ;CHECK FOR WRAPAROUND (WIDEST OBJ=12) BCC DXOK ;NO WRAP CPX #25 ;DON'T X-WRAP THE UFO BEQ DXOK CPY #25 BEQ DXOK SEC SBC #XPOSMAX+1 ;USE WRAPPED DISTANCE EOR #$FF ; CLC ;CARRY IS CLEAR FROM SBC (IE, BORROW) ADC #1 DXOK: CMP #10 ;FURTHEST COLLISION HAS DX OF ONLY 10 BCS NOCOL ; IF >= 11, NO COLLISION. STA TEMP LDA COLYPOSH,X ;COMPUTE DY SEC SBC COLYPOSH,Y BCS DYPOS ;TAKE ABSOLUTE VALUE EOR #$FF ; CLC ;CARRY MUST ALREADY BE CLR (BCS ABOVE) ADC #1 DYPOS: CMP #YPOSMAX-17 ;CHECK FOR WRAPAROUND (TALLEST OBJ=16) BCC DYOK ;NO WRAP SBC #YPOSMAX+1 ;USE WRAPPED DISTANCE EOR #$FF ; CLC ;CARRY IS CLEAR FROM SBC (IE, BORROW) ADC #1 DYOK: CMP #14 ;FURTHEST COLLISION HAS DY OF ONLY 14 BCS NOCOL ; IF >= 15, NO COLLISION. STA TEMP+1 * AT THIS POINT, WE MUST DO CLOSER INSPECTION, SINCE THE OBJECTS ARE CLOSE. CLC ;COMPUTE MANHATTAN DISTANCE (DX+DY) ADC TEMP STA TEMP+2 LDA STATUS,X ;TEMP+5 <- TYPE OF OBJECT X AND #$0F STA TEMP+5 LDA STATUS,Y ;TEMP+6 <- TYPE OF OBJECT Y AND #$0F STA TEMP+6 STY TEMP+9 ;SAVE Y, WE NEED AN INDEX REGISTER! TAY LDA OBJDIAG,Y ;GET WIDTH OF SECOND OBJECT LDY TEMP+5 ADC OBJDIAG,Y ;ADD IN WIDTH OF FIRST OBJECT CMP TEMP+2 ;COMPARE WITH MANHATTAN DISTANCE BMI NOCOL1 ;TOO FAR AWAY, NO COLLISION. LDA OBJWID,Y ;DO MORE PRECISE XTENT CHECKING LDY TEMP+6 CLC ADC OBJWID,Y CMP TEMP BCC NOCOL1 ;TOO FAR TO THE SIDE: NO COLLISION LDA OBJHEIT,Y ;DO MORE PRECISE YTENT CHECKING LDY TEMP+5 CLC ADC OBJHEIT,Y CMP TEMP+1 BCS YESCOL ;WE HAVE A COLLISION. NOCOL1: LDY TEMP+9 ;RESTORE Y NOCOL: CPY #40 ;DECREMENT INDICES WITHOUT RESTORING BEQ COLSETX ; IF WE ARE DOING SPECIAL CHECKING BCS DECY1 CPX #40 BEQ RESTORE1 CPX #37 BCC RESTORE1 BCS DECX1 ;(UNCONDITIONAL) COLSETX: CPX #37 ;SET X AND Y TO LOOP OVER SHIP'S PARTS BCC RESTORE1 BCS COLSETY ;(UNCONDITIONAL) COLSETY: LDY #43 ;RESET Y FOR NEXT ROUND DECX1: DEX JMP COLCHK DECY1: DEY JMP COLCHK * COME HERE IN THE EVENT OF A POSSIBLE COLLISION. YESCOL: ;COMPUTE LOWEST P2 BULLET OR SHIP FOR THIS MODE. IN TEAM MODES ;WE SHARE BULLETS. RESULT IS LEFT IN TEMP FOR LATER. LDA #32 ;ASSUME 30 AND 31 ARE NOT P2'S LDY MODE CPY #1 BMI NOTEAMSC ;NOT TEAMPLAY, DON'T SPLIT BULLETS LDA #30 ;30 AND 31 ARE P2'S NOTEAMSC: STA TEMP LDY TEMP+9 ;RESTORE Y * PERFORM ACTIONS DEPENDENT UPON THE SPECIAL CASE OBJECTS CPX #32 BEQ COLP2X ;FIRST OBJECT IS P2 SHIP CPX #24 BEQ COLP1X ;FIRST OBJECT IS P1 SHIP CPY #24 BEQ COLP1Y ;SECOND OBJECT IS P1 SHIP LDX TEMP+3 ;RESTORE X AND Y LDY TEMP+4 JSR DOCOL ;DO THE COLLISION JMP DECX ;AND THE NEXT ITERATION RESTORE1: JMP RESTORE ;AND CONTINUE COLP2X: LDA STATE+1 ;DON'T COLLIDE IF SHIP ISN'T OK BNE RESTORE1 LDA MODE ;IN COMPETITIVE, P1'S SHOTS KILL P2 CMP #2 BEQ COLP2XGO CPY #28 ; (P1'S SHOTS ARE 28 AND 29) BCS RESTORE1 ;OTHERWISE, IGNORE THEM COLP2XGO: LDX #39 ;POINT TO SHIP2'S PARTS JSR P2SETUP ;SET UP FOR SPECIAL P2 CHECKING CPY #24 ;IS IT SHIP1 VS SHIP2? BNE COLNOP1Y ;NOPE LDA MODE CMP #2 ;IN COMPETITIVE PLAY, DON'T BOUNCE, BEQ COLP1Y ; COLLIDE! LDA STATE ;IF SHIP NOT OK, DON'T COLLIDE BNE RESTORE1 JMP RUBBERS ;LET'S GO BOUNCY BOUNCY... COLP1Y: LDA STATE ;DON'T COLLIDE IF SHIP ISN'T OK BNE RESTORE1 CPX #28 ;ANYTHING LESS THAN 28 IS HARMFUL BCC COLP1YGO ;IN TEAM PLAY, IGNORE THE COLLISION: THEY ARE FRIENDS LDA MODE CMP #1 BEQ RESTORE1 CPX TEMP ;CHECK AGAINST P2'S BULLETS. BCC RESTORE1 ; IF < TEMP, IT IS SAFE ;NOT SAFE: CHECK SHIP'S PARTS COLP1YGO: LDY #43 ;POINT TO SHIP1'S PARTS COLP1GO: JSR P1SETUP ;SET THEM UP COLNOP1Y: JMP COLCHK ;AND CONTINUE COLP1X: LDA STATE ;DON'T COLLIDE IF SHIP ISN'T OK BNE RESTORE1 LDX #43 ;POINT TO SHIP1'S PARTS BNE COLP1GO ;CONTINUE AS ABOVE (UNCONDITIONAL) * P1SETUP: SET UP STATUS ENTRIES FOR THE PARTS OF THE SHIP TO CHECK P1SETUP: STX TEMP+8 LDA SHIPDIR ;GENERATE SHIP DIRECTION INDEX LSR LSR LSR LSR TAX LDA SHNOSEX,X CLC ADC XPOSH+24 STA COLXPOSH+40 LDA SHNOSEY,X ADC YPOSH+24 STA COLYPOSH+40 LDA SHRTAILX,X ; CLC ADC XPOSH+24 STA COLXPOSH+41 LDA SHRTAILY,X ADC YPOSH+24 STA COLYPOSH+41 LDA SHLTAILX,X ; CLC ADC XPOSH+24 STA COLXPOSH+42 LDA SHLTAILY,X ADC YPOSH+24 STA COLYPOSH+42 LDA COLXPOSH+24 STA COLXPOSH+43 LDA COLYPOSH+24 STA COLYPOSH+43 LDX TEMP+8 RTS * P2SETUP: SET UP STATUS ENTRIES FOR THE PARTS OF THE SHIP TO CHECK P2SETUP: STX TEMP+8 LDA SHIPDIR+1 ;GENERATE SHIP DIRECTION INDEX LSR LSR LSR LSR TAX LDA SHNOSEX,X CLC ADC XPOSH+32 STA COLXPOSH+36 LDA SHNOSEY,X ADC YPOSH+32 STA COLYPOSH+36 LDA SHRTAILX,X ; CLC ADC XPOSH+32 STA COLXPOSH+37 LDA SHRTAILY,X ADC YPOSH+32 STA COLYPOSH+37 LDA SHLTAILX,X ; CLC ADC XPOSH+32 STA COLXPOSH+38 LDA SHLTAILY,X ADC YPOSH+32 STA COLYPOSH+38 LDA COLXPOSH+32 STA COLXPOSH+39 LDA COLYPOSH+32 STA COLYPOSH+39 LDX TEMP+8 RTS * DOCOL1: PERFORM CERTAIN COMMON ACTIONS ON AN OBJECT EXPLODING. * ON ENTRANCE, X IS THE INDEX OF OBJECT COLLIDING. ON EXIT, TEMP+6 HAS THE * 'TYPE NYBBLE'. OH, AND BY THE WAY, X AND Y ARE TRASHED. DOCOL1: STX TEMP+8 ;SAVE X LDA STATUS,X ORA #$80 ;TAG THIS OBJECT AS "EXPLODING" STA STATUS,X AND #$0F ;COMPUTE OBJECT TYPE (AGAIN) STA TEMP+6 ;STORE IT CMP #6 BCS NOEXPSND ;OBJECTS >= 6 MAKE NO EXPLOSION SOUNDS CMP #4 BCS COLUFO ;UFO COLLIDING: HANDLE IT CMP #3 BCS COLSHIP ;SHIP COLLIDING: HANDLE IT ; CLC ;CARRY IS CLEAR ADC #$0A ;ADD OFFSET OF ROCK TUNES PHA ;THIS IS 'ROCKSND' LDA #$0A ; (KILL OFF ANY CURRENT ROCK SOUNDS) JSR KILLTUNE LDA #$0B JSR KILLTUNE LDA #$0C JSR KILLTUNE PLA CONT: JSR DOTUNE LDX TEMP+8 ;RESTORE X, TRASHED BY DOTUNE NOEXPSND: LDY TEMP+6 ;GET TYPE NYBBLE LDA ELBOUND,Y ;SET UP EXPLOSION ANIMATION STA ACYC,X RTS COLUFO: TAX SEC SBC #2 ;COMPUTE INDEX INTO LVLINC JSR INCLVL ;MAKE IT HARDER NOW CPX #4 ;ONLY MR. BILL CHANGES ACCURACY BNE ZNOBILAC LDA UFOACC CMP #4 ;DON'T GO BELOW 3 BCC ZNOBILAC DEC UFOACC ;TIGHTEN UP MR. BILL'S ACCURACY ZNOBILAC: TXA ;DO TUNES: CANCEL THEME AND PLAY EXPL. CLC ADC #2 ;EXPLOSION = TYPE + 2 PHA ;PUSH IT FOR LATER ADC #2 ;THEME = TYPE + 4 JSR KILLTUNE PLA ;PULL EXPLOSION SOUND BPL CONT ;BPL = JMP COLSHIP: LDA TEMP+8 ;FIGURE OUT WHICH SHIP DIED LDX #0 ;DEFAULT TO SHIP 1 CMP #32 ;FIGURE OUT WHICH SHIP DIED BNE NOP2DIE INX ;INCREMENT TO SHIP 2 NOP2DIE: LDA #DEATH ;INDUCE A FATAL DEATH STA STATE,X LDA #DIET+$28 ;AT TIMER 'DIE TIME' + $28 STA TIMER,X LDA #$05 ;SHIP EXPLOSION = 05 BPL CONT ;BPL = JMP * WE HAVE A COLLISION, FOLKS! DO WHAT NEEDS TO BE DONE (EXPLODING, SCORING) DOCOL: ;DEBUGGING PATCH ; LDA #$0A ;USE SMALL ROCK EXPLOSION SOUND ; JSR DOTUNE ; LDX TEMP+3 ; LDY TEMP+4 ; RTS * FIRST DO TUNES AND EXPLOSION ANIMATIONS ; LDX TEMP+3 JSR DOCOL1 LDA TEMP+6 ;TRANSFER TYPE NYBBLE STA TEMP+5 ; TO PROPER PLACE LDX TEMP+4 JSR DOCOL1 * NOW DO SCORING LDX TEMP+6 ;SCORE ONE OBJECT LDY TEMP+3 JSR DOSCOR LDX TEMP+5 ;SCORE OTHER OBJECT LDY TEMP+4 JSR DOSCOR CPY #24 ;SEE IF WE HAVE ANY EXPLODING ROCKS BCC ROCKEXPL LDX TEMP+3 ;RESTORE X RTS * SCORE OBJECT OF TYPE X ACCORDINGLY AS IT WERE SHOT BY OBJECT Y * I.E., IF Y CONTAINS INDEX OF PLAYER ONE'S SHOT, SCORE A HIT ON AN 'X' TO * PLAYER ONE. DOSCOR: CPY TEMP ;CHECK P2'S BULLETS OR SHIP BPL SCORP2 ;CREDIT OBJECT TO P2'S SCORE CPY #28 ;CHECK P1'S BULLETS BPL SCORPL ;CREDIT OBJECT TO CURRENT PLAYER CPY #24 ;CHECK P1'S SHIP BNE SCORERTS ;NONE OF THE ABOVE: RTS CPX #3 ;IS IT A SHIP THAT #24 IS HITTING? BNE SCORPL ;NO. JUST SCORE IT. LDA #17 ;SOUR THE GOATMILK STA GOATMILK ; RTS ;RTS IF YOU DON'T WANT TO SCORE THESE. SCORPL: LDA PLAYER ;SCORE IT TO THE CURRENT PLAYER SCORIT: STA SCORER ;MARK THE SCORER JSR ADDPOINT ;RACK 'EM UP SCORERTS: RTS SCORP2: LDA #1 ;SCORE FOR P2 REGARDLESS OF PLAYER BPL SCORIT ;BPL = JMP * HANDLE EXPLODING (="SPLITTING") ROCKS. ROCKEXPL: LDA STATUS,Y ;CHECK THE EXPLODING ROCK SEC SBC #$91 ;WIDTH IS LO NYBBLE. IF =1, THEN SMALL BMI SPLITRTS ;THIS IS CLEVER. B2-91=21, ETC... STA TEMP+7 ;SAVE IT FOR NEWROCK TO USE... LDA #$50 ;RESET 5.2 SEC UFO COUNTER STA RTIMER ;CREATE ONE, TWO, OR THREE NEW ROCKS, BASED ON DIFF. LDA DIFF ;UNLESS AT A WHIPPY LEVEL THEN ONE BEQ ONEROCK CMP #3 ;AT EXPERT LEVEL, MAYBE > 2 ROCKS! BCC TWOROCKS LDA RANDPTR0 ;USE PTR AS RANDOM (NEWRAND SCREWS Y) AND #$03 BNE TWOROCKS JSR NEWROCK ;CREATE EACH NEW ROCK IF POSSIBLE; TWOROCKS: JSR NEWROCK ;NEWROCK RETURNS "EMPTY HANDED" IF NOT. ONEROCK: JSR NEWROCK LDX TEMP+3 ;RESTORE X, TRASHED IN NEWROCK SPLITRTS: RTS NEWROCK: LDX #23 ;FIND A FREE ROCK SLOT ROCKLOOP: LDA STATUS,X CMP #$FF BEQ THISROCK DEX BPL ROCKLOOP RTS THISROCK: LDA XPOSL,Y ;INITIALIZE NEW ROCK (X) FROM OLD (Y) STA XPOSL,X LDA XPOSH,Y STA XPOSH,X LDA YPOSL,Y STA YPOSL,X LDA YPOSH,Y STA YPOSH,X LDA COLXPOSH,Y ;THESE AREN'T QUITE RIGHT, BUT CLOSE. STA COLXPOSH,X LDA COLYPOSH,Y STA COLYPOSH,X LDA PALS,Y ;ADJUST WIDTH TO SMALLER ROCK SIZE CLC ADC #1 STA PALS,X LDA TEMP+7 ;GIVE IT THE PROPER ROCK TYPE STATUS STA STATUS,X AND #$0F ;SET FIRST ANIMATION FRAME TAY LDA ROCKCYC,Y STA ACYC,X JSR RANDVEL ;SET UP RANDOM VELOCITIES. LDX PLAYER INC ROCKTOT,X ;THERE IS NOW ONE MORE ROCK! LDY TEMP+4 ;RESTORE Y, TRASHED ABOVE RTS ;RUBBER SHIPS RUBBERS: LDA RUBFLAG ;HAVE WE BEEN HERE BEFORE? BPL ZNORUB ;YUP. DON'T BOUNCE BACK LDA XVELH+24 CMP #$80 ;SIGNED 16 BIT DIVIDE BY TWO ROR PHA LDA XVELL+24 ROR PHA LDA XVELH+32 CMP #$80 ROR STA XVELH+24 LDA XVELL+32 ROR STA XVELL+24 PLA STA XVELL+32 PLA STA XVELH+32 LDA YVELH+24 CMP #$80 ROR PHA LDA YVELL+24 ROR PHA LDA YVELH+32 CMP #$80 ROR STA YVELH+24 LDA YVELL+32 ROR STA YVELL+24 PLA STA YVELL+32 PLA STA YVELH+32 ZNORUB: LDA #1 ;PREVENT A SECOND BOUNCE STA RUBFLAG JMP RESTORE * TABLE OF STARTING VALUES FOR 'Y' IN COLLIDE LOOP: ESSENTIALLY, THESE ARE * THE HIGHEST NUMBERED OBJECTS WE MUST COMPARE TO FOR A GIVEN X. * THESE ARE OFFSET BY 24, SINCE THE LOWEST X WE CHECK IS 24 (SHIP1) * COLTAB: .DC.B 23,24,24,24,25,25,25,25,29 * WIDTH TABLES FOR COLLISION PURPOSES OBJWID: .DC.B 2,4,5,3,2,4,1,1;X-EXTENTS (XTENTS) OBJHEIT: .DC.B 3,6,8,6,2,3,1,1;Y-EXTENTS (YTENTS) OBJDIAG: .DC.B 3,6,9,6,2,3,2,1;DIAGONALS * OFFSET (INTO THE STAMP) OF SHARP POINTS OF THE SHIP SHLTAILX: .DC.B 1,0,0,1,1,2,3,4,5,5,6,5,5,4,3,2 SHLTAILY: .DC.B 5,7,9,11,12,13,14,14,13,11,9,7,6,5,4,4 SHRTAILX: .DC.B 5,4,3,2,1,1,0,0,1,2,3,4,5,5,6,5 SHRTAILY: .DC.B 5,4,4,5,6,7,9,11,13,14,14,13,12,11,9,7