Subject: [stella] Source (fwd) From: Glenn Saunders <krishna@xxxxxxxxxxxx> Date: Thu, 17 Apr 1997 21:09:46 -0700 (PDT) |
Here is the source file to Activision's Freeway, which was reconstructed by hand and extensively commented by "Burger" Bill Heineman. He assures me this is legal, and although I'm not going to go out of my way to distribute this, I feel that the subscribers of the mailing list should study it.
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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [stella] MultiSprite... game up, Lee Seitz | Thread | Re: [stella] looking for a 6502 boo, Dan Boris |
[stella] looking for a 6502 book, nall | Date | Re: [stella] looking for a 6502 boo, Dan Boris |
Month |