Skip to content

Instantly share code, notes, and snippets.

@Frank-Buss
Created November 23, 2019 03:31
Show Gist options
  • Save Frank-Buss/802aae736b7ffbd80196623553730996 to your computer and use it in GitHub Desktop.
Save Frank-Buss/802aae736b7ffbd80196623553730996 to your computer and use it in GitHub Desktop.
Game of Life implementation for Commander X16
; Game of Life implementation for Commander X16
; Copyright 2019 by Frank Buss
;
; compile with CC65 like this:
; cl65 --cpu 65c02 -t none -o gameoflife.prg gameoflife.s
VERA_ADDR_LO = $9f20
VERA_ADDR_MID = $9f21
VERA_ADDR_HI = $9f22
VERA_DATA0 = $9f23
timer = $294
.macro vpoke bank, adr
pha
lda #bank
sta VERA_ADDR_HI
lda #>adr
sta VERA_ADDR_MID
lda #<adr
sta VERA_ADDR_LO
pla
sta VERA_DATA0
.endmacro
.zeropage
p: .res 2
p2: .res 2
p3: .res 2
p4: .res 2
xc: .res 1
yc: .res 1
.code
.org $07ff
.word $0801 ; load address
.word $080b ; address of next basic line
.word 2019 ; line number
.byte $9E ; SYS token
.byte '2', '0', '6', '1'
.byte $00 ; end of BASIC line
.word 0 ; BASIC end marker
; disable interrupts for max speed
sei
; enable VSYNC bit
lda #1
sta $9f26
; disable both layers
jsr waitvsync
lda #0
vpoke $f, $2000
vpoke $f, $3000
jsr waitvsync
jsr waitvsync
; set standard scale for 640 x 480
lda #$80
vpoke $f, 1
vpoke $f, 2
; clear memory, set all tiles to 0, init tile map color to 1
lda #$10
sta VERA_ADDR_HI
stz VERA_ADDR_MID
stz VERA_ADDR_LO
lda #2
sta xc
lda #1
c1: ldx #0
c2: ldy #0
c3: stz VERA_DATA0
sta VERA_DATA0
dey
bne c3
dex
bne c2
dec xc
bne c1
; layer 0 setup
; tileh=0, tilew=0 (8 x 8 pixels), mapw=2, maph=2 (128 x 32 tiles)
lda #$06
vpoke $f, $2001
; map_base at $0
lda #0
vpoke $f, $2002
vpoke $f, $2003
; tile_base at $10000
lda #($10000 >> 2) & $ff
vpoke $f, $2004
lda #$10000 >> 10
vpoke $f, $2005
; tile graphics
lda #$11
sta VERA_ADDR_HI
stz VERA_ADDR_MID
stz VERA_ADDR_LO
ldx #8
g1: stz VERA_DATA0
dex
bne g1
ldx #8
lda #$ff
g2: sta VERA_DATA0
dex
bne g2
; background color black
lda #0
vpoke $f, $1000
vpoke $f, $1001
; cell color cyan
lda #$ff
vpoke $f, $1002
lda #0
vpoke $f, $1003
; layer 0, mode=0, enabled=1
jsr waitvsync
lda #1
vpoke $f, $2000
; clear life arrays, 82*62*2 bytes, can be more, unused RAM after the arrays
lda #<life1
sta p
lda #>life1
sta p + 1
lda #0
ldx #40
cl1:ldy #0
cl2:sta (p),y
dey
bne cl2
inc p+1
dex
bne cl1
; init with rabbits pattern
lda #1
sta life1 + 30*82+35
sta life1 + 30*82+39
sta life1 + 30*82+40
sta life1 + 30*82+41
sta life1 + 31*82+35
sta life1 + 31*82+36
sta life1 + 31*82+37
sta life1 + 31*82+40
sta life1 + 32*82+36
; init pointers to the life arrays
lda #<life1
sta p
lda #>life1
sta p+1
lda #<life2
sta p2
lda #>life2
sta p2+1
; show life array
s: jsr waitvsync
clc
lda p
adc #83
sta p3
lda p+1
adc #0
sta p3+1
lda #$20 ; increment 2 to skip color in tile map, tile map starts at address 0
sta VERA_ADDR_HI
ldx #0
s1: stx VERA_ADDR_MID ; x-reg is the y position, 128 tiles means I need can use this for MID
stz VERA_ADDR_LO
ldy #0 ; y-reg is the x position
s2: lda (p3),y
sta VERA_DATA0
iny
cpy #80
bne s2
clc
lda p3
adc #82
sta p3
lda p3+1
adc #0
sta p3+1
inx
cpx #60
bne s1
; wrap around: copy first row to last offscreen row
clc
lda p
adc #83
sta p3
lda p+1
adc #0
sta p3+1
clc
lda p
adc #<(82*61+1)
sta p4
lda p+1
adc #>(82*61+1)
sta p4+1
ldy #79
w1: lda (p3),y
sta (p4),y
dey
bpl w1
; wrap around: copy last row to first offscreen row
clc
lda p
adc #1
sta p3
lda p+1
adc #0
sta p3+1
clc
lda p
adc #<(82*60+1)
sta p4
lda p+1
adc #>(82*60+1)
sta p4+1
ldy #79
w2: lda (p4),y
sta (p3),y
dey
bpl w2
; wrap around: copy first column to last offscreen column
; and last column to first offscreen column
clc
lda p
adc #82
sta p3
lda p+1
adc #0
sta p3+1
ldx #60
w3: ldy #1
lda (p3),y
ldy #81
sta (p3),y
ldy #80
lda (p3),y
ldy #0
sta (p3),y
clc
lda p3
adc #82
sta p3
lda p3+1
adc #0
sta p3+1
dex
bne w3
; wrap around: 4 corners
clc
lda p
sta p3
lda p+1
sta p3+1
clc
lda p
adc #<(82*60)
sta p4
lda p+1
adc #>(82*60)
sta p4+1
ldy #83
lda (p3),y
ldy #163
sta (p3),y
ldy #162
lda (p3),y
ldy #82
sta (p4),y
ldy #1
lda (p4),y
ldy #81
sta (p3),y
ldy #80
lda (p4),y
ldy #0
sta (p3),y
; calculate next generation
lda p
sta p3
lda p+1
sta p3+1
lda p2
sta p4
lda p2+1
sta p4+1
lda #60
sta yc
n: lda #80
sta xc
n2: clc
ldy #0
lda (p3),y
iny
adc (p3),y
iny
adc (p3),y
ldy #82
adc (p3),y
ldy #84
adc (p3),y
ldy #164
adc (p3),y
iny
adc (p3),y
iny
adc (p3),y
asl a
ldy #83
ora (p3),y
tax
lda lookup,x
sta (p4),y
inc p3
bne n3
inc p3+1
n3: inc p4
bne n4
inc p4+1
n4: dec xc
bne n2
inc p3
bne n5
inc p3+1
n5: inc p4
bne n6
inc p4+1
n6: inc p3
bne n7
inc p3+1
n7: inc p4
bne n8
inc p4+1
n8: dec yc
bne n
; swap life arrays
lda p
ldx p2
stx p
sta p2
lda p+1
ldx p2+1
stx p+1
sta p2+1
jmp s
waitvsync:
lda $9f27
and #1
beq waitvsync
sta $9f27
rts
lookup:
.byte 0 ; neighbours: 0, center: 0
.byte 0 ; neighbours: 0, center: 1
.byte 0 ; neighbours: 1, center: 0
.byte 0 ; neighbours: 1, center: 1
.byte 0 ; neighbours: 2, center: 0
.byte 1 ; neighbours: 2, center: 1
.byte 1 ; neighbours: 3, center: 0
.byte 1 ; neighbours: 3, center: 1
.byte 0 ; neighbours: 4, center: 0
.byte 0 ; neighbours: 4, center: 1
.byte 0 ; neighbours: 5, center: 0
.byte 0 ; neighbours: 5, center: 1
.byte 0 ; neighbours: 6, center: 0
.byte 0 ; neighbours: 6, center: 1
.byte 0 ; neighbours: 7, center: 0
.byte 0 ; neighbours: 7, center: 1
.byte 0 ; neighbours: 8, center: 0
.byte 0 ; neighbours: 8, center: 1
.bss
life1: .res 82*62
life2: .res 82*62
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment