mirror of
https://github.com/peterdell/wudsn-ide.git
synced 2024-06-03 06:29:35 +00:00
1684 lines
39 KiB
NASM
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 |