Created
November 23, 2019 03:31
-
-
Save Frank-Buss/802aae736b7ffbd80196623553730996 to your computer and use it in GitHub Desktop.
Game of Life implementation for Commander X16
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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