diff --git a/compiler/res/prog8lib/cx16/gfx_lores.p8 b/compiler/res/prog8lib/cx16/gfx_lores.p8 index 1016a6606..4d82b2684 100644 --- a/compiler/res/prog8lib/cx16/gfx_lores.p8 +++ b/compiler/res/prog8lib/cx16/gfx_lores.p8 @@ -22,7 +22,34 @@ gfx_lores { sub clear_screen(ubyte color) { if verafx.available() { - verafx.clear(0, 0, color, 320*240/4) + ; use verafx cache writes to quicly clear the screen + const ubyte vbank = 0 + const uword vaddr = 0 + cx16.VERA_CTRL = 0 + cx16.VERA_ADDR_H = vbank | %00110000 ; 4-byte increment + cx16.VERA_ADDR_M = msb(vaddr) + cx16.VERA_ADDR_L = lsb(vaddr) + cx16.VERA_CTRL = 6<<1 ; dcsel = 6, fill the 32 bits cache + cx16.VERA_FX_CACHE_L = color + cx16.VERA_FX_CACHE_M = color + cx16.VERA_FX_CACHE_H = color + cx16.VERA_FX_CACHE_U = color + cx16.VERA_CTRL = 2<<1 ; dcsel = 2 + cx16.VERA_FX_MULT = 0 + cx16.VERA_FX_CTRL = %01000000 ; cache write enable + repeat 320/4/4 { + %asm {{ + ldy #240 +- stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + dey + bne - + }} + } + cx16.VERA_FX_CTRL = 0 ; cache write disable + cx16.VERA_CTRL = 0 return } ; fallback to cpu clear diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 42efd38f7..c60bc4eed 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -136,6 +136,7 @@ class TestCompilerOnExamplesCx16: FunSpec({ "multi-irq-new", "plasma", "rasterbars", + "rotating-stars", "showbmx", "snow", "spotlight", diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 3312e677b..7ec4cf162 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -4,6 +4,7 @@ TODO word starw for starw in 50 downto 0 -> compiler error word loop variable can only loop over bytes or words +fix the ubyte[] parser error. Regenerate skeleton doc files. diff --git a/examples/cx16/rotating-stars.p8 b/examples/cx16/rotating-stars.p8 new file mode 100644 index 000000000..1b981ad4c --- /dev/null +++ b/examples/cx16/rotating-stars.p8 @@ -0,0 +1,57 @@ +; Animate a rotating and zooming sprite field. +; Rather than doing complicated 3d stuff, this simply uses polar coordinates. +; Every star lies along the circle and just has a radius R. + +%import math +%import palette +%import gfx_lores +%option no_sysinit + +main { + %option verafxmuls + + sub start() { + const ubyte NUM_STARS = 128 ; must be 128 to evenly distribute (angle goes from 0..255 in steps of 2) + + ubyte[NUM_STARS] r + ubyte[NUM_STARS] speeds + uword[NUM_STARS] prev_x + ubyte[NUM_STARS] prev_y + uword angle + + gfx_lores.set_screen_mode() + + ; init the star positions + ubyte star + for star in 0 to NUM_STARS-1 { + r[star] = 4 + math.rnd()/4 + speeds[star] = (math.rnd() & 3) + 1 + } + + repeat { + sys.waitvsync() + ;; palette.set_color(0, $400) + for star in NUM_STARS-1 downto 0 { + gfx_lores.plot(prev_x[star], prev_y[star], 0) + cx16.r2L = star*2 + msb(angle) + uword sx = (msb(math.sin8(cx16.r2L) as word * r[star]) + 128) as uword + 32 + ubyte sy = (msb(math.cos8(cx16.r2L) as word * r[star]) + 120) + prev_x[star] = sx + if sy<240 { + prev_y[star] = sy + gfx_lores.plot(sx, sy, star) + } else + prev_y[star] = 0 + + r[star] += speeds[star] + if r[star] >= 255-3 { + r[star] = 4 + speeds[star] = (math.rnd() & 3) + 1 + } + } + angle += $0040 + ;; palette.set_color(0, $000) + } + } +} +