added cx16/life.p8 example (Conway's game of life)

This commit is contained in:
Irmen de Jong 2024-09-06 01:46:22 +02:00
parent 29dd758302
commit 0eac04c220
4 changed files with 168 additions and 44 deletions

View File

@ -129,6 +129,7 @@ class TestCompilerOnExamplesCx16: FunSpec({
"highresbitmap", "highresbitmap",
"kefrenbars", "kefrenbars",
"keyboardhandler", "keyboardhandler",
"life",
"mandelbrot", "mandelbrot",
"multi-irq-old", "multi-irq-old",
"multi-irq-new", "multi-irq-new",

View File

@ -1,6 +1,24 @@
TODO 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: 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 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!) in overwriting registers that already got their value, which requires a lot of stack juggling (especially on plain 6502 cpu!)

139
examples/cx16/life.p8 Normal file
View File

@ -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
}
}

View File

@ -4,50 +4,16 @@
main { main {
sub start() { sub start() {
for cx16.r0L in 5 to 5 { uword active_world = memory("world", 80*50, 0)
txt.print("derp0.") uword cell_off = 500
txt.print_ub(cx16.r0L) const uword STRIDE = 40
txt.nl() sys.memset(active_world, 80*50, 1)
} txt.print_ub(count()) ; TODO prints 1, must be 8
for cx16.r0L in 100 downto 100 {
txt.print("derp1.") sub count() -> ubyte {
txt.print_ub(cx16.r0L) return active_world[cell_off-STRIDE-1] + active_world[cell_off-STRIDE] + active_world[cell_off-STRIDE+1] +
txt.nl() 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]
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()
} }
} }
} }