wudsn-ide/com.wudsn.ide.ref/ASM/Atari2600/DASM/minidig/disassembly/freeway.asm
2018-12-30 16:52:33 +01:00

1684 lines
39 KiB
NASM

; 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 #<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!!!
;
LOOPF DEX ;(91) 2
BPL LOOPF ;2/3
STA RESP0 ;3 Position the car on the left side
BCS 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!!!
;
LOOPG DEX ;(121) Course adjustment
BPL LOOPG
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
LOOPH 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
BCC FinishLane ;No more? (Fall through is only 2 cycles)
DEY ;Count down
.byte $8D, $2B, $00 ; This is STA HMCLR, absolute adressed!
;4 Clear horizontal motion registers (4 cycles)
LDA CurrentCarColor ;Get the car color
EOR SaverColor ;Screen saver
AND LumMask
JMP LOOPH ;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
LOOPI 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?
BCS LOOPI
;
; 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
LOOPJ 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 LOOPJ ;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
BCC 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
BCS 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
BCC 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
BCC LaneNumOk
LDY #9 ;Force bottom lane
LaneNumOk LDA #0 ;Going right?
CPY #5
BCC 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
BCC 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
LOOPK 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
BCC NoXWrap
SBC #160 ;Wrap around
NoXWrap STA TempCarXWrap ;Save the X
LDA TrueChickenXs,X ;Get the chicken
SEC
SBC TempCarXWrap ;Get the difference
BCS DiffPositive
EOR #$FF ;Negate it
INC TempX1 ;0,1,2
DiffPositive CMP TempClosestDist ;Closer?
BCS NotCloser
STA TempClosestDist ;Save the new distance
LDA TempX1 ;Save the facing
STA TempClosestFacing
NotCloser DEY
TYA
AND #3 ;All done?
BNE LOOPK
LDA TempClosestDist ;Will a car honk?
CMP TempHonkDistance
BCC 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
LOOPL JSR MoveACar
DEX
CPX #5
BCS LOOPL
;
; 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
LOOPM JSR MoveACar
DEX
BPL LOOPM
;
; 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
LOOPN LDA ChickenSounds,X ;Override?
BEQ Normal1
AND #$10 ;Force down...
BNE ForceDown
BEQ NotDown ;JMP
Normal1 LDA Player1Joy,X ;Pressing up?
LSR
BCS NotUp ;Nope
INC ChickenYs,X ;Move 1 pixel up
LDY ChickenYs,X ;At the top?
CPY #178
BCC 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
BCS 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
BCS Next
LDA Chick0LaneCollide,X ;Am I hitting a car?
BMI Next
LDA #92 ;Reset the sound
STA ChickenSounds,X
Next DEX ;Next chicken...
BPL LOOPN
;
; 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
BCS 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
BCC 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
LOOPO LDA #6 ;Move to the bottom
STA ChickenYs,X
LDA #0 ;Reset the volume of the audio chip
STA AUDV0,X
DEX
BPL LOOPO
LDX #14-1
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 #<ChickFrameX ;No chickens are drawn
STA LChickPtrs16,X ;Zap all the tables
STA LChickPtrs16+4,X
STA RChickPtrs16+2,X
DEX
BPL LOOPQ
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
BCC 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
LOOPR DEY ;Wait for cycle delay (5 cycles per)
BPL LOOPR
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?
BCC NotHigh
LDA #159 ;Wrap around
NotHigh CMP #160 ;Off the right side?
BCC 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 Normal2
AND #$40 ;Not in pain...
BEQ Normal2
LDA ChickenYs,X ;Test bit #2
LSR
LSR
LSR
LDA #<ChickFrame3 ;If !(&4), use a sqwak frame
BCC GotFrame
Normal2 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 .byte %00000000
.byte %10101101
.byte %10101001
.byte %11101001
.byte %10101001
.byte %11101101
.byte %01000001
.byte %00001111
Activision2 .byte %00000000
.byte %01010000
.byte %01011000
.byte %01011100
.byte %01010110
.byte %01010011
.byte %00010001
.byte %11110000
Activision3 .byte %00000000
.byte %10111010
.byte %10001010
.byte %10111010
.byte %10100010
.byte %00111010
.byte %10000000
.byte %11111110
Activision4 .byte %00000000
.byte %11101001
.byte %10101011
.byte %10101111
.byte %10101101
.byte %11101001
.byte %00000000
.byte %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
;
ORG $F700
;
; Numeric font
;
FontPage .byte %00111100
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %00111100
.byte %00111100
.byte %00011000
.byte %00011000
.byte %00011000
.byte %00011000
.byte %00011000
.byte %00111000
.byte %00011000
.byte %01111110
.byte %01100000
.byte %01100000
.byte %00111100
.byte %00000110
.byte %00000110
.byte %01000110
.byte %00111100
.byte %00111100
.byte %01000110
.byte %00000110
.byte %00001100
.byte %00001100
.byte %00000110
.byte %01000110
.byte %00111100
.byte %00001100
.byte %00001100
.byte %00001100
.byte %01111110
.byte %01001100
.byte %00101100
.byte %00011100
.byte %00001100
.byte %01111100
.byte %01000110
.byte %00000110
.byte %00000110
.byte %01111100
.byte %01100000
.byte %01100000
.byte %01111110
.byte %00111100
.byte %01100110
.byte %01100110
.byte %01100110
.byte %01111100
.byte %01100000
.byte %01100010
.byte %00111100
.byte %00011000
.byte %00011000
.byte %00011000
.byte %00011000
.byte %00001100
.byte %00000110
.byte %01000010
.byte %01111110
.byte %00111100
.byte %01100110
.byte %01100110
.byte %00111100
.byte %00111100
.byte %01100110
.byte %01100110
.byte %00111100
.byte %00111100
.byte %01000110
.byte %00000110
.byte %00111110
.byte %01100110
.byte %01100110
.byte %01100110
.byte %00111100
;
; Chicken frame with no shape
;
ChickFrameX .byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
ChickFrame1 .byte %00110000
.byte %01100000
.byte %01111000
.byte %11111000
.byte %10111000
.byte %00001100
.byte %00000110
.byte %00000100
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
ChickFrame2 .byte %00011000
.byte %00110000
.byte %01111000
.byte %11111000
.byte %10111000
.byte %00011000
.byte %00001100
.byte %00001000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
ChickFrame3 .byte %01100000
.byte %00110000
.byte %01111000
.byte %11111000
.byte %10111000
.byte %00111100
.byte %00101000
.byte %01000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
CarFrame .byte %01100110
.byte %11111110
.byte %11001111
.byte %10110011
.byte %10110011
.byte %10110011
.byte %10110011
.byte %11001111
.byte %11111110
.byte %01100110
.byte %00000000
TruckFrame .byte %10000101
.byte %11111111
.byte %10000101
.byte %11111101
.byte %11111101
.byte %11111101
.byte %11111101
.byte %10000101
.byte %11111111
.byte %10000101
Mul10Tbl1 .byte 0,10,20,30
CarGroupXs .byte 0,0,0,0 ;X coord for each car group
.byte 0,0,16,16
.byte 0,0,0,32
.byte 0,0,16,32
.byte 0,0,0,64
.byte 0,0,0,0
.byte 0,0,32,64
TrueChickenXs .byte 48,104 ;Chicken Xs
MotorPitchs .byte 16,16,17,16 ;Base pitches for motors
ORG $F7FC
.word $f000 ; Reset
DiffSwitchTbl HEX 4080 ;Left,Right difficulty flags