|
Subject: [stella] Animating the Marbles From: Paul Slocum <paul-stella@xxxxxxxxxxxxxx> Date: Tue, 02 Jul 2002 22:17:37 -0500 |
;---------------------------------------------------------------------------
; Marble Craze by Paul Slocum
;---------------------------------------------------------------------------
;------------------------------
; Marble Craze bank 1
;------------------------------
; Includes:
;
; - Game Kernal
; - Variable Initialization
; - Game Loop Logic
;------------------------------
; LEVEL IDEAS
; Easy wall level (1st)
; Adventure
; Combat
; Easy Does It
; Dungeon
; Earthworld
; Fireworld
; Jump level
; Intersection Puzzler
; Get the Gems
; Grand Prix
; Grand Prix 2
; Waterworld
; Airworld
; Video Game Characters
; Up,Down,Right,Left Power Bars
; Slope level
; Slope level 2
; Key level
; Tightrope
; Rainbow Road
; Diagonal Paths
; Warps?
; Big open level
; Invisible Maze (catacombs)
; Power up extensions (get power up on each screen to extend path)
; MUSIC IDEAS
; Techno beat w/ arpeggiated music
; Slower song with 2 part arpeggiated melody
; Reverberated square song
processor 6502
include vcs.h
;--------------------------- TODO
;
; Switch to 32k
;
; GENERALIZE LEVEL READING
; SLOPE DATA STRUCTURE
; Check PF
; 2637
; 2666 = 47 bytes
; Load Screen
; 2778
; 2837 = 191 bytes
; Get Value = 20 bytes?
;
; Allow alternate songs
;
; Slow animation/allow turn off
;
; Look into modifying kernal for more animation
;
;--------------------------------
;------------------------ TODO LATER
;
; Fall off animation/fading
; Jump handling
;
; Slope handling
;
; Write C program to generate levels
;
; Stop, Up, Down etc power ups
;
; Warp power ups?
;
; (Lives bug)?
;
; Add friction?
;
;------------------------------------
;-------------------- SUGGESTIONS:
;
; Fat paddle center
;
; Friction
;
; Time about up indicator (sound or visual)
;
; Clean up respawn handling (restart sound? indicator?)
;
; Preview next screen
;
; Show ball rolling/falling off
;
; Track Ball control
;
; ------------------------------------
;---------------------------------------------------------------------------
; Constants
;---------------------------------------------------------------------------
LASTLEVEL equ 2
KERNAL_DELAY equ 8
TIMECOLOR equ $86
STATUSCOLOR equ $48
INTROCOLOR equ $8A
; Flags in level variable
ENDGAME equ %10000000
NEXTLEVEL equ %01000000
WINGAME equ %00100000
NUMBEROFLIVES equ 8
;---------------------------- status
;Status bits
FLASH equ 16
NOGAME equ 32
NOTIME equ 64
DONE equ 128
; Status
NORMAL equ 0
FALLOFF equ 1 + FLASH
RESET equ 2 + FLASH
SCREENLOAD equ 3
LOADREADY equ 6
FINISHED equ 4 + NOTIME + DONE
STARTUP equ 5 + FLASH + NOTIME
GETREADY equ 7 + FLASH + NOTIME
GAMEOVER equ 8 + NOTIME + FLASH + DONE + NOGAME
INACTIVE equ 9 + NOTIME + DONE + NOGAME
ENDLEVEL equ 10 + NOTIME ;+ SKIPLOGIC
TIMEUP equ 11 + FLASH
;--------------------------------------
;-------------------------- power ups
PWR20PTS equ %00000001
PWR50PTS equ %00000010
PWR100PTS equ %00000011
PWR5SEC equ %00000100
PWR10SEC equ %00000101
PWR20SEC equ %00000110
PWRWALLS equ %00000111
PWR1UP equ %00001000
PWRKEY equ %00001001
HPWR20PTS equ %00010000
HPWR50PTS equ %00100000
HPWR100PTS equ %00110000
HPWR5SEC equ %01000000
HPWR10SEC equ %01010000
HPWR20SEC equ %01100000
HPWRWALLS equ %01110000
HPWR1UP equ %10000000
HPWRKEY equ %10010000
;-------------------------------------
; Bankswitching
BANK1 equ $1FF6
BANK2 equ $1FF7
BANK3 equ $1FF8
BANK4 equ $1FF9
;---------------------------------------------------------------------------
; RAM Variables
;---------------------------------------------------------------------------
playField equ $80 ; 72 bytes (12 lines * 5) + 12 color bytes
; Variables for title screen only
option equ $80
paddle equ $81
debounce equ $84
bounce equ $85
titleBlank equ $86
startGame equ $87
;------------------------------------ 8 bytes
; 16 bit temp (overlaps with pfBuffer)
temp16L equ $C8
temp16H equ $C9
levelL equ $CA ; temp level pointer (during game logic)
levelH equ $CB
screenL equ $CC ; temp screen pointer (during game logic)
screenH equ $CD
temp equ $CE ; two more temps (for game logic)
temp2 equ $CF
;------
pfBuffer equ $C8 ; 8 bytes
;------------------------------------
pMarble equ $D0; 2 bytes
pMarble2 equ $D2; 2 bytes
pfColor equ $D4
frame equ $D5
p1x equ $D6
p2x equ $D7
p1y equ $D8
p2y equ $D9
p1xVel equ $DA
p2xVel equ $DB
p1yVel equ $DC
p2yVel equ $DD
pwr1x equ $DE
pwr2x equ $DF
pwr1y equ $E0
pwr2y equ $E1
padVal1 equ $E2
padVal3 equ $E3
padVal2 equ $E4
padVal4 equ $E5 ; 102 bytes total
level equ $E6
p1Screen equ $E7 ; bit 7 = WALLS flag, bit 6 & 5 = falling count
p2Screen equ $E8 ; ""
p1Status equ $E9
p2Status equ $EA
p1Counter equ $EB
p2Counter equ $EC
p1TimeL equ $ED
p2TimeL equ $EE
p1TimeH equ $EF
p2TimeH equ $F0
temp5 equ $F1
p1Lives equ $F2 ; High 4 bits store power up type
p2Lives equ $F3 ; High 4 bits store power up type
bkColor equ $F4
pwrArray1 equ $F5
pwrArray2 equ $F6
beat equ $F7
measure equ $F8
p1ScoreL equ $F9
p2ScoreL equ $FA
p1ScoreH equ $FB
p2ScoreH equ $FC
titleOptions equ $FD
; 126 bytes total (added titleOptions)
;-------------------------------------------------
; Temporary Game Logic Variables
;-------------------------------------------------
screen equ pMarble
player equ pMarble+1
status equ temp5
;--------------------------------------------------
; These two temp variables are in the stack area,
; and are only used during the kernal where
; the stack is not used.
temp3 equ $FE
temp4 equ $FF
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
org $1000
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
marbleData2
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0
byte #%00111100
byte #%01111110
byte #%01111110
byte #%11111111
byte #%11111111
byte #%11111111
byte #%11111111
byte #%11111111
byte #%11111111
byte #%01111110
byte #%01111110
byte #%00111100
align 256
marbleData3
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0
byte #%00111100
byte #%01111110
byte #%01111110
byte #%11111111
byte #%11111111
byte #%11111111
byte #%11111111
byte #%11111111
byte #%11111111
byte #%01111110
byte #%01111110
byte #%00111100 ; total = 99 bytes
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
byte 0,0,0,0,0,0,0,0
align 256
movement
byte #%01110001, #%01100001, #%01010001, #%01000001, #%00110001, #%00100001, #%00010001, #%00000001
byte #%11110001, #%11100001, #%11010001, #%11000001, #%10110001, #%10100001, #%10010001
byte #%01110010, #%01100010, #%01010010, #%01000010, #%00110010, #%00100010, #%00010010, #%00000010
byte #%11110010, #%11100010, #%11010010, #%11000010, #%10110010, #%10100010, #%10010010
byte #%01110011, #%01100011, #%01010011, #%01000011, #%00110011, #%00100011, #%00010011, #%00000011
byte #%11110011, #%11100011, #%11010011, #%11000011, #%10110011, #%10100011, #%10010011
byte #%01110100, #%01100100, #%01010100, #%01000100, #%00110100, #%00100100, #%00010100, #%00000100
byte #%11110100, #%11100100, #%11010100, #%11000100, #%10110100, #%10100100, #%10010100
byte #%01110101, #%01100101, #%01010101, #%01000101, #%00110101, #%00100101, #%00010101, #%00000101
byte #%11110101, #%11100101, #%11010101, #%11000101, #%10110101, #%10100101, #%10010101
byte #%01110110, #%01100110, #%01010110, #%01000110, #%00110110, #%00100110, #%00010110, #%00000110
byte #%11110110, #%11100110, #%11010110, #%11000110, #%10110110, #%10100110, #%10010110
byte #%01110111, #%01100111, #%01010111, #%01000111, #%00110111, #%00100111, #%00010111, #%00000111
byte #%11110111, #%11100111, #%11010111, #%11000111, #%10110111, #%10100111, #%10010111
byte #%01111000, #%01101000, #%01011000, #%01001000, #%00111000, #%00101000, #%00011000, #%00001000
byte #%11111000, #%11101000, #%11011000, #%11001000, #%10111000, #%10101000, #%10011000
byte #%01111001, #%01101001, #%01011001, #%01001001, #%00111001, #%00101001, #%00011001, #%00001001
byte #%11111001, #%11101001, #%11011001, #%11001001, #%10111001, #%10101001, #%10011001
byte #%01111010, #%01101010, #%01011010, #%01001010, #%00111010, #%00101010, #%00011010, #%00001010
byte #%11111010, #%11101010, #%11011010, #%11001010, #%10111010, #%10101010, #%10011010
paddleDecode
byte 0,0,0,0,0,0,1,1,1,1,1,1,1
byte 2,2,2,2,2,2,3,3,3,3,3,3,3
byte 4,4,4,4,4,4,5,5,5,5,5,5,5
byte 5,5,5,5,5,5,6,6,6,6,6,6,6
byte 6,6,6,6,6,6,7,7,7,7,7,7,7
byte 7,7,7,7,7,7,8,8,8,8,8,8,8
byte 8,8,8,8,8,8,8,8,8,8,8,8,8
byte 9,9,9,9,9,9,9,9,9,9,9,9,9
byte 10,10,10,10,10,10,10,10,10,10,10,10,10
byte 11,11,11,11,11,11,11,11,11,11,11,11,11
byte 12,12,12,12,12,12,12,12,12,12,12,12,12
byte 13,13,13,13,13,13,14,14,14,14,14,14,14
byte 15,15,15,15,15,15
;--------------------------------------------------------------------------
; Draw Screen
;--------------------------------------------------------------------------
drawScreen
;******************* Position P0/P1 for Score ***********************
sta HMCLR
; Set horizontal player positions for score
sta WSYNC
lda #%11000000
sta HMM0
lda #%11010000
sta HMM1
nop
lda (temp),x
lda (temp),x
lda temp
sta RESP0
lda temp
lda (temp),x
sta RESM0
lda temp
sta RESBL
nop
lda temp
sta RESP1
lda #%00100000
sta HMP0
lda #%00010000
sta HMBL
sta RESM1
sta WSYNC
sta HMOVE
lda #0
sta COLUBK
; ************** Score Draw Loop ********************
jmp callDrawScore
rtnCallDrawScore
; ************** Future Status and Timer (22 lines) ****************
lda #$0F
sta COLUPF
; ***************** Position Game Objects *********************
; DEBUG LIVES PROBLEM
; lda p1Lives
; sta PF2
; nop
nop
lda temp ; waste 3 cycles
sta temp
; Set sizes
lda #32 ;2
sta NUSIZ1 ;3
lda #0
sta NUSIZ0 ;3
; ***************** Position M0 (Divider Line) *********************
sta RESM0
sta PF1 ;3
; DEBUG LIVES PROBLEM
; lda #$0F
; sta PF2 ;3
sta HMCLR
lda #%01000000
sta HMM0
lda #6
sta temp4
; preLoad playfield color buffer
lda playField+71+6
sta pfBuffer+7
sta WSYNC
; Set player colors to white
lda #$0F ;2
sta COLUP0 ;3
sta COLUP1 ;3
;**************** Position P0 (Left Marble) ***************
lda p1x
lsr
tax
STA WSYNC
; Uses a lookup table to get the fine and course movement
lda movement,x
STA HMP0
AND #$0F
TAY
pPos1
DEY
BPL pPos1
STA RESP0
STA WSYNC
STA HMOVE
;**************** Position P1 (Right Marble) ***************
nop
nop
lda p2x
clc
adc #5
lsr
tax
; Uses a lookup table to get the fine and course movement
lda movement,x
STA HMP1
ldx #0
stx HMP0
stx HMM0
AND #$0F
TAY
pPos2
DEY
BPL pPos2
STA RESP1
; **************** Position M1 (Power Ups) *********************
; DBEUG LIVES PROBLEM
; lda #0
; sta PF2
STA WSYNC
STA HMOVE
; Power up flickers between player 1 and 2
; power up.
ldx pwr1x
lda frame
and #%00000001
beq powerUp1
lda pwr2x
clc
adc #77
tax
powerUp1
; Uses a lookup table to get the fine and course movement
lda movement,x
ldy #$0F
sta WSYNC
sta HMCLR
STA HMM1
AND #$0F
TAY
pPos3
DEY
BPL pPos3
STA RESM1
sta WSYNC
sta HMOVE
; The Ball is used to show the center divider in the score
; area, but M0 is used in the game area. Turn on M0 here.
lda #$FF
sta ENAM0
;******* Calculate line position of Vertical Paddle bar (Ball) *******
; temp16L stores the position
; of the vertical paddle indicator
ldx padVal1
lda frame
and #1
beq vertPad1
ldx padVal3
vertPad1
lda paddleDecode,x
sta temp3
lda #14
sec
sbc temp3
bcc padZero
clc
adc #1
jmp notPadZero
padZero
lda #1
notPadZero
sta temp3
ldx #$0
cmp #13
bmi ballOff
ldx #$FF
ballOff
stx ENABL
lda #%00010000
sta CTRLPF
sta WSYNC
; Draw top white line
lda #$0F
sta COLUBK
sta COLUBK
;*********** Position Ball (shows vertical Paddle position) ***********
; The ball graphics flickers between the left side and right side
; to indicate both player's vertical paddle positions
lda frame
and #1
bne right
ldx #4
ballL
dex
bne ballL
lda #%11010000
sta HMBL
nop
sta RESBL
jmp endBallPos
right
ldx #9
ballR
dex
bne ballR
lda #%10110000
sta HMBL
nop
sta RESBL
endBallPos
sta WSYNC
sta HMOVE
lda bkColor
sta COLUBK
lda #$FF
sta ENAM0
;--------------------------- set startup text to display (or not)
; 147 = no intro display
ldx #147
; Check for GAMEOVER/ENDLEVEL flags
lda level
and #%11100000
bne showDisplay
; Check for startup
lda p1Status
cmp #STARTUP
bne noStartup
showDisplay
ldx #148 ; 148 = show display
noStartup
stx temp5
;------------------------------------------
;***************** General Setup for Screen Drawing *******************
; Alternate the two kernals every frame
lda frame
and #%00000001
beq gotoScanLoop2
jmp gotoScanLoop3
gotoScanLoop2
; Playfield Reference
;
; pfBuffer
; 0 = PF0.1
; 1 = PF1.1
; 2 = PF2.1
; 3 = PF0.2
; 4 = PF1.2
; 5 = PF2.2
; 6 = PFCOLOR1
; 7 = PFCOLOR2
;
; 0 Hblank 22 PF0 28 PF1 38 PF2 48 PF0 56 PF1 66 PF2 76
; |----22----||--6--||---10----||---10----||--6--||---10----||---10----||
; 4---7 7-------0 0-------7 4---7 7-------0 0-------7
;==========================================================================
;
; KERNAL A
;
;==========================================================================
; ********* Draw Horizontal Paddle Indicator Left *********
lda pfColor
sta COLUPF
; Don't show paddles if INACTIVE
lda p1Status
cmp #INACTIVE
bne showBall
lda #255
sta temp3 ; location of ball line position
sta WSYNC
sta WSYNC
jmp endPaddleDisplay
showBall
; Get paddle value
ldx padVal2
lda paddleDecode,x
ldy #2
hLoopA
sta WSYNC
asl
asl
tax
; Use array to convert paddle value
; to playfield data
lda hPaddleDisplay,x
sta PF0
lda hPaddleDisplay+1,x
sta PF1
lda hPaddleDisplay+2,x
sta PF2
ldx #2
hPadA
dex
bne hPadA
; Turn off display
lda #0
sta PF0
sta PF1
sta PF2
; Get paddle value
ldx padVal2
lda paddleDecode,x
dey
bne hLoopA
endPaddleDisplay
sta WSYNC
; ***************** Prepare for Kernal Loop ****************
; Set starting Paddle counter values
lda #161
sta padVal1
sta padVal2
; Delay a bit before start of kernal loop
ldx #6
kBDelay
dex
bne kBDelay
; PreLoad the next right-playfield color
lda playField+71
sta pfBuffer+7
; preload temp2 value (x/2)
lda #6
sta temp4
; number of blocks
ldx #12 ;2 = 18
; Use Y to track the actual line
ldy #156 ;2 20
scanLoop2
; lda pfColor ; waste cycles
txs ; waste cycles
lda playField-1,x ;4 76
; 1A) setup
;---------------------------------------
sta PF0 ;3
sta pfBuffer ;3
lda (pMarble),y ;5*
sta GRP0 ;3
lda playField+11,x ;4
sta PF1 ;3
lda playField+23,x ;4
sta PF2 ;3
lda (pMarble2),y ;5*
sta GRP1 ;3
lda pfBuffer ;3
asl ;2
asl ;2
asl ;2
asl ;2
sta PF0 ;3 48
sta pfBuffer+3 ;3
lda playField+35,x ;4
sta PF1 ;3 55
lda playField+47,x ;4
sta PF2 ;3
; sta pfBuffer+5 ;3
dey ;2
lda (pMarble),y ;5*
; 2A) colors
;---------------------------------------
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
ldx temp4
lda playField+59,x ;4 66
sta COLUPF ;3
sta pfBuffer+6 ;3
tsx
lda playField+11,x ;4
sta PF1 ;3
lda playField+23,x ;4
sta PF2 ;3 34
lda (pMarble2),y ;4
sta GRP1 ;3
; nop
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda playField+35,x ;4
sta PF1 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
; lda pfBuffer+5 ;4
lda playField+47,x ;4
sta PF2 ;3
sta pfBuffer+5 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
; 3A) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda pfColor ;3
sta COLUPF ;3
lda playField+11,x ;4
sta PF1 ;3
sta pfBuffer+1 ;3
lda playField+23,x ;4
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3 39
; nop
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda playField+35,x ;4
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3 68
lda INPT0 ;3
bmi paddles1 ;2 or 3
sty padVal1 ;3
paddles1
lda pfBuffer ;3
sta PF0 ;3
sta WSYNC
; 4A) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
lda pfBuffer+1 ;4
sta PF1 ;3
lda playField+23,x ;4
sta PF2 ;3 29
sta pfBuffer+2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda playField+35,x ;4
sta PF1 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
; 5A) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda pfColor ;3
sta COLUPF ;3
lda pfBuffer+1 ;3
sta PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3 29
lda (pMarble2),y ;4
sta GRP1 ;3
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda playField+35,x ;4
sta PF1 ;3
sta pfBuffer+4
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
lda INPT1 ;3
bmi paddles2 ;2 or 3
sty padVal2 ;3
paddles2
sta WSYNC
; 6A) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
txs
ldx pfBuffer+1 ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
dey ;2
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
; 7A) more setup
;---------------------------------------
; lda pfBuffer ;3
; sta PF0 ;3
lda pfColor ;3
stx PF1 ;3
sta COLUPF ;3
; Draw the power up (using missile 1)
tsx ;2
txa ;2
ldx #ENABL ;2
txs ;2
cmp temp3
php
cmp pwr1y ;2
php ;3
tax
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
txs
nop
lda pfBuffer ;3
sta WSYNC
sta PF0 ;3
ldx pfBuffer+1 ;3
; 8A) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
dey ;2
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
; 9A) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda pfColor ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
cpy temp5 ; Check for message display
bne noMessageDisplay ; display message
jmp messageDisplay
noMessageDisplay
nop
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
lda INPT0 ;3
bmi paddles3 ;2 or 3
sty padVal1 ;3
paddles3
sta WSYNC
; 10A) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
stx PF1 ;3
lda #0
sta ENAM1
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
;nop
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
dey ;2
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
; 11A) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda pfColor ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
; This gets X out of the stack register,
; divides it by two and stores it for use
; with the color shading.
tsx
txa
lsr
sta temp4
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
lda INPT1 ;3
bmi paddles4 ;2 or 3
sty padVal2 ;3
paddles4
sta WSYNC
; 12A) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
lda pfBuffer+1 ;3
sta PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
; Grab that color pointer
ldx temp4
dey ;2
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
; 13A) setup for loop
;---------------------------------------
lda pfColor ;3
sta COLUPF ;3
lda pfBuffer+1 ;3
sta PF1 ;3
;nop
; Load the next right-playfield color
lda playField+65,x ;4 66
sta pfBuffer+7 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y
sta GRP1
tsx ;2
dey
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;4
sta PF1 ;3
lda pfBuffer+5 ;3
sta PF2 ;3
dex ;2
beq quitScanLoop2 ;2
jmp scanLoop2 ;3 must be 70
;******************* End Of Kernal A *******************
;==========================================================================
;
; KERNAL CLEAN UP
;
;==========================================================================
quitScanLoop2
sta WSYNC
; Draw the white line at the bottom
lda #$0F
sta COLUPF
lda #255
sta PF0
sta PF1
sta PF2
endOfScreen
; One more scanline
sta WSYNC
lda #0
sta COLUBK
sta PF0
sta ENABL
sta ENAM0
sta PF1
sta PF2
sta COLUP0
sta COLUP1
; restore stack
ldx #255
txs
jmp rtnDrawScreen
;==========================================================================
;
; messageDisplay
;
;--------------------------------------------------------------------------
; Displays text in middle of game screen
;==========================================================================
messageDisplay
; Finish current line (cuts in a 9th scanline in loop)
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda frame
and #1
beq padFrame01
lda INPT2
bmi paddles13 ;2 or 3
sty padVal3 ;3
jmp paddles13
padFrame01
lda INPT0 ;3
bmi paddles13 ;2 or 3
sty padVal1 ;3
paddles13
sta WSYNC
; call function to display text in bank 3
jmp callIntroMessage
rtnCallIntroMessage
; sta WSYNC
; Set player colors to white
lda #$0F ;2
sta COLUP0 ;3
sta COLUP1 ;3
; Now, have to reposition the player graphics
; since they were moved to display the text..
;**************** Position P0 (Left Marble) ***************
lda p1x
lsr
tax
STA WSYNC
; Uses a lookup table to get the fine and course movement
lda movement,x
STA HMP0
AND #$0F
TAY
pPos5
DEY
BPL pPos5
STA RESP0
STA WSYNC
STA HMOVE
;**************** Position P1 (Right Marble) ***************
nop
nop
lda p2x
clc
adc #5
lsr
tax
; Uses a lookup table to get the fine and course movement
lda movement,x
STA HMP1
ldx #0
stx HMP0
stx HMM0
AND #$0F
TAY
pPos6
DEY
BPL pPos6
STA RESP1
STA WSYNC
STA HMOVE
lda #255
sta PF1
sta PF2
; ***********************************************************
; Restore remaining registers and variables to resume
; drawing the screen...
; restore X and Y
ldx pfBuffer+1
txs
ldy pfBuffer+2
lda #32 ;2
sta NUSIZ1
lda #$00 ; set both players to normal
sta NUSIZ0
sta VDELP0
sta VDELP1
; sta WSYNC
tya
sec
sbc #31
tay
sta WSYNC
lda bkColor
sta COLUBK
lda #0
sta PF1
sta PF2
tsx
dex
dex
txa
lsr
sta temp4
tax
; Load the next right-playfield color
lda playField+65,x ;4 66
sta pfBuffer+7 ;3
lda playField+59,x ;4 66
sta pfBuffer+6
tsx
dex
dex
dex
txs
; Don't change number of cycles after this...
sta WSYNC
lda #0
sta PF1
sta PF2
lda #%00010000
sta CTRLPF
lda pfColor ;3
sta COLUPF ;3
lda #255
sta ENAM0
lda frame
and #1
beq reEnterLoop2
ldx #3
messageLoop1
dex
bne messageLoop1
nop
nop
tsx
jmp scanLoop3
reEnterLoop2
ldx #3
messageLoop2
dex
bne messageLoop2
lda temp
tsx
jmp scanLoop2
hPaddleDisplay ; 64 bytes
byte %00010000, %00000000, %00000000, %00000000
byte %00010000, %00000000, %00000000, %00000000
byte %00010000, %00000000, %00000000, %00000000
byte %00010000, %00000000, %00000000, %00000000
byte %01100000, %00000000, %00000000, %00000000
byte %10000000, %10000000, %00000000, %00000000
byte %00000000, %01100000, %00000000, %00000000
byte %00000000, %00011000, %00000000, %00000000
byte %00000000, %00000110, %00000000, %00000000
byte %00000000, %00000001, %00000001, %00000000
byte %00000000, %00000000, %00000110, %00000000
byte %00000000, %00000000, %00011000, %00000000
byte %00000000, %00000000, %01100000, %00000000
byte %00000000, %00000000, %10000000, %00000000
byte %00000000, %00000000, %10000000, %00000000
byte %00000000, %00000000, %10000000, %00000000
;==========================================================================
;
; KERNAL B
;
;==========================================================================
gotoScanLoop3
; ******* Draw horizontal Paddle Indicator Right *******
lda pfColor
sta COLUPF
lda p2Status
cmp #INACTIVE
bne showBall2
lda #255
sta temp3 ; location of ball line position
sta WSYNC
sta WSYNC
jmp endPaddleDisplay2
showBall2
ldy #2
hLoopB
sta WSYNC
; Get paddle value
ldx padVal4
lda paddleDecode,x
ldx #0
stx PF0
stx PF1
stx PF2
asl
asl
ldx #2
hPadB
dex
bne hPadB
tax
lda hPaddleDisplay,x
sta PF0
lda hPaddleDisplay+1,x
sta PF1
lda hPaddleDisplay+2,x
sta PF2
dey
bne hLoopB
endPaddleDisplay2
sta WSYNC
ldx #0
stx PF0
stx PF1
stx PF2
ldx #4
kADelay
dex
bne kADelay
; PreLoad the next right-playfield color
lda playField+71
sta pfBuffer+7
; PreLoad the next left-playfield color
lda playField+59+6;
; lda #$54
sta pfBuffer+6
; Set starting paddle counter values
lda #161
sta padVal3
sta padVal4
; number of blocks
ldx #12 ;2 = 18
; Use Y to track the actual line
ldy #156 ;2 20
scanLoop3
lda pfColor
; sta COLUPF
lda playField-1,x ;4 76
; 1B) setup
;---------------------------------------
sta PF0 ;3
sta pfBuffer ;3
lda (pMarble),y ;5*
sta GRP0 ;3
lda playField+11,x ;4
sta PF1 ;3
lda playField+23,x ;4
sta PF2 ;3
lda (pMarble2),y ;5*
sta GRP1 ;3
lda pfBuffer ;3
asl ;2
asl ;2
asl ;2
asl ;2
sta PF0 ;3 48
sta pfBuffer+3 ;3
lda playField+35,x ;4
sta PF1 ;3 55
lda playField+47,x ;4
sta PF2 ;3
sta pfBuffer+5 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3 68
; 2B) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda playField+11,x ;4
sta PF1 ;3
sta pfBuffer+1 ;3
lda playField+23,x ;4
sta PF2 ;3
sta pfBuffer+2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3 39
; nop
; nop
; nop
dey ;2
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda playField+35,x ;4
sta PF1 ;3
sta pfBuffer+4 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3 68
lda INPT2 ;3
bmi paddles5 ;2 or 3
sty padVal3 ;3
paddles5
lda pfBuffer ;3
sta PF0 ;3
; lda (pMarble),y ;5*
; sta GRP0 ;3
sta WSYNC
; 3B) colors
;---------------------------------------
lda pfBuffer+6 ;4 66
sta COLUPF ;3
; sta pfBuffer+6 ;3
nop
nop
lda pfBuffer+1 ;3
sta PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3 34
lda (pMarble2),y ;4
sta GRP1 ;3
nop
nop
nop
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
; 4B) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda pfColor ;3
sta COLUPF ;3
lda pfBuffer+1 ;3
sta PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3 29
lda (pMarble2),y ;4
sta GRP1 ;3
dey ;2
nop
nop
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
lda INPT3 ;3
bmi paddles6 ;2 or 3
sty padVal4 ;3
paddles6
sta WSYNC
; 5B) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
lda pfBuffer+1 ;4
sta PF1 ;3
lda playField+23,x ;4
sta PF2 ;3 29
sta pfBuffer+2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
lda pfBuffer+3 ;3
sta PF0 ;3 52
lda playField+35,x ;4
sta PF1 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
; 6B) more setup
;---------------------------------------
lda pfColor ;3
sta COLUPF ;3
lda pfBuffer+1 ;3
sta PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
; Draw the power up (using missile 1)
txa ;2
ldx #ENABL ;2
txs ;2
cmp temp3
php
cmp pwr2y ;2
php ;3
tax
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
nop
; 7B) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
txs
ldx pfBuffer+1 ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
dey ;2
nop
lda temp3 ; waste 3 cycles
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
; 8B) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda pfColor ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
nop ;8
nop
nop
nop
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
lda INPT2 ;3
bmi paddles7 ;2 or 3
sty padVal3 ;3
paddles7
sta WSYNC
; 9B) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
cpy temp5
bne noMessage2
jmp messageDisplay
noMessage2
dey ;2
lda #0 ;2
sta ENAM1 ;3
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
; 10B) paddles
;---------------------------------------
lda pfBuffer ;3
sta PF0 ;3
lda pfColor ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
lda temp3 ; waste 3 cycles
nop
nop
nop
dey ;2
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
lda INPT3 ;3
bmi paddles8 ;2 or 3
sty padVal4 ;3
paddles8
sta WSYNC
; 11B) colors
;---------------------------------------
lda pfBuffer+6 ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
lda temp3 ; waste 3 cycles
nop
nop
nop
nop
dey ;2
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+7 ;3
sta COLUPF ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
lda (pMarble),y ;4*
sta GRP0 ;3
lda pfBuffer ;3
sta PF0 ;3
; 12B) nothing
;---------------------------------------
lda pfColor ;3
sta COLUPF ;3
stx PF1 ;3
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y ;4
sta GRP1 ;3
; This gets X out of the stack register,
; divides it by two and stores it for use
; with the color shading.
tsx
txa
lsr
nop
tax
lda playField+59,x ;4 66
sta pfBuffer+6
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;3
sta PF1 ;3
lda pfBuffer+5 ;4
sta PF2 ;3
dey ;2
lda (pMarble),y ;4*
sta GRP0 ;3
nop
lda pfBuffer ;3
sta PF0 ;3
; 13B) setup for loop
;---------------------------------------
lda pfBuffer+1 ;3
sta PF1 ;3
; Load the next right-playfield color
lda playField+65,x ;4 66
sta pfBuffer+7 ;3
tsx
lda pfBuffer+2 ;3
sta PF2 ;3
lda (pMarble2),y
sta GRP1
nop
dey
lda pfBuffer+3 ;3
sta PF0 ;3
lda pfBuffer+4 ;4
sta PF1 ;3
lda pfBuffer+5 ;3
sta PF2 ;3
dex ;2
beq quitScanLoop3 ;2
jmp scanLoop3 ;3 must be 70
quitScanLoop3
sta WSYNC
lda #$0F
sta COLUPF
lda #255
sta PF0
sta PF1
sta PF2
jmp endOfScreen
; ******************* End of Kernal B ******************
;==========================================================================
;
; Start of Program
;
;--------------------------------------------------------------------------
; Clear memory, locate character graphics positions and such,
; initialize key memory values, start GameLoop.
;==========================================================================
Start
sei
cld
ldx #$FF
txs
lda #0
clear
sta 0,x
dex
bne clear
; Initialize Variables
jsr initVar
;==========================================================================
;
; GameLoop
;
;==========================================================================
GameLoop
jmp VSync ;start vertical retrace
rtnVSync
lda level
cmp #255
beq noGameSelect
lda SWCHB
and #2
beq resetGame
; ----------------------------------------
; Reset game when level = 254
lda level
cmp #254
bne noGameSelect
resetGame
lda #0
ldx #$78
clrVar
sta $80,x
dex
bpl clrVar
; Variables for title screen only
lda #0
; sta option
; sta paddle
; sta debounce
; sta bounce
; sta titleBlank
; sta startGame
; sta beat
; sta measure
sta AUDV0
sta AUDV1
lda #255
sta level
lda #50
sta titleBlank
sta debounce
noGameSelect
;---------------------------------------
; if the level is set to 255, the title
; screen is run.
lda level
cmp #255
bne gameMode
jmp callTitleScreen
gameMode
jmp VBlank ; spare time during screen blank
; uses jmp to avoid extra stack usage
VBlankReturn
sta CXCLR
inc frame
jmp drawScreen ; draw one screen
rtnDrawScreen
rtnCallTitleScreen
jmp overscan ; do overscan
rtnOverscan
jmp GameLoop ;back to top
;==========================================================================
;
; Initialize variables
;
;==========================================================================
initVar
; Set initialization flag.
; This stays set until the first frame is drawn.
lda #$0f ;set text color to white
sta COLUP0
sta COLUP1
lda #80
sta padVal1
sta padVal2
sta padVal3
sta padVal4
lda #128
sta p1xVel
sta p1yVel
sta p2xVel
sta p2yVel
lda #120
sta p2xVel
lda #STARTUP
sta p1Status
sta p2Status
lda #200
sta p1Counter
sta p2Counter
lda #$25
sta p2TimeH
sta p2TimeL
lda #3
sta p1Lives
; sta p2Lives
lda #255
sta level
lda #1
;sta p1Screen
;sta p2Screen
rts
;==========================================================================
;
; VSync
;
;-------------------------------------------------------------------------
; Game timers are elapsed during VSync
;==========================================================================
VSync
lda #2 ;bit 1 needs to be 1 to start retrace
sta VSYNC ;start retrace
sta WSYNC ;wait a few lines
;--------------- elapse game timer 1
lda p1Status ;3
and #NOTIME ;2
bne noDecTime1 ;2
; Handle Time
ldx #0 ;2
jsr elapseTime ;5
noDecTime1
;------------------------------------
lda #44 ;prepare timer to exit blank period (44)
sta WSYNC
sta TIM64T ;turn it on
;--------------- elapse game timer 2
lda p2Status ;3
and #NOTIME ;2
bne noDecTime2 ;2
; Handle Time
ldx #1 ;2
jsr elapseTime ;5
noDecTime2
;------------------------------------
lda #44 ;bit 1 needs to be 1 to start retrace
sta WSYNC ;wait one more
sta VSYNC ;done with retrace, write 0 to bit 1
jmp rtnVSync
;==========================================================================
;
; VBlank
;
;--------------------------------------------------------------------------
; Handle user input and display setup during the VBLANK period
;==========================================================================
VBlank
jmp callVBlank2 ; call VBlank routines in bank 2
VBlank2Return
; ------- Cycle headroom: remove these in release version
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
;---------------------------------------------------------
jmp VBlankReturn ; use jmps to avoid extra stack usage
;==========================================================================
;
; incScore
;
;--------------------------------------------------------------------------
; Increase BCD score by one
;
; preload
; X: player number (0 or 1)
;==========================================================================
incScore
sed
lda #1
clc
adc p1ScoreL,x
sta p1ScoreL,x
lda #0
adc p1ScoreH,x
sta p1ScoreH,x
cld
rts
;==========================================================================
;
; decTime
;
;--------------------------------------------------------------------------
; Elapse 1/10th of a second of time
;
; preload:
; X: number of player (0 or 1)
;==========================================================================
decTime
sed
; Make sure it's not already at zero
lda p1TimeL,x
bne contDecTime2
lda p1TimeH,x
bne contDecTime2
cld
rts
contDecTime2
lda p1TimeL,x
and #$0F
sec
sbc #1
and #$0F
sta p1TimeL,x
lda p1TimeH,x
sbc #0
sta p1TimeH,x
cld
rts ; other rts
;==========================================================================
;
; elapseTime
;
;--------------------------------------------------------------------------
; Elapse 1 frame of time
;
; Max cycles = about 52
;
; preload:
; X: number of player (0 or 1)
;==========================================================================
elapseTime
lda p1TimeL,x ;4
and #$F0 ;2
bne noDecTime ;2
sed ;2
lda p1TimeL,x ;4
and #$0F ;2
sec ;2
sbc #1 ;2
and #$0F ;2
sta p1TimeL,x ;4
lda p1TimeH,x ;4
sbc #0 ;2
; If carry is clear then time rolled...
bcc setTimeZero ;2
sta p1TimeH,x ;4
endElapseTime
cld ;2
lda p1TimeL,x ;4
ora #%01010000 ;2
sta p1TimeL,x ;4
rts ; other rts ;5
setTimeZero
cld
lda #0
sta p1TimeL,x
sta p1TimeH,x
rts
noDecTime
lda p1TimeL,x
sec
sbc #%00010000
sta p1TimeL,x
rts
;==========================================================================
;
; Overscan
;
;==========================================================================
overscan
sta WSYNC
lda #33 ; Use the timer to make sure overscan takes (34)
sta TIM64T ; 30 scan lines. 29 scan lines * 76 = 2204 / 64 = 34.4
; Skip OS processing if in Title Screen mode
lda level
cmp #255
bne doOS
jmp endOS
doOS
;-------------------------------------
; Invert vertical paddle values (1&3)
sec ;2 -- about 22 cycles max
lda frame ;3
and #1 ;2
bne invPad3 ;2*
lda #161 ;2
sbc padVal1 ;3
sta padVal1 ;3
jmp quitInv ;3
invPad3
lda #161 ;2
sbc padVal3 ;3
sta padVal3 ;3
quitInv
;--------------------------------------
;----------------------------------------
; Call game logic routines in bank 2
jmp callProcessGameLogic
rtnCallProcessGameLogic
;-----------------------------------------
; --------------- status state machine
ldx #0
jsr handleStatus
ldx #1
jsr handleStatus
;------------------------------------
;------------------- check for end of game
;jmp endGameCheck
lda level
and #%11100000
bne endGameCheck
lda p1Status
and #DONE
beq endGameCheck
lda p2Status
and #DONE
beq endGameCheck
lda #255
sta p1Counter
sta p2Counter
ldx #0
jsr endSetup
ldx #1
jsr endSetup
; default to NEXTLEVEL flag
ldx #NEXTLEVEL
lda p1Status
and #NOGAME
beq setFlag
lda p2Status
and #NOGAME
beq setFlag
ldx #ENDGAME
setFlag
txa
ora level
sta level
endGameCheck
;-------------------------------------
;----------------------------------handle game/level end flags
lda p1Counter
bne endFlags
lda level
and #ENDGAME
beq checkEndLevel
; signal to go back to title screen
lda #254
sta level
; Not doing this causes one extra
; point to be added to scores at end
lda #0
sta pwrArray1
sta pwrArray2
jmp endFlags
; check for next level flag
checkEndLevel
lda level
and #NEXTLEVEL
beq gameEnd2
ldx #0
jsr nextLevelSetup
ldx #1
jsr nextLevelSetup
; reset flags
inc level
lda #%00011111
and level
sta level
lda #0
sta pwrArray1
sta pwrArray2
; sta p1x
; sta p1y
; sta p2x
; sta p2y
; Check to see if the last level was completed
lda level
cmp #LASTLEVEL
bne notLastLevel
lda level
ora #WINGAME
sta level
ldx #0
lda p1Status
cmp #STARTUP
bne noP1Win
ldx #255
noP1Win
stx pwrArray1
ldx #0
lda p2Status
cmp #STARTUP
bne noP2Win
ldx #255
noP2Win
stx pwrArray2
lda #INACTIVE
sta p1Status
sta p2Status
notLastLevel
lda #250
sta p1Counter
sta p2Counter
sta pfColor
jmp endFlags
gameEnd2
; After finishing all levels, go to game over
lda level
and #WINGAME
beq endFlags
lda level
and #%00011111
ora #ENDGAME
sta level
lda #255
sta p1Counter
sta p2Counter
endFlags
;---------------------------------------------------
;----------------------- score end of level
lda p1Status
cmp #ENDLEVEL
bne notScore1
ldx #0
jsr scoreLevel
notScore1
lda p2Status
cmp #ENDLEVEL
bne notScore2
ldx #1
jsr scoreLevel
notScore2
;------------------------------------------
;------------------------ end of game bonus
lda level
and #WINGAME
beq noBonus2
lda pwrArray1
beq noBonus1
ldx #0
jsr incScore
noBonus1
lda pwrArray2
beq noBonus2
ldx #1
jsr incScore
noBonus2
;-----------------------------------------------
endOS
;---------------- OS cycle overhead: remove in release version
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
sta WSYNC
;---------------------------------------------------------
endOSLoop
lda INTIM ; We finished, but wait for timer
bne endOSLoop ; by looping till zero
sta WSYNC ; End last scanline
lda #$82
sta VBLANK
jmp rtnOverscan
;==========================================================================
;
; scoreLevel
;
;==========================================================================
scoreLevel
sed
; Decrease two 1/10th seconds
ldy #2
;--------------------------
scoreLoop
; Check that score isn't at zero
lda p1TimeL,x
bne point
lda p1TimeH,x
bne point
cld
endScoreLevel
rts
point
; dec time
lda p1TimeL,x
sec
sbc #1
and #$0F
sta p1TimeL,x
lda p1TimeH,x
sbc #0
sta p1TimeH,x
dey
bne scoreLoop
;---------------------------
lda p1ScoreL,x
clc
adc #1
sta p1ScoreL,x
lda p1ScoreH,x
adc #0
sta p1ScoreH,x
cld
rts ; other rts
;==========================================================================
;
; nextLevelSetup
;
;==========================================================================
nextLevelSetup
lda p1Status,x
cmp #ENDLEVEL
bne endLevelSetup
lda #STARTUP
sta p1Status,x
lda #0
sta p1Screen,x
lda #200
sta p1Counter,x
endLevelSetup
lda p1Status,x
cmp #GAMEOVER
bne doneLevelSetup
lda #INACTIVE
sta p1Status,x
doneLevelSetup
rts
;==========================================================================
;
; endSetup
;
;--------------------------------------------------------------------------
; Adjusts status at end of level/game
;==========================================================================
endSetup
lda p1Status,x
cmp #FINISHED
bne checkGameOver
lda #ENDLEVEL
sta p1Status,x
rts
checkGameOver
; cmp #GAMEOVER
; bne doneEndSetup
; lda #INACTIVE
; sta p1Status,x
doneEndSetup
rts ; multiple rts
;==========================================================================
;
; handleStatus
;
;--------------------------------------------------------------------------
; Status state machine
;
; Preload:
; X: Player number (0 or 1)
;==========================================================================
handleStatus
lda p1Counter,x
beq check
sec
sbc #1
sta p1Counter,x
rts
check
; skip all this if WINGAME flag set
lda level
and #WINGAME
bne endStatus
lda p1Status,x
beq endStatus
cmp #FALLOFF
bne nextCheck
lda #RESET
ldy #130
jmp endStatus
nextCheck
cmp #RESET
bne nextCheck2
lda #NORMAL
jmp endStatus
nextCheck2
cmp #STARTUP
bne nextCheck3
lda #GETREADY
ldy #150
jmp endStatus
nextCheck3
cmp #GETREADY
bne nextCheck4
lda #NORMAL
jmp endStatus
nextCheck4
cmp #TIMEUP
bne endStatus
lda #$15
sta p1TimeH,x
lda #RESET
ldy #120
jmp endStatus
endStatus
sta p1Status,x
tya
sta p1Counter,x
rts ; other rts in function
;==========================================================================
;
; callProcessGameLogic
;--------------------------------------------------------------------------
; Call to bank 2
;==========================================================================
org $1FA0
callProcessGameLogic
ldx BANK2
nop
nop
nop
nop
nop
nop
jmp rtnCallProcessGameLogic
;==========================================================================
;
; callIntroMessage
;
;--------------------------------------------------------------------------
; Call to bank 3
;==========================================================================
org $1FB0
callIntroMessage
ldx BANK3
nop
nop
nop
nop
nop
nop
jmp rtnCallIntroMessage
;==========================================================================
;
; callTitleScreen
;
;--------------------------------------------------------------------------
; Call to bank 3
;==========================================================================
org $1FC0
callTitleScreen
ldx BANK3
nop
nop
nop
nop
nop
nop
jmp rtnCallTitleScreen
;--------------------------------------------------------------------------
; callDrawScore
;--------------------------------------------------------------------------
; Call to bank 4
;--------------------------------------------------------------------------
org $1FD0
callDrawScore
ldx BANK4
nop
nop
nop
nop
nop
nop
jmp rtnCallDrawScore
;--------------------------------------------------------------------------
; callVBlank2
;--------------------------------------------------------------------------
; Call to bank 2
;--------------------------------------------------------------------------
org $1FE0
callVBlank2
ldx BANK2
nop
nop
nop
nop
nop
nop
jmp VBlank2Return
;---------------------------------------------------------------------------
; Program Startup Vector
;---------------------------------------------------------------------------
org $1FF3 ; The cart may start in bank 2, then a bankswitch
; will occur and land here...
jmp Start ; Start program
org $1FFC ; Program startup vector
.word Start
.word Start
include marbank2.asm
include marbank3.asm
include marbank4.asm
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| [stella] "kernel panic!", KirkIsrael | Thread | Re: [stella] Animating the Marbles, Thomas Jentzsch |
| [stella] "kernel panic!", KirkIsrael | Date | Re: [stella] Higher Resolution thro, Clay Halliwell |
| Month |