Code:
.inesprg 1
.ineschr 1
.inesmir 1
.inesmap 0
.org $8000
.bank 0
paddle_y = $0200
paddle_x = $0203
paddle2_y = $020c
paddle2_x = $020f
ball_y = $0218
ball_x = $021b
score_1 = $0221
score_2 = $021d
direction = $304
reset:
sei ; ignore IRQs
cld ; disable decimal mode
ldx #$40
stx $4017 ; disable APU frame IRQ
ldx #$ff
txs ; Set up stack
inx ; now X = 0
stx $2000 ; disable NMI
stx $2001 ; disable rendering
stx $4010 ; disable DMC IRQs
; Optional (omitted):
; Set up mapper and jmp to further init code here.
; First of two waits for vertical blank to make sure that the
; PPU has stabilized
vblankwait1:
bit $2002
bpl vblankwait1
; We now have about 30,000 cycles to burn before the PPU stabilizes.
; Use it to clear RAM. X is still 0...
txa
clrmem:
sta $000,x
sta $100,x
sta $200,x
sta $300,x
sta $400,x
sta $500,x
sta $600,x
sta $700,x ; Remove this if you're storing reset-persistent data
inx
bne clrmem
vblankwait2:
bit $2002
bpl vblankwait2
ldpalletadr:
lda #$3F
sta $2006
lda #$10
sta $2006
ldx #$00
palletloop:
LDA palette, x ;load palette byte
STA $2007 ;write to PPU
INX ;set index to next byte
CPX #$20
BNE palletloop ;if x = $20, 32 bytes copied, all done
preploadscreen:
lda $2002
lda #$20
sta $2006
lda #$20
sta $2006
ldx #$00
lda #$01
loadscreen:
sta $2007
inx
cpx #$20
bne loadscreen
preloadscreen2:
lda $2002
lda #$23
sta $2006
lda #$00
sta $2006
ldx #$00
lda #$01
loadscreen2:
sta $2007
inx
cpx #$20
bne loadscreen2
set2006:
lda #$00
sta $2006
sta $2006
drawscore1:
lda #$c7
sta $021C
lda #$04
STA $021d
lda #$00
sta $021e
lda #$50
sta $021f
drawscore2:
lda #$c7
sta $0220
lda #$04
STA $0221
lda #$00
sta $0222
lda #$A7
sta $0223
drawpaddle:
lda #$48 ;first sprite
sta paddle_y ;store y position
lda #$03
sta $0201 ;store sprite number
lda #%00000000
sta $0202 ;store no flipping ect.
lda #$08
sta paddle_x ;store x position
lda #$50 ;second sprite
sta $0204
lda #$01
sta $0205
lda #$00
sta $0206
lda #$08
sta $0207
lda #$58 ;third sprite
sta $0208
lda #$03
sta $0209
lda #%10000000
sta $020A
lda #$08
sta $020B ;end third sprite
drawpaddle2:
lda #$48 ;first sprite
sta paddle2_y ;store y position
lda #$03
sta $020d ;store sprite number
lda #$00
sta $020e ;store no flipping ect.
lda #$f0
sta paddle2_x ;store x position
lda #$50 ;second sprite
sta $0210
lda #$01
sta $0211
lda #$00
sta $0212
lda #$f0
sta $0213
lda #$58 ;third sprite
sta $0214
lda #$03
sta $0215
lda #%10000000
sta $0216
lda #$f0
sta $0217 ;end third sprite
lda #$02
sta $4014
drawball:
lda #$50 ;sprite
sta ball_y ;store y position
lda #$02
sta $0219 ;store sprite number
lda #$00
sta $021a ;store no flipping ect.
lda #$7b
sta ball_x ;store x position
setbalv:
lda #$01
sta $301
lda #$02
sta $300
generate:
lda #%10000000
sta $2000
turnon:
lda #%00011110
sta $2001
setscore:
lda #$04
sta score_1
sta score_2
loop:
jmp loop
reverse:
Lda direction
eor #$00000001
sta direction
rts
nmi:
pha ; Push A on the stack (which were the contents in A)
txa ; transfer X to A
pha ; Push A on the stack (which were the contents in X)
tya ; transfer Y to A
pha ; Push A on the stack (which were the contents in Y)
checkscore1:
ldx ball_x
cpx #$F7
bcc checkscore2
lda score_2
clc
cmp #$07
bne scorelol1
jmp reset
scorelol1:
lda #$7b
sta ball_x
lda #$50
sta ball_y
ldx score_2
inx
stx score_2
jsr reverse
checkscore2:
ldx ball_x
cpx #$08
bcs checkdirection
lda score_1
clc
cmp #$07
bne scorelol2
jmp reset
scorelol2:
lda #$7b
sta ball_x
lda #$50
sta ball_y
ldx score_1
inx
stx score_1
jsr reverse
checkdirection:
ldx direction
cpx #$00
bne checkballpaddle2
checkballpaddle1:
lda paddle2_x
clc
adc #$08
clc
cmp ball_x
bcc checkbounce ;If the left edge of the enemy is farther than the Player's Right edge, there is could be no collision.
lda ball_x
clc
adc #$08
clc
cmp paddle2_x
bcc checkbounce ;If the Player's Left edge is beyond the enemy's right, there's no way there could be a collision.
lda paddle2_y
clc
adc #$15
clc
cmp ball_y
bcc checkbounce ;If the Player's Bottom Border is above the top of the enemy, there is no way for collision.
lda ball_y
clc
adc #$08
clc
cmp paddle2_y
bcc checkbounce ;If the player's Top edge is below (Greater than) the enemy's bottom edge, there can be no collision.
reverseball:
jsr reverse
checkballpaddle2:
lda paddle_x
clc
adc #$08
clc
cmp ball_x
bcc checkbounce ;If the left edge of the enemy is farther than the Player's Right edge, there is could be no collision.
lda ball_x
clc
adc #$08
clc
cmp paddle_x
bcc checkbounce ;If the Player's Left edge is beyond the enemy's right, there's no way there could be a collision.
lda paddle_y
clc
adc #$15
clc
cmp ball_y
bcc checkbounce ;If the Player's Bottom Border is above the top of the enemy, there is no way for collision.
lda ball_y
clc
adc #$08
clc
cmp paddle_y
bcc checkbounce ;If the player's Top edge is below (Greater than) the enemy's bottom edge, there can be no collision.
reverseball2:
jsr reverse
checkbounce:
ldx ball_y
cpx #$10
beq checkbounce2
reversey:
lda $303
eor #$00000001
sta $303
checkbounce2:
ldx ball_y
cpx #$b8
beq updatebally1
reversey2:
lda $303
eor #$00000001
sta $303
updatebally1:
lda $303
and #$01
bne updatebally2
lda ball_y
clc
adc $300
sta ball_y
jmp updateballx1
updatebally2:
lda ball_y
sec
sbc $300
sta ball_y
updateballx1:
lda direction
and #%00000001
bne updateballx2
lda ball_x
clc
adc $301
sta ball_x
jmp check1
updateballx2:
lda ball_x
sec
sbc $301
sta ball_x
checkcheck1:
ldx ball_x
cpx #$EF
bcc checkcheck2
jmp finish
checkcheck2:
ldx ball_x
cpx #$10
bcs check1
jmp finish
check1:
ldx paddle_y ;see if paddle is at top
cpx #$10
beq check2
lda #$01 ; start latch
sta $4016
lda #$00
sta $4016 ;latch the controller
lda $4016
lda $4016
lda $4016
lda $4016 ;ignore everything till up and down
lda $4016
and #%00000001
beq check2 ;if up pressed go up
ldx paddle_y
dex
stx paddle_y ;first sprite
ldx $0204
dex
stx $0204 ;second
ldx $0208
dex
stx $0208 ;third
check2:
ldx $0208 ;see if paddle is at bottom
cpx #$b8
beq check3
lda #$01 ; start latch
sta $4016
lda #$00
sta $4016 ;latch the controller
lda $4016
lda $4016
lda $4016
lda $4016 ;ignore everything till up and down
lda $4016
lda $4016
and #%00000001
beq check3 ;yaya
ldx paddle_y
inx
stx paddle_y ;first
ldx $0204
inx
stx $0204 ;second
ldx $0208
inx
stx $0208 ;third.
check3:
ldx paddle2_y ;see if paddle is at top
cpx #$10
beq check4
lda #$01 ; start latch
sta $4016
lda #$00
sta $4016 ;latch the controller
lda $4017
lda $4017
lda $4017
lda $4017 ;ignore everything till up and down
lda $4017
and #%00000001
beq check4 ;if up pressed go up
ldx paddle2_y
dex
stx paddle2_y ;first sprite
ldx $0210
dex
stx $0210 ;second
ldx $0214
dex
stx $0214 ;third
check4:
ldx $0214 ;see if paddle is at bottom
cpx #$b8
beq finish
lda #$01 ; start latch
sta $4016
lda #$00
sta $4016 ;latch the controller
lda $4017
lda $4017
lda $4017
lda $4017 ;ignore everything till up and down
lda $4017
lda $4017
and #%00000001
beq finish ;yaya
ldx paddle2_y
inx
stx paddle2_y ;first
ldx $0210
inx
stx $0210 ;second
ldx $0214
inx
stx $0214 ;third.
finish:
lda #$02
sta $4014
pla ; Pull A off of the stack (which were the contents in Y)
tay ; transfer A to Y
pla ; Pull A off of the stack (which were the contents in X)
tax ; transfer A to X
pla ; Pull A off of the stack (which were the contents in A)
rti ; return from NMI interrupt
palette:
.db $0F,$30,$30,$30, $0F,$30,$30,$30, $0F,$30,$30,$30, $0F,$30,$30,$30
.db $0F,$30,$30,$30, $0F,$30,$30,$30, $0F,$30,$30,$30, $0F,$30,$30,$30
.bank 1
.org $FFFA
.dw nmi ;(NMI_Routine)
.dw reset ;(Reset_Routine)
.dw 0 ;(IRQ_Routine)
.bank 2
.org $0000
.incbin "pong.chr" ;gotta be 8192 bytes long
My code in its entirety.