diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index c986c4870..6745d03b9 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -129,6 +129,7 @@ class TestCompilerOnExamplesCx16: FunSpec({ "highresbitmap", "kefrenbars", "keyboardhandler", + "life", "mandelbrot", "multi-irq-old", "multi-irq-new", diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 6970397ea..e004e1f1c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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!) diff --git a/examples/cx16/life.p8 b/examples/cx16/life.p8 new file mode 100644 index 000000000..8eaaf30d1 --- /dev/null +++ b/examples/cx16/life.p8 @@ -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 + } +} diff --git a/examples/test.p8 b/examples/test.p8 index cea274579..9616cea82 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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] } } }