Import from tarball created on 2024-03-14
This commit is contained in:
commit
9206086b8a
11 changed files with 924 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
*.o
|
||||||
|
*.prg
|
||||||
|
*.lst
|
3
build.sh
Executable file
3
build.sh
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cl65 -o pong.prg -l pong.lst -t c64 -C c64-asm.cfg -u__EXEHDR__ main.asm
|
84
c64.inc
Normal file
84
c64.inc
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
|
||||||
|
PROGSTART = $080D ; just after BASIC header
|
||||||
|
|
||||||
|
;; Misc
|
||||||
|
CINV = $0314 ; Hardware IRQ vector
|
||||||
|
|
||||||
|
;; CIA registers
|
||||||
|
PRA = $DC00
|
||||||
|
PRB = $DC01
|
||||||
|
DDRA = $DC02
|
||||||
|
DDRB = $DC03
|
||||||
|
CIA_ICR = $DC0D
|
||||||
|
|
||||||
|
PRA2 = $DD00
|
||||||
|
|
||||||
|
;; VIC-II registers
|
||||||
|
VICBASE = $D000
|
||||||
|
SPRITE_0X = VICBASE+0
|
||||||
|
SPRITE_0Y = VICBASE+1
|
||||||
|
SPRITE_1X = VICBASE+2
|
||||||
|
SPRITE_1Y = VICBASE+3
|
||||||
|
SPRITE_2X = VICBASE+4
|
||||||
|
SPRITE_2Y = VICBASE+5
|
||||||
|
SPRITE_3X = VICBASE+6
|
||||||
|
SPRITE_3Y = VICBASE+7
|
||||||
|
SPRITE_4X = VICBASE+8
|
||||||
|
SPRITE_4Y = VICBASE+9
|
||||||
|
SPRITE_5X = VICBASE+10
|
||||||
|
SPRITE_5Y = VICBASE+11
|
||||||
|
SPRITE_6X = VICBASE+12
|
||||||
|
SPRITE_6Y = VICBASE+13
|
||||||
|
SPRITE_7X = VICBASE+14
|
||||||
|
SPRITE_7Y = VICBASE+15
|
||||||
|
SPRITE_X_MSB = VICBASE+16
|
||||||
|
YSCROLL_MODE = VICBASE+17
|
||||||
|
RASTER = VICBASE+18
|
||||||
|
;; ...
|
||||||
|
SPRITE_ENABLE = VICBASE+21
|
||||||
|
XSCROLL_MODE = VICBASE+22
|
||||||
|
SPRITE_XPAND_Y = VICBASE+23
|
||||||
|
;; ...
|
||||||
|
MEMPTR = VICBASE+24
|
||||||
|
VICINT = VICBASE+25
|
||||||
|
VICINTMASK = VICBASE+26
|
||||||
|
SPRITE_BG_PRIO = VICBASE+27
|
||||||
|
;; ...
|
||||||
|
SPRITE_XPAND_X = VICBASE+29
|
||||||
|
SSCOL = VICBASE+30
|
||||||
|
;; ...
|
||||||
|
BORDER = VICBASE+32
|
||||||
|
BGCOL0 = VICBASE+33
|
||||||
|
BGCOL1 = VICBASE+34
|
||||||
|
BGCOL2 = VICBASE+35
|
||||||
|
BGCOL3 = VICBASE+36
|
||||||
|
;; ...
|
||||||
|
SPRITE_0C = VICBASE+39
|
||||||
|
SPRITE_1C = VICBASE+40
|
||||||
|
SPRITE_2C = VICBASE+41
|
||||||
|
SPRITE_3C = VICBASE+42
|
||||||
|
SPRITE_4C = VICBASE+43
|
||||||
|
SPRITE_5C = VICBASE+44
|
||||||
|
SPRITE_6C = VICBASE+45
|
||||||
|
SPRITE_7C = VICBASE+46
|
||||||
|
|
||||||
|
COLORMEM = $D800
|
||||||
|
|
||||||
|
;; SID registers
|
||||||
|
SIDBASE = $D400
|
||||||
|
SIDF1H = SIDBASE+1
|
||||||
|
SIDF1L = SIDBASE+2
|
||||||
|
SIDCR1 = SIDBASE+4
|
||||||
|
SIDAD1 = SIDBASE+5
|
||||||
|
SIDSR1 = SIDBASE+6
|
||||||
|
|
||||||
|
SIDFMV = SIDBASE+24
|
||||||
|
|
||||||
|
;; Macros
|
||||||
|
|
||||||
|
.macro padto addr
|
||||||
|
.repeat (addr - *)
|
||||||
|
.byte 0
|
||||||
|
.endrep
|
||||||
|
.endmacro
|
8
enum.asm
Normal file
8
enum.asm
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
|
||||||
|
.enum mode
|
||||||
|
StartScreen = 0
|
||||||
|
MainGame
|
||||||
|
ScoreHighlight
|
||||||
|
Win
|
||||||
|
.endenum
|
183
gameloop.asm
Normal file
183
gameloop.asm
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
|
||||||
|
;;; Main gameloop routine.
|
||||||
|
game:
|
||||||
|
lda p1score
|
||||||
|
ldx #4
|
||||||
|
jsr printbyte
|
||||||
|
|
||||||
|
lda p2score
|
||||||
|
ldx #(40 - 6)
|
||||||
|
jsr printbyte
|
||||||
|
|
||||||
|
lda col
|
||||||
|
beq @nocol
|
||||||
|
jsr handle_collision
|
||||||
|
@nocol:
|
||||||
|
;; Player input:
|
||||||
|
;; F1 (restart)
|
||||||
|
ldx #%11111110
|
||||||
|
ldy #%00010000
|
||||||
|
jsr keydown
|
||||||
|
bne @norestart
|
||||||
|
jmp PROGSTART
|
||||||
|
@norestart:
|
||||||
|
|
||||||
|
;; Q (player 1 up)
|
||||||
|
ldx #%01111111
|
||||||
|
ldy #%01000000
|
||||||
|
jsr keydown
|
||||||
|
bne @skip1
|
||||||
|
dec p1y
|
||||||
|
dec p1y
|
||||||
|
|
||||||
|
;; A (player 1 down)
|
||||||
|
@skip1:
|
||||||
|
ldx #%11111101
|
||||||
|
ldy #%00000100
|
||||||
|
jsr keydown
|
||||||
|
bne @skip2
|
||||||
|
inc p1y
|
||||||
|
inc p1y
|
||||||
|
@skip2:
|
||||||
|
|
||||||
|
;; O (player 2 up)
|
||||||
|
ldx #%11101111
|
||||||
|
ldy #%01000000
|
||||||
|
jsr keydown
|
||||||
|
bne @skip3
|
||||||
|
dec p2y
|
||||||
|
dec p2y
|
||||||
|
@skip3:
|
||||||
|
|
||||||
|
;; L (player 2 down)
|
||||||
|
ldx #%11011111
|
||||||
|
ldy #%00000100
|
||||||
|
jsr keydown
|
||||||
|
bne @skip4
|
||||||
|
inc p2y
|
||||||
|
inc p2y
|
||||||
|
@skip4:
|
||||||
|
|
||||||
|
;; Clamp paddles to stay on-screen.
|
||||||
|
lda #$32 ;player 1 top
|
||||||
|
cmp p1y
|
||||||
|
bcc @dontclamp1
|
||||||
|
sta p1y
|
||||||
|
@dontclamp1:
|
||||||
|
lda #($fa - 42) ;player 1 bottom
|
||||||
|
cmp p1y
|
||||||
|
bcs @dontclamp2
|
||||||
|
sta p1y
|
||||||
|
@dontclamp2:
|
||||||
|
lda #$32 ;player 2 top
|
||||||
|
cmp p2y
|
||||||
|
bcc @dontclamp3
|
||||||
|
sta p2y
|
||||||
|
@dontclamp3:
|
||||||
|
lda #($fa - 42) ;player 2 bottom
|
||||||
|
cmp p2y
|
||||||
|
bcs @dontclamp4
|
||||||
|
sta p2y
|
||||||
|
@dontclamp4:
|
||||||
|
|
||||||
|
update_paddles:
|
||||||
|
lda p1y
|
||||||
|
sta SPRITE_0Y
|
||||||
|
lda p2y
|
||||||
|
sta SPRITE_1Y
|
||||||
|
|
||||||
|
ball_physics:
|
||||||
|
lda #BALLVERT
|
||||||
|
and balldata
|
||||||
|
beq @down ; 0 = down, 1 = up
|
||||||
|
txa
|
||||||
|
clc
|
||||||
|
dec ball_y
|
||||||
|
lda #BALLVSPEED
|
||||||
|
bit balldata
|
||||||
|
beq @slowballup
|
||||||
|
dec ball_y ;else we have a fast down ball
|
||||||
|
@slowballup:
|
||||||
|
;; Top bounce check
|
||||||
|
lda ball_y
|
||||||
|
cmp #$32
|
||||||
|
beq @topbouncestill
|
||||||
|
bcs @horizontal
|
||||||
|
@topbouncestill:
|
||||||
|
;; If it's <= 32 then we bounce off the top
|
||||||
|
jsr ball_bounce_vert
|
||||||
|
jmp @horizontal
|
||||||
|
|
||||||
|
@down:
|
||||||
|
inc ball_y
|
||||||
|
lda #BALLVSPEED
|
||||||
|
bit balldata
|
||||||
|
beq @slowballdown
|
||||||
|
inc ball_y
|
||||||
|
@slowballdown:
|
||||||
|
;; Bottom bounce check
|
||||||
|
lda ball_y
|
||||||
|
cmp #($fa - 8) ;$fa is bottom of the screen, - 8 for ball height
|
||||||
|
bcc @horizontal
|
||||||
|
jsr ball_bounce_vert
|
||||||
|
;; fallthrough to horizontal
|
||||||
|
|
||||||
|
@horizontal:
|
||||||
|
lda #BALLHORI
|
||||||
|
and balldata
|
||||||
|
beq @left ; 0 = left, 1 = right
|
||||||
|
;; Move ball right
|
||||||
|
jsr ball_x_inc ;first increment
|
||||||
|
lda #BALLHSPEED
|
||||||
|
bit balldata
|
||||||
|
beq @done
|
||||||
|
;; if bit BALLHSPEED is set, we have a horizontally fast ball
|
||||||
|
jsr ball_x_inc ;so we increment again
|
||||||
|
jmp @done
|
||||||
|
@left:
|
||||||
|
;; Move ball left
|
||||||
|
jsr ball_x_dec ;first decrement
|
||||||
|
lda #BALLHSPEED
|
||||||
|
bit balldata
|
||||||
|
beq @done
|
||||||
|
;; if bit BALLHSPEED is set, we have a horizontally fast ball
|
||||||
|
jsr ball_x_dec ;so we dec again
|
||||||
|
@done:
|
||||||
|
|
||||||
|
check_ball_goal:
|
||||||
|
;; Check to see if it's time to change score and reset the ball
|
||||||
|
lda #%00000100
|
||||||
|
bit SPRITE_X_MSB ;check if it's on the left or right side
|
||||||
|
bne @right
|
||||||
|
|
||||||
|
lda ball_x
|
||||||
|
cmp #$10
|
||||||
|
bcs @nope
|
||||||
|
inc p2score
|
||||||
|
lda p2score
|
||||||
|
jsr clampscore
|
||||||
|
sta p2score
|
||||||
|
jsr reset_ball
|
||||||
|
jsr highlightscore
|
||||||
|
jmp @nope
|
||||||
|
@right:
|
||||||
|
lda ball_x
|
||||||
|
cmp #$50
|
||||||
|
bcc @nope
|
||||||
|
inc p1score
|
||||||
|
lda p1score
|
||||||
|
jsr clampscore
|
||||||
|
sta p1score
|
||||||
|
jsr reset_ball
|
||||||
|
jsr highlightscore
|
||||||
|
@nope:
|
||||||
|
|
||||||
|
ball_sprite:
|
||||||
|
lda ball_x
|
||||||
|
sta SPRITE_2X
|
||||||
|
lda ball_y
|
||||||
|
sta SPRITE_2Y
|
||||||
|
|
||||||
|
;; MAIN GAME ROUTINE ENDS HERE, PUT SUBROUTINES AFTER
|
||||||
|
rts
|
73
graphics.asm
Normal file
73
graphics.asm
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
|
||||||
|
SPRITEBASE = $3400
|
||||||
|
|
||||||
|
sprite_data:
|
||||||
|
.repeat 21
|
||||||
|
.byte $ff, 0, 0 ;defines 8x21 paddle sprite
|
||||||
|
.endrep
|
||||||
|
.byte 0
|
||||||
|
|
||||||
|
.repeat 8
|
||||||
|
.byte $ff, 0, 0
|
||||||
|
.endrep
|
||||||
|
.repeat 13
|
||||||
|
.byte 0, 0, 0
|
||||||
|
.endrep
|
||||||
|
.byte 0
|
||||||
|
|
||||||
|
sprite_data_end:
|
||||||
|
|
||||||
|
scrlinelo:
|
||||||
|
.byte $00
|
||||||
|
.byte $28
|
||||||
|
.byte $50
|
||||||
|
.byte $78
|
||||||
|
.byte $A0
|
||||||
|
.byte $C8
|
||||||
|
.byte $F0
|
||||||
|
.byte $18
|
||||||
|
.byte $40
|
||||||
|
.byte $68
|
||||||
|
.byte $90
|
||||||
|
.byte $B8
|
||||||
|
.byte $E0
|
||||||
|
.byte $08
|
||||||
|
.byte $30
|
||||||
|
.byte $58
|
||||||
|
.byte $80
|
||||||
|
.byte $A8
|
||||||
|
.byte $D0
|
||||||
|
.byte $F8
|
||||||
|
.byte $20
|
||||||
|
.byte $48
|
||||||
|
.byte $70
|
||||||
|
.byte $98
|
||||||
|
.byte $C0
|
||||||
|
|
||||||
|
scrlinehi:
|
||||||
|
.byte $04
|
||||||
|
.byte $04
|
||||||
|
.byte $04
|
||||||
|
.byte $04
|
||||||
|
.byte $04
|
||||||
|
.byte $04
|
||||||
|
.byte $04
|
||||||
|
.byte $05
|
||||||
|
.byte $05
|
||||||
|
.byte $05
|
||||||
|
.byte $05
|
||||||
|
.byte $05
|
||||||
|
.byte $05
|
||||||
|
.byte $06
|
||||||
|
.byte $06
|
||||||
|
.byte $06
|
||||||
|
.byte $06
|
||||||
|
.byte $06
|
||||||
|
.byte $06
|
||||||
|
.byte $06
|
||||||
|
.byte $07
|
||||||
|
.byte $07
|
||||||
|
.byte $07
|
||||||
|
.byte $07
|
||||||
|
.byte $07
|
215
init.asm
Normal file
215
init.asm
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
|
||||||
|
init:
|
||||||
|
;; Set our custom NMI vector so that pressing restore quits
|
||||||
|
lda #<nmi
|
||||||
|
sta $0318
|
||||||
|
lda #>nmi
|
||||||
|
sta $0319
|
||||||
|
|
||||||
|
;; Reset gamemode
|
||||||
|
lda #mode::StartScreen
|
||||||
|
sta gamemode
|
||||||
|
|
||||||
|
;; Reset variables
|
||||||
|
lda #0
|
||||||
|
sta p1score
|
||||||
|
sta p2score
|
||||||
|
sta p1y
|
||||||
|
sta p2y
|
||||||
|
sta exit
|
||||||
|
lda #64
|
||||||
|
sta ball_x
|
||||||
|
sta ball_y
|
||||||
|
|
||||||
|
|
||||||
|
sei ;turn off IRQ while setting up
|
||||||
|
|
||||||
|
lda #$7f
|
||||||
|
sta CIA_ICR ;disable CIA IRQ
|
||||||
|
bit CIA_ICR ;acknowledge it
|
||||||
|
|
||||||
|
;; Set up our graphics
|
||||||
|
ldx #$00
|
||||||
|
stx BGCOL0 ;black background, appropriate for pong
|
||||||
|
stx BORDER
|
||||||
|
|
||||||
|
jsr loadtitlescreen
|
||||||
|
|
||||||
|
lda #%00000111
|
||||||
|
sta SPRITE_ENABLE ;enable sprite 0,1,2
|
||||||
|
sta SSCOL
|
||||||
|
sta SPRITE_BG_PRIO
|
||||||
|
lda #%00000011
|
||||||
|
sta SPRITE_XPAND_Y
|
||||||
|
lda #$01
|
||||||
|
sta SPRITE_0C
|
||||||
|
sta SPRITE_1C
|
||||||
|
sta SPRITE_2C
|
||||||
|
|
||||||
|
lda #%00000010
|
||||||
|
sta SPRITE_X_MSB
|
||||||
|
lda #$18
|
||||||
|
sta SPRITE_0X
|
||||||
|
lda #$50
|
||||||
|
sta SPRITE_1X
|
||||||
|
|
||||||
|
lda #$32
|
||||||
|
sta SPRITE_0Y
|
||||||
|
sta SPRITE_1Y
|
||||||
|
|
||||||
|
lda #$64
|
||||||
|
sta SPRITE_2X
|
||||||
|
sta SPRITE_2Y
|
||||||
|
|
||||||
|
;; Load sprites
|
||||||
|
;; Note: breaks if we have more than 255 bytes of sprite gfx
|
||||||
|
ldx #(sprite_data_end - sprite_data) ;DANGER
|
||||||
|
ldy #$00
|
||||||
|
@loadloop:
|
||||||
|
lda sprite_data,y
|
||||||
|
sta SPRITEBASE,y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne @loadloop
|
||||||
|
;; done when X is zero
|
||||||
|
|
||||||
|
;; lda #<scorestr
|
||||||
|
;; sta z:zscratch0
|
||||||
|
;; lda #>scorestr
|
||||||
|
;; sta z:zscratch1
|
||||||
|
;; ldx #4
|
||||||
|
;; jsr printstr
|
||||||
|
|
||||||
|
;; Set up our own IRQ routine
|
||||||
|
lda #<irq
|
||||||
|
sta CINV
|
||||||
|
lda #>irq
|
||||||
|
sta CINV+1
|
||||||
|
|
||||||
|
ldx #$0
|
||||||
|
stx RASTER ;trigger IRQ on scanline 0 (vblank)
|
||||||
|
ldx #%00000101 ;raster & sprite-sprite col IRQs
|
||||||
|
stx VICINTMASK ;enable VIC IRQ
|
||||||
|
|
||||||
|
cli ;turn IRQ back on, we're ready
|
||||||
|
idle:
|
||||||
|
jmp idle ;do nothing forever, game is driven by IRQ
|
||||||
|
|
||||||
|
nmi:
|
||||||
|
brk
|
||||||
|
|
||||||
|
clearscreen:
|
||||||
|
;; Let's clear the background
|
||||||
|
lda #<VMBASE
|
||||||
|
sta z:zscratch0
|
||||||
|
lda #>VMBASE
|
||||||
|
sta z:zscratch1
|
||||||
|
lda #<COLORMEM
|
||||||
|
sta z:zscratch2
|
||||||
|
lda #>COLORMEM
|
||||||
|
sta z:zscratch3
|
||||||
|
ldx #$04
|
||||||
|
@loopouter:
|
||||||
|
ldy #$00
|
||||||
|
@loopinner:
|
||||||
|
lda #$20
|
||||||
|
sta (zscratch0),y
|
||||||
|
lda #$01 ;write the color white
|
||||||
|
sta (zscratch2),y ;to every part of color RAM
|
||||||
|
iny
|
||||||
|
bne @loopinner
|
||||||
|
inc z:zscratch1 ;increment page
|
||||||
|
inc z:zscratch3
|
||||||
|
dex
|
||||||
|
bne @loopouter
|
||||||
|
|
||||||
|
;; Set up sprites
|
||||||
|
;; sprite ptr $d0 = memory location $3400
|
||||||
|
ldx #$d0
|
||||||
|
stx VMBASE+($400 - 8)
|
||||||
|
stx VMBASE+($400 - 7)
|
||||||
|
inx
|
||||||
|
stx VMBASE+($400 - 6)
|
||||||
|
|
||||||
|
rts
|
||||||
|
|
||||||
|
loadtitlescreen:
|
||||||
|
jsr clearscreen
|
||||||
|
|
||||||
|
lda #<title
|
||||||
|
sta z:zscratch0
|
||||||
|
lda #>title
|
||||||
|
sta z:zscratch1
|
||||||
|
|
||||||
|
ldx #$0a
|
||||||
|
ldy #$0b
|
||||||
|
jsr printstr
|
||||||
|
|
||||||
|
lda #<credits
|
||||||
|
sta z:zscratch0
|
||||||
|
lda #>credits
|
||||||
|
sta z:zscratch1
|
||||||
|
|
||||||
|
ldx #$0c
|
||||||
|
ldy #$0e
|
||||||
|
jsr printstr
|
||||||
|
|
||||||
|
lda #<tutorial2
|
||||||
|
sta z:zscratch0
|
||||||
|
lda #>tutorial2
|
||||||
|
sta z:zscratch1
|
||||||
|
|
||||||
|
ldx #$09
|
||||||
|
ldy #$15
|
||||||
|
jsr printstr
|
||||||
|
|
||||||
|
lda #<tutorial1
|
||||||
|
sta z:zscratch0
|
||||||
|
lda #>tutorial1
|
||||||
|
sta z:zscratch1
|
||||||
|
|
||||||
|
ldx #$0a
|
||||||
|
ldy #$17
|
||||||
|
jsr printstr
|
||||||
|
|
||||||
|
rts
|
||||||
|
|
||||||
|
title:
|
||||||
|
.byte $10, $0F, $0E, $07, $2C, $20, $0D, $0F, $12, $05, $20, $0F, $12, $20, $0C, $05, $13, $13, 0
|
||||||
|
|
||||||
|
credits:
|
||||||
|
.byte $0D, $01, $04, $05, $20, $02, $19, $20, $04, $15, $15, $11, $0E, $04, 0
|
||||||
|
|
||||||
|
tutorial1:
|
||||||
|
.byte $03, $0F, $0E, $14, $12, $0F, $0C, $20, $17, $09, $14, $08, $20, $11, $01, $20, $0F, $0C, 0
|
||||||
|
|
||||||
|
tutorial2:
|
||||||
|
.byte $10, $12, $05, $13, $13, $20, $13, $10, $01, $03, $05, $20, $14, $0F, $20, $13, $14, $01, $12, $14, 0
|
||||||
|
|
||||||
|
loadgamefield:
|
||||||
|
jsr clearscreen
|
||||||
|
|
||||||
|
;; now we'll draw the center column
|
||||||
|
ldx #$25
|
||||||
|
@lineloop:
|
||||||
|
lda scrlinelo,x
|
||||||
|
sta z:zscratch0
|
||||||
|
lda scrlinehi,x
|
||||||
|
sta z:zscratch1
|
||||||
|
txa
|
||||||
|
and #%00000001
|
||||||
|
bne @skipdot
|
||||||
|
lda #103
|
||||||
|
ldy #20
|
||||||
|
sta (zscratch0),y
|
||||||
|
jmp @next
|
||||||
|
@skipdot:
|
||||||
|
lda #116
|
||||||
|
ldy #19
|
||||||
|
sta (zscratch0),y
|
||||||
|
@next:
|
||||||
|
dex
|
||||||
|
bpl @lineloop
|
||||||
|
|
||||||
|
rts
|
246
main.asm
Normal file
246
main.asm
Normal file
|
@ -0,0 +1,246 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
.include "c64.inc"
|
||||||
|
.include "enum.asm"
|
||||||
|
|
||||||
|
VMBASE = $0400
|
||||||
|
|
||||||
|
.org PROGSTART
|
||||||
|
|
||||||
|
.include "init.asm" ;must come first
|
||||||
|
.include "utilities.asm"
|
||||||
|
|
||||||
|
;; Start screen, waits for space key to be pressed.
|
||||||
|
titlescreen:
|
||||||
|
;; More visually interesting sprite positioning for
|
||||||
|
;; the title screen. Overrides default from init.
|
||||||
|
lda #$82
|
||||||
|
sta SPRITE_0Y
|
||||||
|
|
||||||
|
ldx #%01111111
|
||||||
|
ldy #%00010000
|
||||||
|
jsr keydown
|
||||||
|
bne @dontstart
|
||||||
|
;; Start the game here.
|
||||||
|
jsr loadgamefield ;set the background
|
||||||
|
lda #mode::MainGame ;don't forget that #
|
||||||
|
sta gamemode ;set the game mode to MainGame
|
||||||
|
@dontstart:
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
;; Wait and highlight the score change for half a second.
|
||||||
|
;; Happens every time a player scores or whatever it's called in tennis
|
||||||
|
scorewait:
|
||||||
|
;; While waiting we play a buzz
|
||||||
|
lda #$0f
|
||||||
|
sta SIDFMV
|
||||||
|
lda #$08
|
||||||
|
sta SIDAD1
|
||||||
|
lda #$68
|
||||||
|
sta SIDSR1
|
||||||
|
|
||||||
|
lda #$45
|
||||||
|
sta SIDF1L
|
||||||
|
lda #$1d
|
||||||
|
sta SIDF1H
|
||||||
|
|
||||||
|
lda #$11
|
||||||
|
sta SIDCR1
|
||||||
|
|
||||||
|
dec timer
|
||||||
|
bne @dontresume
|
||||||
|
;; Reset gamemode
|
||||||
|
lda #mode::MainGame
|
||||||
|
sta gamemode
|
||||||
|
;; Reset background color
|
||||||
|
lda #0
|
||||||
|
sta BGCOL0
|
||||||
|
;; Stop sound
|
||||||
|
lda #$10
|
||||||
|
sta SIDCR1
|
||||||
|
@dontresume:
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
;; Call after a player scores to highlight the win
|
||||||
|
highlightscore:
|
||||||
|
lda #mode::ScoreHighlight
|
||||||
|
sta gamemode
|
||||||
|
lda #25
|
||||||
|
sta timer
|
||||||
|
lda #2
|
||||||
|
sta BGCOL0
|
||||||
|
rts
|
||||||
|
|
||||||
|
.include "gameloop.asm"
|
||||||
|
|
||||||
|
|
||||||
|
;; "Victory" mode when 100 points has been reached.
|
||||||
|
win:
|
||||||
|
dec timer
|
||||||
|
bne @skip
|
||||||
|
dec timer2
|
||||||
|
bne @continue
|
||||||
|
;; After five seconds (10 half-seconds) we reset the game
|
||||||
|
jmp PROGSTART
|
||||||
|
@continue:
|
||||||
|
lda #25
|
||||||
|
sta timer
|
||||||
|
lda BGCOL0
|
||||||
|
eor #8
|
||||||
|
sta BGCOL0
|
||||||
|
@skip:
|
||||||
|
rts
|
||||||
|
|
||||||
|
winstop:
|
||||||
|
lda #25
|
||||||
|
sta timer
|
||||||
|
lda #10
|
||||||
|
sta timer2
|
||||||
|
lda #$0d
|
||||||
|
sta BGCOL0
|
||||||
|
lda #mode::Win ;DO NOT FORGET THE #
|
||||||
|
sta gamemode
|
||||||
|
rts
|
||||||
|
|
||||||
|
ball_x_inc:
|
||||||
|
inc ball_x
|
||||||
|
bne @done
|
||||||
|
;; If ball_x incremented to zero we have either looped around
|
||||||
|
;; the screen (shouldn't happen) or crossed the bit 8 boundry.
|
||||||
|
;; So we set the MSB to one, since we're going right.
|
||||||
|
lda #%00000100
|
||||||
|
ora SPRITE_X_MSB
|
||||||
|
sta SPRITE_X_MSB
|
||||||
|
@done:
|
||||||
|
rts
|
||||||
|
|
||||||
|
ball_x_dec:
|
||||||
|
dec ball_x
|
||||||
|
lda ball_x
|
||||||
|
cmp #$ff
|
||||||
|
bne @done
|
||||||
|
;; If ball_x incremented to zero we have either looped around
|
||||||
|
;; the screen (shouldn't happen) or crossed the bit 8 boundry.
|
||||||
|
;; So we set the MSB to one, since we're going right.
|
||||||
|
lda #%11111011
|
||||||
|
and SPRITE_X_MSB
|
||||||
|
sta SPRITE_X_MSB
|
||||||
|
@done:
|
||||||
|
rts
|
||||||
|
|
||||||
|
ball_bounce_vert:
|
||||||
|
jsr color_change
|
||||||
|
lda #%10000000
|
||||||
|
eor balldata
|
||||||
|
sta balldata
|
||||||
|
rts
|
||||||
|
|
||||||
|
ball_bounce_hori:
|
||||||
|
jsr color_change
|
||||||
|
lda #%01000000
|
||||||
|
eor balldata
|
||||||
|
sta balldata
|
||||||
|
rts
|
||||||
|
|
||||||
|
reset_ball:
|
||||||
|
jsr ball_bounce_hori
|
||||||
|
lda #$90
|
||||||
|
sta ball_y
|
||||||
|
lda #$c0
|
||||||
|
sta ball_x
|
||||||
|
lda #%11111011
|
||||||
|
and SPRITE_X_MSB
|
||||||
|
sta SPRITE_X_MSB
|
||||||
|
rts
|
||||||
|
|
||||||
|
color_change:
|
||||||
|
inc bordercol
|
||||||
|
lda bordercol
|
||||||
|
and #$0f
|
||||||
|
cmp #2
|
||||||
|
bcs @fine
|
||||||
|
lda #2
|
||||||
|
sta bordercol
|
||||||
|
@fine:
|
||||||
|
lda bordercol
|
||||||
|
sta BORDER
|
||||||
|
rts
|
||||||
|
|
||||||
|
handle_collision:
|
||||||
|
jsr ball_bounce_hori ;obvious, flip the ball's horizontal direction
|
||||||
|
lda #$00
|
||||||
|
sta col ;clear the collision flag
|
||||||
|
rts
|
||||||
|
|
||||||
|
;; Cheap trick to make a hexprinted number look decimal.
|
||||||
|
;; Score comes in the A register, clamped score returned in A
|
||||||
|
clampscore:
|
||||||
|
tax
|
||||||
|
and #%00001111
|
||||||
|
cmp #$0a
|
||||||
|
bcc @noclamplower
|
||||||
|
;; yes clamp, inc upper nybble, ex. $19 -> $20
|
||||||
|
txa
|
||||||
|
and #%11110000
|
||||||
|
clc
|
||||||
|
adc #$10
|
||||||
|
tax
|
||||||
|
@noclamplower:
|
||||||
|
txa
|
||||||
|
and #%11110000
|
||||||
|
cmp #$a0
|
||||||
|
bcc @noclamp
|
||||||
|
;; over 99? just stop at that point, we'll flash some colors then reset
|
||||||
|
jsr winstop
|
||||||
|
pla
|
||||||
|
pla
|
||||||
|
@noclamp:
|
||||||
|
txa
|
||||||
|
rts
|
||||||
|
|
||||||
|
modedispatch:
|
||||||
|
jsr jumpwithtable
|
||||||
|
.addr titlescreen
|
||||||
|
.addr game ;normal gameplay
|
||||||
|
.addr scorewait
|
||||||
|
.addr win
|
||||||
|
|
||||||
|
|
||||||
|
;; Main IRQ subroutine. CPU gets sent here by the interrupts from the
|
||||||
|
;; VIC-II's raster and collision interrupts, and is responsible for
|
||||||
|
;; calling everything else. Since the game is interrupt-driven, you
|
||||||
|
;; could add a RTS to the init code and have the game run together
|
||||||
|
;; with BASIC. Would be pretty stupid but you *can* do it. That does
|
||||||
|
;; give me an idea though...
|
||||||
|
irq:
|
||||||
|
lda SSCOL ;need to do this for collision checking to work
|
||||||
|
|
||||||
|
lda #%00000100 ;check if irq is for collision or not
|
||||||
|
and VICINT
|
||||||
|
beq @nocol
|
||||||
|
;; Collision
|
||||||
|
sta col ;set the collision flag
|
||||||
|
lda #$7f
|
||||||
|
and VICINT
|
||||||
|
sta VICINT
|
||||||
|
jmp @skipgame
|
||||||
|
@nocol:
|
||||||
|
lda gamemode
|
||||||
|
jsr modedispatch
|
||||||
|
@skipgame:
|
||||||
|
lda #$7f
|
||||||
|
and VICINT
|
||||||
|
sta VICINT
|
||||||
|
|
||||||
|
jmp $ea31
|
||||||
|
|
||||||
|
.include "variables.asm"
|
||||||
|
|
||||||
|
BALLVERT = %10000000
|
||||||
|
BALLHORI = %01000000
|
||||||
|
BALLVSPEED = %00000010
|
||||||
|
BALLHSPEED = %00000001
|
||||||
|
|
||||||
|
.include "graphics.asm"
|
||||||
|
.include "zeropage.asm"
|
88
utilities.asm
Normal file
88
utilities.asm
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
|
||||||
|
;; Jumps to a routine via a table. Index goes in A register.
|
||||||
|
jumpwithtable:
|
||||||
|
tay
|
||||||
|
|
||||||
|
;; Set up pointer to jump table
|
||||||
|
pla
|
||||||
|
sta z:zscratch0
|
||||||
|
pla
|
||||||
|
sta z:zscratch1
|
||||||
|
|
||||||
|
tya
|
||||||
|
asl
|
||||||
|
tay
|
||||||
|
iny
|
||||||
|
|
||||||
|
lda (zscratch0),y
|
||||||
|
sta z:zscratch2
|
||||||
|
iny
|
||||||
|
lda (zscratch0),y
|
||||||
|
sta z:zscratch3
|
||||||
|
|
||||||
|
jmp (zscratch2)
|
||||||
|
|
||||||
|
printbyte:
|
||||||
|
inx
|
||||||
|
jsr printnyb
|
||||||
|
.repeat 4
|
||||||
|
lsr
|
||||||
|
.endrep
|
||||||
|
dex
|
||||||
|
jsr printnyb
|
||||||
|
rts
|
||||||
|
|
||||||
|
printnyb:
|
||||||
|
pha
|
||||||
|
and #$0f
|
||||||
|
cmp #$0a
|
||||||
|
bcc @number ;if nybble<$A then print a number, else letter
|
||||||
|
sec
|
||||||
|
sbc #$09 ;letters start at $01, so sub away 9
|
||||||
|
jmp @done
|
||||||
|
@number:
|
||||||
|
clc
|
||||||
|
adc #$30 ;print a number, starting at $30
|
||||||
|
@done:
|
||||||
|
sta VMBASE,x
|
||||||
|
pla
|
||||||
|
rts
|
||||||
|
|
||||||
|
;; Put string pointer into zscratch1+2
|
||||||
|
;; X position into X, y pos into Y
|
||||||
|
printstr:
|
||||||
|
lda scrlinelo,y
|
||||||
|
sta z:zscratch2
|
||||||
|
lda scrlinehi,y
|
||||||
|
sta z:zscratch3
|
||||||
|
|
||||||
|
txa
|
||||||
|
clc
|
||||||
|
adc z:zscratch2
|
||||||
|
sta z:zscratch2
|
||||||
|
lda z:zscratch3
|
||||||
|
adc #0
|
||||||
|
sta z:zscratch3
|
||||||
|
|
||||||
|
ldy #$00
|
||||||
|
@loop:
|
||||||
|
lda (zscratch0),y
|
||||||
|
beq @done
|
||||||
|
sta (zscratch2),y
|
||||||
|
iny
|
||||||
|
inx
|
||||||
|
jmp @loop
|
||||||
|
@done:
|
||||||
|
rts
|
||||||
|
|
||||||
|
keydown:
|
||||||
|
lda #$ff
|
||||||
|
sta DDRA
|
||||||
|
lda #$00
|
||||||
|
sta DDRB
|
||||||
|
stx PRA
|
||||||
|
tya
|
||||||
|
and PRB
|
||||||
|
rts
|
||||||
|
|
14
variables.asm
Normal file
14
variables.asm
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
gamemode: .res 1, mode::StartScreen
|
||||||
|
p1y: .res 1, 0
|
||||||
|
p1score: .res 1, $90
|
||||||
|
p2score: .res 1, 0
|
||||||
|
p2y: .res 1, 0
|
||||||
|
col: .res 1, 0
|
||||||
|
balldata: .res 1, %01000011 ;ball starts going right, fast vert & hori
|
||||||
|
ball_x: .res 1, 64
|
||||||
|
ball_y: .res 1, 64
|
||||||
|
bordercol: .res 1, 0
|
||||||
|
timer: .res 1, 0
|
||||||
|
timer2: .res 1, 0
|
||||||
|
exit: .res 1, 0
|
7
zeropage.asm
Normal file
7
zeropage.asm
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*-
|
||||||
|
.zeropage
|
||||||
|
.org $50
|
||||||
|
zscratch0: .res 1
|
||||||
|
zscratch1: .res 1
|
||||||
|
zscratch2: .res 1
|
||||||
|
zscratch3: .res 1
|
Loading…
Add table
Reference in a new issue