Skip to content

Commit

Permalink
added cx16/life.p8 example (Conway's game of life)
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Sep 6, 2024
1 parent 29dd758 commit 0eac04c
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 44 deletions.
1 change: 1 addition & 0 deletions compiler/test/TestCompilerOnExamples.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class TestCompilerOnExamplesCx16: FunSpec({
"highresbitmap",
"kefrenbars",
"keyboardhandler",
"life",
"mandelbrot",
"multi-irq-old",
"multi-irq-new",
Expand Down
18 changes: 18 additions & 0 deletions docs/source/todo.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
TODO
====

TODO creates buggy code in 6502: (ok in IR)
main {
sub start() {
uword active_world = memory("world", 80*50, 0)
uword cell_off = 500
const uword STRIDE = 40
sys.memset(active_world, 80*50, 1)
txt.print_ub(count()) ; TODO prints 1, must be 8

sub count() -> ubyte {
return active_world[cell_off-STRIDE-1] + active_world[cell_off-STRIDE] + active_world[cell_off-STRIDE+1] +
active_world[cell_off-1] + active_world[cell_off+1] +
active_world[cell_off+STRIDE-1] + active_world[cell_off+STRIDE] + active_world[cell_off+STRIDE+1]
}
}
}


Improve register load order in subroutine call args assignments:
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
in overwriting registers that already got their value, which requires a lot of stack juggling (especially on plain 6502 cpu!)
Expand Down
139 changes: 139 additions & 0 deletions examples/cx16/life.p8
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
; conway's game of life.

%import math
%import textio
%import emudbg

main {
const ubyte WIDTH = 80
const ubyte HEIGHT = 60-4
const uword STRIDE = $0002+WIDTH
uword world1 = memory("world1", (WIDTH+2)*(HEIGHT+2), 0)
uword world2 = memory("world2", (WIDTH+2)*(HEIGHT+2), 0)
uword @requirezp active_world = world1

sub start() {
; cx16.set_screen_mode(3)
txt.cls()
txt.color(8)
txt.plot(50,0)
txt.print("prog8 - conway's game of life")
sys.memset(world1, (WIDTH+2)*(HEIGHT+2), 0)
sys.memset(world2, (WIDTH+2)*(HEIGHT+2), 0)

set_start_gen()

ubyte gen_add
uword gen
repeat {
if gen_add==0
cbm.SETTIM(0,0,0)

next_gen()

gen++
txt.home()
txt.color(5)
txt.print(" gen ")
txt.print_uw(gen)

gen_add++
if gen_add==10 {
txt.print(" jiffies/10 gens: ")
txt.print_uw(cbm.RDTIM16())
txt.print(" ")
gen_add=0
}
}
}

sub set_start_gen() {

; some way to set a custom start generation:
; str start_gen = " " +
; " " +
; " " +
; " ** " +
; " * * " +
; " * " +
; " * * " +
; " ****** " +
; " " +
; " " +
; " " +
; " " +
; " " +
; " " +
; " " +
; " "
;
; for y in 0 to 15 {
; for x in 0 to 15 {
; if start_gen[y*16 + x]=='*'
; active_world[offset + x] = 1
; }
; offset += STRIDE
; }

; randomize whole world
uword offset = STRIDE+1
ubyte x
ubyte y
for y in 0 to HEIGHT-1 {
for x in 0 to WIDTH-1 {
if math.rnd() & 1 == 1
active_world[offset+x] = 1
}
offset += STRIDE
}
}

sub next_gen() {
uword @requirezp new_world
if active_world == world1
new_world = world2
else
new_world = world1

const ubyte DXOFFSET = 0
const ubyte DYOFFSET = 2
uword voffset = STRIDE+1-DXOFFSET
uword offset

ubyte x
ubyte y
for y in DYOFFSET to HEIGHT+DYOFFSET-1 {

cx16.vaddr_autoincr(1, $b000 + 256*y, 0, 2) ; allows us to use simple Vera data byte assigns later instead of setchr() calls

for x in DXOFFSET to WIDTH+DXOFFSET-1 {
offset = voffset + x
ubyte cell = active_world[offset]

; count the neighbors
uword @requirezp ptr = active_world + offset - STRIDE - 1
ubyte neighbors = @(ptr) + @(ptr+1) + @(ptr+2) +
@(ptr+STRIDE) + cell + @(ptr+STRIDE+2) +
@(ptr+STRIDE*2) + @(ptr+STRIDE*2+1) + @(ptr+STRIDE*2+2)

; apply game of life rules
if neighbors==3
cell=1
else if neighbors!=4
cell=0
new_world[offset] = cell

; draw new cell
if cell==0
; txt.setchr(x, y, sc:' ')
cx16.VERA_DATA0 = sc:' '
else
; txt.setchr(x, y, sc:'')
cx16.VERA_DATA0 = sc:''
}
voffset += STRIDE
}

active_world = new_world
}
}
54 changes: 10 additions & 44 deletions examples/test.p8
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,16 @@

main {
sub start() {
for cx16.r0L in 5 to 5 {
txt.print("derp0.")
txt.print_ub(cx16.r0L)
txt.nl()
}
for cx16.r0L in 100 downto 100 {
txt.print("derp1.")
txt.print_ub(cx16.r0L)
txt.nl()
}
for cx16.r0L in 100 to 100 {
txt.print("derp2.")
txt.print_ub(cx16.r0L)
txt.nl()
}
for cx16.r0 in 2222 downto 2222 {
txt.print("derp3.")
txt.print_uw(cx16.r0)
txt.nl()
}
for cx16.r0 in 2222 to 2222 {
txt.print("derp4.")
txt.print_uw(cx16.r0)
txt.nl()
}
for cx16.r0L in 100 downto 100 step -5 {
txt.print("derp5.")
txt.print_ub(cx16.r0L)
txt.nl()
}
for cx16.r0L in 100 to 100 step 5 {
txt.print("derp6.")
txt.print_ub(cx16.r0L)
txt.nl()
}
for cx16.r0 in 2222 downto 2222 step -5 {
txt.print("derp7.")
txt.print_uw(cx16.r0)
txt.nl()
}
for cx16.r0 in 2222 to 2222 step 5 {
txt.print("derp8.")
txt.print_uw(cx16.r0)
txt.nl()
uword active_world = memory("world", 80*50, 0)
uword cell_off = 500
const uword STRIDE = 40
sys.memset(active_world, 80*50, 1)
txt.print_ub(count()) ; TODO prints 1, must be 8

sub count() -> ubyte {
return active_world[cell_off-STRIDE-1] + active_world[cell_off-STRIDE] + active_world[cell_off-STRIDE+1] +
active_world[cell_off-1] + active_world[cell_off+1] +
active_world[cell_off+STRIDE-1] + active_world[cell_off+STRIDE] + active_world[cell_off+STRIDE+1]
}
}
}

0 comments on commit 0eac04c

Please sign in to comment.