--============_-1359804286==_============ Content-Type: text/plain; name="Freeway.A65"; charset="us-ascii" Content-Disposition: attachment; filename="Freeway.A65" LST OFF TR ON * * Equates for all the WRITE only registers for the * Atari 2600 * VSYNC = $00 ;Vertical sync set-clear VBLANK = $01 ;Vertical blank set-clear WSYNC = $02 ;Wait for leading edge of horizontal blank RSYNC = $03 ;Reset horizontal sync counter NUSIZ0 = $04 ;Number size Player Missile 0 NUSIZ1 = $05 ;Number size Player Missile 1 COLUP0 = $06 ;Color-lum Player 0 COLUP1 = $07 ;Color-lum Player 1 COLUPF = $08 ;Color-lum playfield COLUBK = $09 ;Color-lum background CTRLPF = $0A ;Ctrol playfield ball size & collisions REFP0 = $0B ;Reflect player #0 REFP1 = $0C ;Reflect player #1 PF0 = $0D ;First 4 bits of playfield PF1 = $0E ;Middle 8 bits of playfield PF2 = $0F ;Last 8 bits of playfield RESP0 = $10 ;Reset player #0 X coord RESP1 = $11 ;Reset player #1 X coord RESM0 = $12 ;Reset missile #0 X coord RESM1 = $13 ;Reset missile #1 X coord RESBL = $14 ;Reset ball AUDC0 = $15 ;Audio control 0 AUDC1 = $16 ;Audio control 1 AUDF0 = $17 ;Audio frequency 0 AUDF1 = $18 ;Audio frequency 1 AUDV0 = $19 ;Audio volume 0 AUDV1 = $1A ;Audio volume 1 GRP0 = $1B ;Pixel data player #0 GRP1 = $1C ;Pixel data player #1 ENABL = $1F ;Ball enable register HMP0 = $20 ;Horizontal motion Player #0 HMP1 = $21 ;Horizontal motion Player #1 HMBL = $24 ;Horizontal motion Ball HMOVE = $2A ;Add horizontal motion to registers HMCLR = $2B ;Clear horizontal motion registers CXCLR = $2C ;Clear collision registers * * Collision registers * CXM0P = $00 ;Read collision M0-P1/M0-P0 CXM1P = $01 ;Read collision M1-P0/M1-P1 CXP0FB = $02 ;Read collision P0-PF/P0-BL CXP1FB = $03 ;Read collision P1-PF/P1-BL CXM0FB = $04 ;Read collision M0-PF/M0-BL CXM1FB = $05 ;Read collision M1-PF/M1-BL CXBLPF = $06 ;Read collision BL-PF/----- CXPPMM = $07 ;Read collision P0-P1/M0-M1 INPT0 = $08 ;Paddle #0 INPT1 = $09 ;Paddle #1 INPT2 = $0A ;Paddle #2 INPT3 = $0B ;Paddle #3 INPT4 = $0C ;Misc input #0 INPT5 = $0D ;Misc input #1 * * Memory equates * DUM $80 GameNumber DS 1 ;Current game variation being played (0-7) FrameCounter DS 1 ;Inc'd every video frame Polynomial DS 1 ;Random number polynomial SelectDelay DS 1 ;Timer for select autorepeat Player1Joy DS 1 ;Player 1's joystick value Player2Joy DS 1 ;Player 2's joystick value SaverColor DS 1 ;$00 for normal, Random for screen saver LumMask DS 1 ;$FF for color, $0F for B&W and $07 for saver ZColorScore DS 1 ;Score color and Activision color ZColorChicken DS 1 ;Chicken color ZColorLine DS 1 ;Street line color ZColorPavement DS 1 ;Pavement color ZColorBlack DS 1 ;Tire/black ZColorSidewalk DS 1 ;Sidewalk color ChickenYs DS 2 ;Y coords for Player 1 and 2's chickens Chick0LaneCollide DS 1 ;Lane where chicken #1 hit a car Chick1LaneCollide DS 1 ;Lane where chicken #2 hit a car ChickP0Collide DS 1 ;Collision flag from VCS ChickP1Collide DS 1 ;Collision flag from VCS CurrentCarColor DS 1 ;Current color of the car shape LaneNumber DS 1 ;Lane currently being drawn CarXDirection DS 1 ;1 or -1 for car X motion ZCarPatterns DS 10 ;Current size and multiples of cars CarMotionTimers DS 10 ;Timer before car is moved CarMotions DS 10 ;Motion values for each car LChickPtrs16 DS 12 ;Pointers for each chick per 16 scan lines RChickPtrs16 DS 12 ;Pointers for each chick per 16 scan lines ZCarColors DS 10 ;Colors for all the cars * I assume there are 7 pointers in a row here CarShapePtr DS 2 ;Pointer to current car shape ChickLeftShapePtr DS 2 ;Pointer to chicken shape #0 ChickRightShapePtr DS 2 ;Pointer to chicken shape #1 * The order of the 4 pointers below is important! ScoreShape01Ptr DS 2 ;Pointer to left score first digit ScoreShape11Ptr DS 2 ;Pointer to right score first digit ScoreShape02Ptr DS 2 ;Pointer to left score second digit ScoreShape12Ptr DS 2 ;Pointer to right score second digit * * All variables from here to $FF are zero'd out every new game * SaverTimer DS 1 ;If > 127 then in screen saver mode GameTimer DS 1 ;If 0 then game is in progress Scores DS 2 ;Player scores (BCD) FrameCounterHi DS 1 ;Inc'd every 256 frames ChickenSounds DS 2 ;True if a chicken was hit (Timer for clucking) CarXCoords DS 10 ;Array of automobile X coords TempX1 DS 1 ;Temp X coord * * These temp variables cannot be used in a subroutine, they are in the stack * TempHonkDistance DS 1 ;Distance from a car to a chicken TempCarSpeed DS 1 ;Speed of the car TempCarX DS 1 ;X coord of the car TempCarPattern DS 1 ;Car speed pattern TempCarFacing DS 1 ;Facing of the car TempCarXWrap DS 1 ;Wrapped X coord of a car TempClosestDist DS 1 ;Closest car's distance TempClosestFacing DS 1 ;Closest car's facing DEND * * 6532 equates * RIOTDATAA = $0280 RIOTDATAB = $0282 RIOTTIMER = $0284 RIOTSETTIMER1 = $0294 RIOTSETTIMER8 = $0295 RIOTSETTIMER64 = $0296 RIOTSETTIMER1024 = $0297 ORG $F000 * * Freeway for the Atari 2600 VCS * * Copyright 1981 Activision Inc. * By David Crane * ResetEntry SEI ;Disable IRQ's CLD ;Binary mode LDX #0 ;Kill all of zero page WarmStart LDA #0 ;Zap memory ]A STA $00,X TXS ;Place here to set stack to #$FF INX ;at end of loop BNE ]A JSR ResetGameVars ;Clear out the game variables * * Main game loop MainLoop LDX #6-1 ]A LDA BaseColors,X ;Get the colors EOR SaverColor ;Screen saver AND LumMask ;B&W mask STA ZColorScore,X ;Save the adjusted colors CPX #4 BGE :NoHardW STA COLUP0,X ;Set the hardware default :NoHardW DEX BPL ]A STX Chick0LaneCollide ;X = FF STX Chick1LaneCollide ;Chicken's didn't hit a car STA WSYNC ;Wait a line STA RESBL ;Reset the ball LDA #$22 ;Set the horizontal ball motion (+2) STA HMBL STA ENABL ;Enable the ball (02) LDA #40 ;X position for score digit #1 INX ;X = 00 STX COLUPF ;Black playfield (Ball) JSR SetMotionRegsX ;Position digit #1 LDA #48 ;X position for score digit #2 STA CTRLPF ;($30) No Reflect,No Score,Low Priority,8 pixel wide ball INX ;X = 01 JSR SetMotionRegsX ;Position digit #2 LDA #$04 ;Two copies wide STA NUSIZ0 ;Two pairs of score digits STA NUSIZ1 LDA ZColorScore ;Color of the score LDY GameTimer ;Game in progress BNE :NormalScore LDY FrameCounterHi ;Frames/256 CPY #32 BLT :NoTimeInc ;Not time yet? INC GameTimer ;Inc the game over timer :NoTimeInc CPY #30 BLT :NormalScore LDA FrameCounter ;Use the frame counter for a color AND LumMask ;Fixed lum :NormalScore STA COLUP0 ;Save the score color STA COLUP1 * * Now display the player's scores at the top of the screen * ]A LDA RIOTTIMER ;Wait for the proper scan line BNE ]A * * 1 line of playfield * STA WSYNC ;Wait for sync STA HMOVE ;Add horizontal motion to position sprites STA VBLANK ;Enable video STA CXCLR ;Clear collision registers * * Display the scores (8 scan lines) * 61 cycle loop * LDY #7 ;7 lines to display ]A STA WSYNC ;3 Wait for sync STA HMCLR ;3 Clear horizontal motion LDA (ScoreShape01Ptr),Y ;5 Get the shape for player #0's score STA GRP0 ;3 LDA (ScoreShape02Ptr),Y ;5 STA GRP1 ;3 JSR Waste18 ;18 Wait for it to be displayed LDA (ScoreShape11Ptr),Y ;5 Get the shape for player #1's score STA GRP0 ;3 LDA (ScoreShape12Ptr),Y ;5 STA GRP1 ;3 DEY ;2 BPL ]A ;3 * * Waste 1 scan line to prepare to draw the sidewalk * LDA #$40 ;Move the chickens 4 pixels to the left STA HMP1 STA WSYNC ;Wait a line STA HMOVE ;Add horizontal motion INY ;Y = 0 STY GRP0 ;Clear the player shapes (Don't draw score) STY GRP1 LDA #$08 STA REFP0 ;Reverse player #0 LDA LChickPtrs16+11 ;Get the topmost chicken shape STA ChickLeftShapePtr LDA RChickPtrs16+11 STA ChickRightShapePtr LDY #8+1 ;8 scan lines of sidewalk and 1 of border STA HMCLR ;Clear horizontal motion registers * * Draw the first black line between the score and the sidewalk * STA WSYNC STA HMOVE ;Add horizontal motion LDA ZColorBlack ;Draw the black line STA COLUBK LDA ZColorChicken ;Set the chicken's color STA COLUP1 * * Just draw lines with the chicken on the sidewalk and 1 black line * ]A STA WSYNC LDA ZColorSidewalk ;Assume sidewalk color CPY #1 ;Bottom line? BNE :NotLine LDA ZColorBlack ;Draw a black line :NotLine STA COLUBK ;Set the background color LDA (ChickLeftShapePtr),Y ;First chicken shape STA GRP1 JSR Waste14 LDA (ChickRightShapePtr),Y STA GRP1 DEY BNE ]A * * Now I need 3 scan lines to position the car * STA WSYNC ;Sync video STA HMOVE ;Add horizontal motion (Draw black line) LDA ZColorPavement ;Force pavement STA COLUBK LDA #10-1 ;Init the lane count (10 lanes) STA LaneNumber LDA (ChickLeftShapePtr),Y ;First chicken (Y=0) STA GRP1 NOP ;10 cycles NOP NOP NOP NOP LDA (ChickRightShapePtr),Y ;Second chicken STA GRP1 LDX LaneNumber ;X = (10-1) LDA LChickPtrs16+1,X ;Get the chick shape for the first lane STA ChickLeftShapePtr LDA RChickPtrs16+1,X STA ChickRightShapePtr * * I will draw a lane of the highway * DrawALane LDY #15 ;15 lines to draw LDA #0 ;A = 0 STA WSYNC * * Line 1 is just pavement and setup for car position * STA HMOVE ;(0) 3 Add horizontal motion STA PF1 ;(3) 3 Clear out the highway pattern (A=0) STA PF2 ;(6) 3 STA COLUPF ;(9) 3 Playfield is black LDA (ChickLeftShapePtr),Y ;(12) 5 First shape byte STA GRP1 ;(17) 3 LDA ZCarColors,X ;(20) 4 Get the color of the car STA CurrentCarColor ;(24) 3 LDA CarMotions,X ;(27) 4 Get the DEX count for car course position AND #$0F ;(31) 2 Only use lower 4 bits STA TempX1 ;(33) 3 LDA (ChickRightShapePtr),Y ;(36) 5 Get player #2's shape DEY ;(41) 2 Y = 14 STA GRP1 ;(43) 3 Draw it LDA ZCarPatterns,X ;(46) 4 Get the width of the shape AND #7 ;(50) 2 STA NUSIZ0 ;(52) 3 CMP #5 ;(55) 2 Double wide? BNE :ItsACar ;(57) 2/3 LDA #TruckFrame-4 ;(59) 2 Draw a truck BNE :GotCarShp ;(61) 3 :ItsACar LDA #CarFrame-4 ;(60) 2 Draw a car NOP ;(62) 2 :GotCarShp STA CarShapePtr ;(64) 3 Save the car's shape LDA (ChickLeftShapePtr),Y ;(67) 5 STA GRP1 ;(72) 3 * * Line 2 is pavement and actually setting the car position * LDA ZCarPatterns,X ;(75) 4 BMI :CarOnRight ;(79) 2/3 (Car is on the right side) * * Set the car position for the left side * LDX TempX1 ;(81) 3 CPX #3 ;(84) 2 LDA (ChickRightShapePtr),Y ;(86) 5 Get the right chicken shape * * IMPORTANT!!!! This routine MUST start at cycle 91!!! * ]A DEX ;(91) 2 BPL ]A ;2/3 STA RESP0 ;3 Position the car on the left side BGE :DelayOk ;2/3 Too close to the left JSR Waste12 ;Waste 12 cycles :DelayOk DEY ;2 Y = 13 STA GRP1 ;3 Right chicken LDX LaneNumber ;3 LDA CarMotions,X ;4 Fine horizonal position for car STA HMP0 ;3 LDA ZColorBlack ;3 Black color for tires JMP :BeginLaneLoop ;3 * * Draw the right chicken first, then position the car on the right * IMPORTANT!!!! This routine MUST start at cycle 82!!! * :CarOnRight NOP ;(82) 2 4 cycles NOP ;(84) 2 STA CXCLR ;(86) 3 Clear collisions LDX LaneNumber ;(89) 3 LDA CarMotions,X ;(92) 4 Get the fine motion STA HMP0 ;(96) 3 Set now LDA TempX1 ;(99) 3 Get the course cycle count SEC ;(102) 2 SBC #30/5 ;(104) 2 Remove 30 cycles (121-91) TAX ;(106) 2 LDA (ChickRightShapePtr),Y ;(108) 5 Get the right shape DEY ;(113) 2 Y = 13 STA GRP1 ;(115) 3 Draw it LDA ZColorBlack ;(118) 3 Start with black tires * * IMPORTANT!!!! This routine MUST start at cycle 121!!! * ]A DEX ;(121) Course adjustment BPL ]A STA RESP0 ;Set the car on the right side * * Draw the car in the lane, I enter with Black in A * and then change to the proper color so I can draw the tires in black * and the rest of the car in the proper color * :BeginLaneLoop STA WSYNC ;Sync ]A STA HMOVE ;Add horizontal motion STA COLUP0 ;Save the car color (Or black for the tires) LDA (CarShapePtr),Y ;Get the car shape STA GRP0 ;Draw it LDA ChickP1Collide ;Did player #2 get hit by a car? (Previous line) ORA CXPPMM STA ChickP1Collide STA CXCLR ;Clear collisions LDA (ChickLeftShapePtr),Y ;Get the chicken shape STA GRP1 CPY #6 ;At the bottom of the car? LDA ChickP0Collide ;Check for car collision ORA CXPPMM STA ChickP0Collide STA CXCLR ;Clear collisions again! (For player #2) LDA (ChickRightShapePtr),Y ;Set player #2's chicken STA GRP1 BLT :FinishLane ;No more? (Fall through is only 2 cycles) DEY ;Count down STA |HMCLR ;4 Clear horizontal motion registers (4 cycles) LDA CurrentCarColor ;Get the car color EOR SaverColor ;Screen saver AND LumMask JMP ]A ;Loop * * Now, I finished drawing the car in the NORMAL color, * let's draw the bottom tires * :FinishLane LDA ZColorBlack ;Get black DEY ;Y = 4 STA WSYNC ;Sync STA HMOVE ;Add horizontal motion STA COLUP0 LDA (CarShapePtr),Y ;Draw the bottommost tires STA GRP0 LDA ChickP1Collide ;Check for Player #2's chicken death ORA CXPPMM STA ChickP1Collide STA CXCLR ;Clear collisions LDA (ChickLeftShapePtr),Y ;Right player STA GRP1 NOP ;2 LDA ChickP0Collide ;Save player 1's collision value (Final for lane) ORA CXPPMM STA ChickP0Collide STA CXCLR ;Clear collisions LDA (ChickRightShapePtr),Y ;Draw the right chicken STA GRP1 DEY ;Y = 3 * * Now, clear the car sprite and wrap up player 2's collision register * Draw only pavement * STA WSYNC ;Sync STA HMOVE ;Add horizontal motion LDA #0 ;Kill the car shape STA GRP0 LDA (ChickLeftShapePtr),Y ;Draw the left chicken STA GRP1 LDX LaneNumber ;Which lane am I in? BIT ChickP0Collide ;Did I hit? BPL :NoHitP0 STX Chick0LaneCollide ;Save the lane number of the collision :NoHitP0 LDA ChickP1Collide ;Get player #2 ORA CXPPMM ;Add the current hardware BPL :NoHitP1 ;Did I hit? STX Chick1LaneCollide ;Save the collision :NoHitP1 LDA (ChickRightShapePtr),Y ;Get the chicken shape STA GRP1 ;Draw it STA CXCLR ;Clear collisions DEY ;Y = 2 LDA LaneNumber ;Are we in the final lane? BEQ WrapUp ;Finish and draw sidewalk if so... * * I need to draw the center divider or the single white line * I will draw 3 lines, Either the lines will be drawn... * Pavement,White,Pavement or * Chicken,Pavement,Chicken * LDX ZColorPavement ;Get the pavement color CMP #5 ;Should I draw the center divider? BNE :DrawWhiteLane ;Draw the regular white lines LDX ZColorChicken ;Use the chicken's color for the lines :DrawWhiteLane STA WSYNC STA HMOVE ;Add horizontal motion LDA #$AA ;Draw the line patter STA PF0 ;Write the highway line pattern STA PF2 LSR ;Reverse bits A = $55 STA PF1 ;Middle bits STX COLUPF ;Save the color (Pavement or chicken) LDA (ChickLeftShapePtr),Y ;First chicken STA GRP1 DEC LaneNumber ;Next lane LDA (ChickRightShapePtr),Y STA GRP1 DEY ;Y = 1 * * Center line (Pavement or white) * STA WSYNC STA HMOVE ;Add horizontal motion CPX ZColorChicken ;Am I drawing the center divider? BNE :NotCenter3 LDA #0 ;I will also force the cars to face right STA REFP0 ;Don't reverse player #0 LDA ZColorPavement ;No center line JMP :Pavement :NotCenter3 LDA ZColorLine ;White line color :Pavement STA COLUPF ;Change the line color LDA (ChickLeftShapePtr),Y ;First chicken STA GRP1 JSR Waste12 ;Waste 12 cycles LDA (ChickRightShapePtr),Y ;Second chicken STA GRP1 DEY ;Y = 0 * * Final line (Chicken or pavement) * STA WSYNC STA HMOVE ;Add horizontal motion STX COLUPF LDA (ChickLeftShapePtr),Y STA GRP1 LDX LaneNumber ;Get the lane number LDA LChickPtrs16+1,X ;Set the chick shape pointers for the next lane STA ChickLeftShapePtr LDA RChickPtrs16+1,X STA TempX1 ;Can't use yet... NOP LDA (ChickRightShapePtr),Y ;Final right chicken shape STA GRP1 LDA TempX1 ;Grab from temp STA ChickRightShapePtr ;Now I can use it LDA #0 ;Clear the collision masks STA ChickP0Collide STA ChickP1Collide STA PF0 ;Clear out the left most highway pattern JMP DrawALane ;The other two are cleared at the beginning * * Now, draw the last lines of the chicken (Y == 2 on entry) * WrapUp STA WSYNC ;Sync STA HMOVE ;Add horizontal motion LDA (ChickLeftShapePtr),Y ;Get the left chicken STA GRP1 JSR Waste14 ;Waste 26 cycles JSR Waste12 LDA (ChickRightShapePtr),Y ;Get the right chicken STA GRP1 DEY ;Looped 3 times? BPL WrapUp ;All done? * * Now draw the sidewalk on the bottom of the screen * I must loop with Y == 15 to compensate for the Chicken pointers * LDY #9+6 ;9 scan lines to draw ]A LDA ZColorSidewalk ;Assume sidewalk color STA WSYNC ;Sync STA HMOVE ;Border CPY #9+6 ;Topmost black line? BNE :NotBlk2 LDA ZColorBlack ;Draw black :NotBlk2 STA COLUBK ;Save the color LDA LChickPtrs16 ;Bottommost chicken pointers STA ChickLeftShapePtr LDA RChickPtrs16 STA ChickRightShapePtr LDA (ChickLeftShapePtr),Y ;Draw the left chicken STA GRP1 LDA (ChickRightShapePtr),Y ;Draw the right chicken DEY STA GRP1 CPY #6 ;All done? BGE ]A * * Draw the activision logo * 1 line of black to prepare, then draw it * STA WSYNC ;Wait for video sync STA HMOVE LDA ZColorBlack ;Black line STA COLUBK LDX #0 ;Clear the shape register STX GRP1 STX HMCLR ;Clear horizontal motion registers INX ;X = 1 STX NUSIZ0 ;3 shapes, close together STX NUSIZ1 STA RESP0 ;Set the x coord (16) STA RESP1 ;X coord (25) (16+9) LDA #$10 ;Move player #1 one pixel to the left STA HMP1 LDA ZColorScore ;Score color STA COLUP0 STA COLUP1 * * Now draw the 8 lines * Note : All the activision shapes end with a shape of zero, * this way, I can assume the video display is pure black after the loop * is finished. * LDX #8-1 ;8 scan lines ]A STA WSYNC STA HMOVE ;3 Move the players (Only first time) LDA Activision1,X ;4 Draw the shape STA GRP0 ;3 LDA Activision2,X ;4 Draw in player #1 STA GRP1 ;3 NOP ;2 Waste 2 cycles LDA Activision4,X ;4 Preload the final 2 bytes TAY ;2 LDA Activision3,X ;4 STA GRP0 ;3 Store in shape (Cycle 32) STY GRP1 ;3 STA HMCLR ;3 Clear horizontal motion registers for future loops DEX ;2 All done? BPL ]A ;3 Loop * * The video display is now finished, let's time to the vertical blank * (It's black anyways) * LDA #26 ;Init the vertical blank timer STA RIOTSETTIMER64 * * Update a score value and process each player EVERY OTHER FRAME! * I do this since I want the chickens to move 30 pixels a second instead * of 60. Turbo chickens aren't much fun. * LDA FrameCounter ;Player 1 or 2 (Update 30 FPS) AND #1 TAX ;0/1 ASL TAY ;0/2 LDA Scores,X ;Get the score (BCD) AND #$F0 ;Mask it LSR ;$00,$08,$10,$18,$20 BNE :NotZero LDA #ChickFrameX ;Space character :NotZero STA ScoreShape01Ptr,Y ;Insert a space (Or digit) LDA Scores,X ;Get the BCD number again AND #$0F ;0-9 ASL ;Mul by 8 ASL ASL ;$00,$08,$10,$18,$20 STA ScoreShape02Ptr,Y ;Save the second digit LDY #0 ;Preload Y so the sound may be muted JSR ReadConsoleSwitches ;Get the console switches (Affect's A) BPL :SetVol2 ;Reset pressed? * * Process sound effects from the players * $8F = Got a point * $5C = Cluck! * LDA ChickenSounds,X ;Was the chicken moving down by impact? BEQ CheckSelect ;No sound effect AND #$40 ;$40-$5C? BEQ :GotPoint LDA #4 ;Div 2 / Pure tone STA AUDC0,X DEC ChickenSounds,X ;Count down the sound timer LDA ChickenSounds,X ;Get the value AND #$1F ;0-27 CMP #16 BLT :SetVol2 ;Volume is zero (Y=0) PHA AND #3 ;0-3 ADC #3-1 ;3-6 STA AUDF0,X ;Set the frequency PLA LDY #4 ;Medium volume :SetVol2 STY AUDV0,X ;Save the volume CMP #0 ;No more? BNE :DontKillSnd1 LDA #0 ;Shut off the sound STA ChickenSounds,X ;No more clucking... :DontKillSnd1 LDA RIOTDATAB ;Get the difficulty switches AND DiffSwitchTbl,X ;Hard? BEQ :EndSound ;Nope LDA #6 ;Reset the chicken to the bottom on impact STA ChickenYs,X :EndSound JMP SkipAmbientSnd * * I got a point! * :GotPoint LDA ChickenSounds,X ;Get the clucking timer STA AUDV0,X ;Set the volume using it LDA #12 ;Div 31 pure tone STA AUDC0,X TXA ;0/1 ADC #6 ;6/7 STA AUDF0,X DEC ChickenSounds,X ;Count down the sound timer LDA ChickenSounds,X ;Done? AND #$0F BNE JmpEndSnd LDA #0 ;Kill the sound STA ChickenSounds,X JmpEndSnd JMP SkipAmbientSnd ;End * * Check for game select and play a honking horn if so. * Play amibent sounds (Motors, honking) * CheckSelect LDA SelectDelay ;Is the select switch held down? CMP #8 ;Check the time LDA #2 ;Choose a horn BGE :HonkHorn ;Honk! LDA GameTimer ;Game in progress? BEQ :DoAmbient LDA #0 ;Don't play any sound if the game is over STA AUDV0,X ;Clear the volume (Kill voice) BEQ JmpEndSnd ;JMP :DoAmbient LDA ChickenSounds ;Any sound effect present? ORA ChickenSounds+1 BNE :TryMotor LDA Polynomial ;Get the random number value EOR #$40 CMP #$E0 BLT :TryMotor ;No sound now LDA Polynomial EOR FrameCounter ;Real random AND #$3F BEQ :TryMotor LDA Polynomial ;Get the value * * Honk a horn * :HonkHorn AND #3 ;1 of 4 horns to play ORA #4 ;Pitch 4-7 STA AUDF0 SEC SBC #1 ;Pitch 3-6 STA AUDF1 LDA #1 ;4 bit polynomial STA AUDC0 STA AUDC1 STA AUDV0 ;Set volume to minimum STA AUDV1 ;for both voices BNE JmpEndSnd ;JMP * * Play a car's motor if it's speed changes * :TryMotor LDA ChickenYs,X ;Get the Y coord LSR ;Div by 16 for the lane LSR LSR LSR TAY CPY #10 BLT :LaneNumOk LDY #9 ;Force bottom lane :LaneNumOk LDA #0 ;Going right? CPY #5 BLT :FacingRight LDA #1 ;Going left.. :FacingRight STA TempCarFacing ;0-1 LDA ZCarPatterns,Y ;Get the car pattern for the lane STA TempCarPattern ;Save the pattern LSR LSR LSR LSR AND #7 ;Isolate the speed STA TempCarSpeed ;Save speed CMP #2 LDA #32 ;Can honk if 32 pixels away BLT :FastCar LDA #$FF ;Set the facing for a slow car STA TempCarFacing LDA #16 ;Honk if 16 pixels away :FastCar STA TempHonkDistance LDA #3 ;5 bit poly -> 4 bit poly STA AUDC0,X LDA CarXCoords,Y ;Get the X coord STA TempCarX LDA #127 ;Maximum distance STA TempClosestDist LDA TempCarFacing ;0,1,-1 STA TempClosestFacing ;Assume this is the closest facing LDA TempCarPattern ;Get width in pixels of car AND #7 ASL ASL ORA #3 ;Round up to end of table TAY ;Index ]A LDA TempCarFacing ;Get the facing (0,1,-1) STA TempX1 CLC LDA CarGroupXs,Y ;Get the base X ADC TempCarX ;Add to true X CMP #160 BLT :NoXWrap SBC #160 ;Wrap around :NoXWrap STA TempCarXWrap ;Save the X LDA TrueChickenXs,X ;Get the chicken SEC SBC TempCarXWrap ;Get the difference BGE :DiffPositive EOR #$FF ;Negate it INC TempX1 ;0,1,2 :DiffPositive CMP TempClosestDist ;Closer? BGE :NotCloser STA TempClosestDist ;Save the new distance LDA TempX1 ;Save the facing STA TempClosestFacing :NotCloser DEY TYA AND #3 ;All done? BNE ]A LDA TempClosestDist ;Will a car honk? CMP TempHonkDistance BLT :IllHonk LDA #15 ;5 bit poly div 6 STA AUDC0,X LDA #31 ;Very low pitch (1 Khz) STA AUDF0,X LDA #1 ;Minimum volume STA AUDV0,X JMP SkipAmbientSnd ;Done * * Honk the horn * :IllHonk DEC TempHonkDistance ;Dec the distance to the car 15,31 EOR TempHonkDistance ;Reverse volume based on distance LSR ;Lower for the VCS LSR STA AUDV0,X ;Set the volume LDY TempClosestFacing ;-1,0,1,2 INY ;0-3 LDA MotorPitchs,Y ;Get the pitch CLC ADC TempCarSpeed ;Add the car's speed STA AUDF0,X ;Set the frequency * * Blend the random number generator * SkipAmbientSnd LDA FrameCounter ;Only mix every 32 frames AND #$1F BNE :NoRandom LDA Polynomial ;Adjust the random number generator ASL ASL ASL EOR Polynomial ASL ROL Polynomial * * Move the cars in the upper 5 lanes * :NoRandom LDA GameTimer ;Game in progress (if == 0) BNE :WaitHere LDX #9 LDA #-1 ;Make cars move to the left STA CarXDirection ]A JSR MoveACar DEX CPX #5 BGE ]A * * Process VBlank here * :WaitHere LDA RIOTTIMER ;Wait until the timer says ok! BNE :WaitHere LDY #$82 ;Enable video blank flags STY WSYNC ;Sync to HBlank STY VBLANK ;Enable vertical blank and dump I0-I3 to ground STY VSYNC ;Enable vertical sync signal STY WSYNC ;Wait 3 scan lines STY WSYNC STY WSYNC STA VSYNC ;Disable vertical sync signal (A=0) * * Inc the frame counters and timers * INC FrameCounter ;Inc the frame counter BNE :NoRollSv ;255 frames? INC FrameCounterHi ;High byte of the frame counter INC SaverTimer ;Inc the screen saver timer BNE :NoRollSv ;Zero? SEC ;Keep the high byte set ROR SaverTimer ;= $80 :NoRollSv LDY #$FF ;Assume normal color LDA RIOTDATAB ;B&W set? AND #$08 BNE :Color LDY #$0F ;Force b&w :Color TYA ;Place in A LDY #0 ;Assume screen saver not active BIT SaverTimer ;Screen saver active? BPL :NoSaver8 AND #$F7 ;Halve the brightness LDY SaverTimer ;Get the timer value for the random colors :NoSaver8 STY SaverColor ;Save the random saver scrambler ASL SaverColor ;0,2,4 etc... STA LumMask ;$FF,$0F,$07 LDA #44 STA WSYNC ;Wait for scan line STA RIOTSETTIMER64 ;Set the timer for start of screen * * Move the cars in the lower 5 lanes * LDA GameTimer ;Game in progress (if == 0) BNE ReadJoysticks LDX #4 LDA #1 ;Make cars move to the right STA CarXDirection ]A JSR MoveACar DEX BPL ]A * * Read the joysticks * ReadJoysticks LDA RIOTDATAA ;Read the joystick TAY AND #$0F STA Player2Joy ;Save player 2's joystick TYA LSR LSR LSR LSR STA Player1Joy ;Save player 1's joystick INY BEQ :NoJoy ;No joystick pressed LDA #0 ;Joystick is pressed STA SaverTimer :NoJoy LDA Polynomial ;Make sure the polynomial is non-zero! BNE :DoConsole INC Polynomial BNE :NewSel :DoConsole JSR ReadConsoleSwitches ;Read the console BMI :ChkSelect ;Reset pressed? LDX #SaverTimer ;Yep, reset the game JMP WarmStart :ChkSelect LDY #0 ;Was select pressed? (Init Y) BCS :SaveSelDelay ;Nope (Clear select delay) LDA SelectDelay ;Select the next game BEQ :NotHeld DEC SelectDelay BPL :NotSelTime :NotHeld INC GameNumber ;Inc the game selected :NewSel JSR ResetGameVars LDA GameNumber ;Make sure the game number is 0-7 AND #7 STA GameNumber STA SaverTimer ORA #$A0 ;Space / Digit TAY INY STY Scores ;$A1-$A8 Space/1-8 LDA #$AA ;Space/space STA Scores+1 LDY #30 ;Game over! STY GameTimer :SaveSelDelay STY SelectDelay ;30/60 delay (1/2 second or 0) :NotSelTime LDA GameTimer ;Game in progress? (if == 0) BEQ MoveTheChickens JMP MainLoop ;Loop * * Move both player's either up or down. * Add score if you reached the top * MoveTheChickens LDX #2-1 ]A LDA ChickenSounds,X ;Override? BEQ :Normal AND #$10 ;Force down... BNE :ForceDown BEQ :NotDown ;JMP :Normal LDA Player1Joy,X ;Pressing up? LSR BCS :NotUp ;Nope INC ChickenYs,X ;Move 1 pixel up LDY ChickenYs,X ;At the top? CPY #178 BLT :NotUp ;Nope SED ;BCD LDA Scores,X ;Add 1 to the score ADC #1-1 STA Scores,X CLD ;HEX LDA #$8F ;Start the sound effect for a point STA ChickenSounds,X BNE :ForceBottom ;JMP :NotUp LSR ;See if going down BCS :NotDown :ForceDown DEC ChickenYs,X ;Move down 1 LDA ChickenYs,X CMP #6 ;At the bottom BGE :NotDown :ForceBottom LDA #6 ;Set to the bottom STA ChickenYs,X :NotDown LDA ChickenSounds,X ;Am I playing a clucking sound? AND #$1F CMP #$17 BGE :Next LDA Chick0LaneCollide,X ;Am I hitting a car? BMI :Next LDA #92 ;Reset the sound STA ChickenSounds,X :Next DEX ;Next chicken... BPL ]A * * Get the pointers to the chickens' shapes * LDX #0 ;Player #1 JSR CalcChickShapePtr ;Get the pointer STA LChickPtrs16,Y ;Save the pointer CPY #11 ;Topmost? BEQ :NoChick4 CLC ADC #16 STA LChickPtrs16+1,Y :NoChick4 INX JSR CalcChickShapePtr STA RChickPtrs16,Y CPY #11 BEQ AlterCarSpeeds CLC ADC #16 STA RChickPtrs16+1,Y * * Check if I need to speed up or slow down the cars * AlterCarSpeeds LDA FrameCounter ;Time? AND #$70 BNE :JmpMain LDA GameNumber ;Easy game? AND #4 BEQ :JmpMain LDA FrameCounter ;Get the frame count AND #$0F ;Update 1 lane per frame TAX CPX #10 ;Only 10 lanes BGE :JmpMain LDA ZCarPatterns,X ;Get the speed of this lane LSR LSR LSR LSR AND #7 ;Isolate the speed TAY ;Save in Y LDA FrameCounter ;Get the random number EOR Polynomial LSR ;Check low bit (1 = speed up) BCC :NotFaster DEY ;Speed up the car BPL :NotFaster LDY #0 ;No faster than zero :NotFaster LSR ;Check bit #1 (1 = slow down) BCC :GotSpeed INY ;Slow down a bit CPY #6 BLT :GotSpeed LDY #5 ;Slowest speed :GotSpeed TYA ASL ;Put back the speed value ASL ASL ASL STA TempX1 ;Save in temp LDA ZCarPatterns,X ;Get the pattern AND #$8F ;Mask speed ORA TempX1 ;Blend new speed STA ZCarPatterns,X ;Save the pattern :JmpMain JMP MainLoop * * Reset the game variables * ResetGameVars LDA FrameCounter ;Reset the frame counter AND #1 ;But allow updating of the chickens STA FrameCounter LDX #2-1 ;2 players ]A LDA #6 ;Move to the bottom STA ChickenYs,X LDA #0 ;Reset the volume of the audio chip STA AUDV0,X DEX BPL ]A LDX #14-1 LDA #>FontPage ]A STA CarShapePtr,X ;Init the high byte for video pointers DEX DEX BPL ]A LDX #10-1 ;10 lanes ]A LDA #1 ;Allow motion in 2 frames STA CarMotionTimers,X LDA CarColors,X ;Copy the car colors STA ZCarColors,X CLC LDA GameNumber ;Get the traffic pattern AND #3 TAY TXA ADC Mul10Tbl1,Y ;Mul 0-3 by 10 TAY LDA CarPatterns,Y ;Save the pattern STA ZCarPatterns,X LDA #$60 ;Horizontal motion (+6 pixels) STA CarMotions,X LDA #ChickFrameX ;No chickens are drawn STA LChickPtrs16,X ;Zap all the tables STA LChickPtrs16+4,X STA RChickPtrs16+2,X DEX BPL ]A RTS * * Given a requested X coord in A, * return in A and Y and Horizonal offset and the cycle delay * CalcXRegs CLC ADC #46 TAY AND #$F ;Mask the 4 bit offset STA TempX1 ;Save temp TYA ;Get value again LSR ;Isolate the upper 4 bits LSR LSR LSR TAY ;Save as a WSYNC Delay CLC ADC TempX1 ;Mod 15 CMP #15 BLT :NoExcess SBC #15 ;Remove one step INY ;5 more cycles :NoExcess EOR #7 ;Negate horizontal offset ASL ;Move to upper 4 bits (Hardware) Waste18 ASL ;2 Call to waste 18 cycles ASL ;2 Waste14 ASL ;2 Call to waste 14 cycles Waste12 RTS ;6 Call to waste 12 cycles * * Set the horizontal motion registers * SetMotionRegsX JSR CalcXRegs ;Calculate the values STA HMP0,X ;Save the horizontal motion register STA WSYNC ;Sync to video ]A DEY ;Wait for cycle delay (5 cycles per) BPL ]A STA RESP0,X ;Hit the register for course adjustment RTS ;Exit * * Move a car either left or right * Note : I also will clear the chick shape values * MoveACar DEC CarMotionTimers,X ;Time to move it yet? BPL :NoMoveNow ;Nope LDA ZCarPatterns,X ;Get the car's speed LSR LSR LSR LSR AND #7 ;0-7 SEC SBC #1 ;-1-6 BPL :NotFast ;2 pixels a frame? LDA CarXCoords,X CLC ADC CarXDirection ;Add the car direction now STA CarXCoords,X LDA #0 ;Reset the timer :NotFast STA CarMotionTimers,X LDA CarXCoords,X CLC ADC CarXDirection ;Add the car direction CMP #200 ;Off the left side? BLT :NotHigh LDA #159 ;Wrap around :NotHigh CMP #160 ;Off the right side? BLT :InRange LDA #0 ;Wrap around :InRange STA CarXCoords,X :NoMoveNow LDA CarXCoords,X ;Get the X coord of a car JSR CalcXRegs STA TempX1 ;Save the horiz registers DEY ;-15 from the cycle count DEY DEY ASL ZCarPatterns,X ;Save the carry CPY #6 ;Set carry if on the right side (Clear on left) ROR ZCarPatterns,X ;Put the flag back TYA ORA TempX1 ;Get the horiz reg value STA CarMotions,X ;Save the motion registers LDA #ChickFrameX ;Assume all chickens are blank STA LChickPtrs16,X STA RChickPtrs16+2,X STA LChickPtrs16+4,X RTS * * Figure out which lane I shall draw the chicken * CalcChickShapePtr LDA ChickenYs,X ;Get the Y LSR ;/ by 16 to get the lane LSR LSR LSR TAY LDA ChickenYs,X ;Get the Y again AND #$F ;Mask STA TempX1 ;Save in a temp LDA ChickenSounds,X ;Chicken in normal mode? BEQ :Normal AND #$40 ;Not in pain... BEQ :Normal LDA ChickenYs,X ;Test bit #2 LSR LSR LSR LDA #ChickFrame3 ;If !(&4), use a sqwak frame BCC :GotFrame :Normal LDA TempX1 ;Get the scan line LSR LSR LSR LDA #ChickFrame1 ;Use for lines !(&4) BCC :GotFrame LDA #ChickFrame2 ;Use for lines &4 :GotFrame SEC SBC TempX1 ;Subtract from the scan line RTS * * Read the console switches from the 6532 RIOT chip * Bits are... * $01 Reset * $02 Select * $08 Color * $40 Difficulty Left * $80 Difficulty Right * Carry = Select, Negative = Reset * ReadConsoleSwitches LDA RIOTDATAB ;Read the switches LSR ;Shift the reset switch ROR ;Rotate reset to negative flag RTS ;and Carry has select HEX 250C250D ;Not used... (Filler) * * Activision logo bit map * Activision1 DB %00000000 DB %10101101 DB %10101001 DB %11101001 DB %10101001 DB %11101101 DB %01000001 DB %00001111 Activision2 DB %00000000 DB %01010000 DB %01011000 DB %01011100 DB %01010110 DB %01010011 DB %00010001 DB %11110000 Activision3 DB %00000000 DB %10111010 DB %10001010 DB %10111010 DB %10100010 DB %00111010 DB %10000000 DB %11111110 Activision4 DB %00000000 DB %11101001 DB %10101011 DB %10101111 DB %10101101 DB %11101001 DB %00000000 DB %00000000 * * Size and shapes for each traffic pattern for the 8 games * CarPatterns HEX 50403020101020304050 ;Game #1,#5 HEX 40312213041514233241 ;Game #2,#6 HEX 46362016050016203646 ;Game #3,#7 HEX 05152515050515251505 ;Game #4,#8 * * Base colors * BaseColors HEX 4A ;Score and Activision color HEX 1E ;Chicken / Median color HEX 0C ;Line color HEX 06 ;Pavement color HEX 00 ;Tire color HEX 08 ;Sidewalk color CarColors HEX 1AD8448824824A12DC42 ;Colors for each lane of cars * * Must not cross page boundaries!! * All shapes are upside down to allow decrementing by Y as both * a counter and a shape index * ERR *&$FF ;Must be page aligned (256) * * Numeric font * FontPage DB %00111100 DB %01100110 DB %01100110 DB %01100110 DB %01100110 DB %01100110 DB %01100110 DB %00111100 DB %00111100 DB %00011000 DB %00011000 DB %00011000 DB %00011000 DB %00011000 DB %00111000 DB %00011000 DB %01111110 DB %01100000 DB %01100000 DB %00111100 DB %00000110 DB %00000110 DB %01000110 DB %00111100 DB %00111100 DB %01000110 DB %00000110 DB %00001100 DB %00001100 DB %00000110 DB %01000110 DB %00111100 DB %00001100 DB %00001100 DB %00001100 DB %01111110 DB %01001100 DB %00101100 DB %00011100 DB %00001100 DB %01111100 DB %01000110 DB %00000110 DB %00000110 DB %01111100 DB %01100000 DB %01100000 DB %01111110 DB %00111100 DB %01100110 DB %01100110 DB %01100110 DB %01111100 DB %01100000 DB %01100010 DB %00111100 DB %00011000 DB %00011000 DB %00011000 DB %00011000 DB %00001100 DB %00000110 DB %01000010 DB %01111110 DB %00111100 DB %01100110 DB %01100110 DB %00111100 DB %00111100 DB %01100110 DB %01100110 DB %00111100 DB %00111100 DB %01000110 DB %00000110 DB %00111110 DB %01100110 DB %01100110 DB %01100110 DB %00111100 * * Chicken frame with no shape * ChickFrameX DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 ChickFrame1 DB %00110000 DB %01100000 DB %01111000 DB %11111000 DB %10111000 DB %00001100 DB %00000110 DB %00000100 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 ChickFrame2 DB %00011000 DB %00110000 DB %01111000 DB %11111000 DB %10111000 DB %00011000 DB %00001100 DB %00001000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 ChickFrame3 DB %01100000 DB %00110000 DB %01111000 DB %11111000 DB %10111000 DB %00111100 DB %00101000 DB %01000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 DB %00000000 CarFrame DB %01100110 DB %11111110 DB %11001111 DB %10110011 DB %10110011 DB %10110011 DB %10110011 DB %11001111 DB %11111110 DB %01100110 DB %00000000 TruckFrame DB %10000101 DB %11111111 DB %10000101 DB %11111101 DB %11111101 DB %11111101 DB %11111101 DB %10000101 DB %11111111 DB %10000101 Mul10Tbl1 DB 0,10,20,30 CarGroupXs DB 0,0,0,0 ;X coord for each car group DB 0,0,16,16 DB 0,0,0,32 DB 0,0,16,32 DB 0,0,0,64 DB 0,0,0,0 DB 0,0,32,64 TrueChickenXs DB 48,104 ;Chicken Xs MotorPitchs DB 16,16,17,16 ;Base pitches for motors DA ResetEntry ;Reset vector (MUST be at $F7FC) DiffSwitchTbl HEX 4080 ;Left,Right difficulty flags SAV Freeway