; Freeway for the Atari 2600 VCS ; ; Copyright 1981 Activision Inc. ; By David Crane ; ; Reverse-Engineered by Bill Heineman ; ; 18.10.2K Made compilable with DASM ; by Manuel Polik (101.36834@germanynet.de) ; 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 ; 6532 equates RIOTDATAA = $0280 RIOTDATAB = $0282 RIOTTIMER = $0284 RIOTSETTIMER1 = $0294 RIOTSETTIMER8 = $0295 RIOTSETTIMER64 = $0296 RIOTSETTIMER1024 = $0297 ; Memory equates GameNumber = $80 ;Current game variation being played (0-7) FrameCounter = $81 ;Inc'd every video frame Polynomial = $82 ;Random number polynomial SelectDelay = $83 ;Timer for select autorepeat Player1Joy = $84 ;Player 1's joystick value Player2Joy = $85 ;Player 2's joystick value SaverColor = $86 ;$00 for normal, Random for screen saver LumMask = $87 ;$FF for color, $0F for B&W and $07 for saver ZColorScore = $88 ;Score color and Activision color ZColorChicken = $89 ;Chicken color ZColorLine = $8A ;Street line color ZColorPavement = $8B ;Pavement color ZColorBlack = $8C ;Tire/black ZColorSidewalk = $8D ;Sidewalk color ChickenYs = $8E ;Y coords for Player 1 and 2's chickens / 2 Bytes Chick0LaneCollide = $90 ;Lane where chicken #1 hit a car Chick1LaneCollide = $91 ;Lane where chicken #2 hit a car ChickP0Collide = $92 ;Collision flag from VCS ChickP1Collide = $93 ;Collision flag from VCS CurrentCarColor = $94 ;Current color of the car shape LaneNumber = $95 ;Lane currently being drawn CarXDirection = $96 ;1 or -1 for car X motion ZCarPatterns = $97 ;Current size and multiples of cars / 10 Bytes CarMotionTimers = $A1 ;Timer before car is moved / 10 Bytes CarMotions = $AB ;Motion values for each car / 10 Bytes LChickPtrs16 = $B5 ;Pointers for each chick per 16 scan lines / 12 Bytes RChickPtrs16 = $C1 ;Pointers for each chick per 16 scan lines / 12 Bytes ZCarColors = $CD ;Colors for all the cars / 10 Bytes ; I assume there are 7 pointers in a row here CarShapePtr = $D7 ;Pointer to current car shape / 2 Bytes ChickLeftShapePtr = $D9 ;Pointer to chicken shape #0 / 2 Bytes ChickRightShapePtr = $DB ;Pointer to chicken shape #1 / 2 Bytes ; The order of the 4 pointers below is important! ScoreShape01Ptr = $DD ;Pointer to left score first digit / 2 Bytes ScoreShape11Ptr = $DF ;Pointer to right score first digit / 2 Bytes ScoreShape02Ptr = $E1 ;Pointer to left score second digit / 2 Bytes ScoreShape12Ptr = $E3 ;Pointer to right score second digit / 2 Bytes ; All variables from here to $FF are zero'd out every new game SaverTimer = $E5 ;If < 127 then in screen saver mode GameTimer = $E6 ;If 0 then game is in progress Scores = $E7 ;Player scores (BCD) / 2 Bytes FrameCounterHi = $E9 ;Inc'd every 256 frames ChickenSounds = $EA ;True if a chicken was hit (Timer for clucking) / 2 Bytes CarXCoords = $EC ;Array of automobile X coords / 10 Bytes TempX1 = $F6 ;Temp X coord ; These temp variables cannot be used in a subroutine, they are in the stack TempHonkDistance = $F7 ;Distance from a car to a chicken TempCarSpeed = $F8 ;Speed of the car TempCarX = $F9 ;X coord of the car TempCarPattern = $FA ;Car speed pattern TempCarFacing = $FB ;Facing of the car TempCarXWrap = $FC ;Wrapped X coord of a car TempClosestDist = $FD ;Closest car's distance TempClosestFacing = $FE ;Closest car's facing processor 6502 ORG $F000 SEI ;Disable IRQ's CLD ;Binary mode LDX #0 ;Kill all of zero page WarmStart LDA #0 ;Zap memory LOOPA STA $00,X TXS ;Place here to set stack to #$FF INX ;at end of loop BNE LOOPA JSR ResetGameVars ;Clear out the game variables ; Main game loop MainLoop LDX #6-1 LOOPB LDA BaseColors,X ;Get the colors EOR SaverColor ;Screen saver AND LumMask ;B&W mask STA ZColorScore,X ;Save the adjusted colors CPX #4 BCS NoHardW STA COLUP0,X ;Set the hardware default NoHardW DEX BPL LOOPB 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 BCC NoTimeInc ;Not time yet? INC GameTimer ;Inc the game over timer NoTimeInc CPY #30 BCC 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 ; LOOPC LDA RIOTTIMER ;Wait for the proper scan line BNE LOOPC ; ; 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 LOOPD 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 LOOPD ;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 ; LOOPE 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 LOOPE ; ; 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 #FontPage LOOPP STA CarShapePtr,X ;Init the high byte for video pointers DEX DEX BPL LOOPP LDX #10-1 ;10 lanes LOOPQ 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 #