diff --git a/compiler/res/prog8lib/cx16/gfx_hires.p8 b/compiler/res/prog8lib/cx16/gfx_hires.p8 index 7a598f5e3..78fd73040 100644 --- a/compiler/res/prog8lib/cx16/gfx_hires.p8 +++ b/compiler/res/prog8lib/cx16/gfx_hires.p8 @@ -12,6 +12,8 @@ ; This is compatible with the CX16's screen mode 128. (void cx16.set_screen_mode(128)) ; +%import buffers + gfx_hires { %option ignore_unused @@ -574,7 +576,7 @@ gfx_hires { }} } - sub fill(uword x, uword y, ubyte new_color) { + sub fill(uword x, uword y, ubyte new_color, ubyte stack_rambank) { ; reuse a few virtual registers in ZP for variables &ubyte fillm = &cx16.r7L &ubyte seedm = &cx16.r8L @@ -586,75 +588,28 @@ gfx_hires { ; Non-recursive scanline flood fill. ; based loosely on code found here https://www.codeproject.com/Articles/6017/QuickFill-An-efficient-flood-fill-algorithm ; with the fixes applied to the seedfill_4 routine as mentioned in the comments. - const ubyte MAXDEPTH = 100 word @zp xx = x as word word @zp yy = y as word - word[MAXDEPTH] @split @shared stack_xl - word[MAXDEPTH] @split @shared stack_xr - word[MAXDEPTH] @split @shared stack_y - byte[MAXDEPTH] @shared stack_dy - cx16.r12L = 0 ; stack pointer word x1 word x2 byte dy cx16.r10L = new_color + stack.init(stack_rambank) sub push_stack(word sxl, word sxr, word sy, byte sdy) { - if cx16.r12L==MAXDEPTH - return cx16.r0s = sy+sdy if cx16.r0s>=0 and cx16.r0s<=HEIGHT-1 { -;; stack_xl[cx16.r12L] = sxl -;; stack_xr[cx16.r12L] = sxr -;; stack_y[cx16.r12L] = sy -;; stack_dy[cx16.r12L] = sdy -;; cx16.r12L++ - %asm {{ - ldy cx16.r12L - lda p8v_sxl - sta p8v_stack_xl_lsb,y - lda p8v_sxl+1 - sta p8v_stack_xl_msb,y - lda p8v_sxr - sta p8v_stack_xr_lsb,y - lda p8v_sxr+1 - sta p8v_stack_xr_msb,y - lda p8v_sy - sta p8v_stack_y_lsb,y - lda p8v_sy+1 - sta p8v_stack_y_msb,y - ldy cx16.r12L - lda p8v_sdy - sta p8v_stack_dy,y - inc cx16.r12L - }} + stack.pushw(sxl as uword) + stack.pushw(sxr as uword) + stack.pushw(sy as uword) + stack.push(sdy as ubyte) } } sub pop_stack() { -;; cx16.r12L-- -;; x1 = stack_xl[cx16.r12L] -;; x2 = stack_xr[cx16.r12L] -;; y = stack_y[cx16.r12L] -;; dy = stack_dy[cx16.r12L] - %asm {{ - dec cx16.r12L - ldy cx16.r12L - lda p8v_stack_xl_lsb,y - sta p8v_x1 - lda p8v_stack_xl_msb,y - sta p8v_x1+1 - lda p8v_stack_xr_lsb,y - sta p8v_x2 - lda p8v_stack_xr_msb,y - sta p8v_x2+1 - lda p8v_stack_y_lsb,y - sta p8v_yy - lda p8v_stack_y_msb,y - sta p8v_yy+1 - ldy cx16.r12L - lda p8v_stack_dy,y - sta p8v_dy - }} + dy = stack.pop() as byte + yy = stack.popw() as word + x2 = stack.popw() as word + x1 = stack.popw() as word yy+=dy } cx16.r11L = pget(xx as uword, yy as uword) ; old_color @@ -666,7 +621,7 @@ gfx_hires { push_stack(xx, xx, yy, 1) push_stack(xx, xx, yy + 1, -1) word left = 0 - while cx16.r12L!=0 { + while not stack.isempty() { pop_stack() xx = x1 if fill_scanline_left_2bpp() goto skip diff --git a/compiler/res/prog8lib/cx16/gfx_lores.p8 b/compiler/res/prog8lib/cx16/gfx_lores.p8 index 7a3556b8d..cf82cd78f 100644 --- a/compiler/res/prog8lib/cx16/gfx_lores.p8 +++ b/compiler/res/prog8lib/cx16/gfx_lores.p8 @@ -5,6 +5,7 @@ %import syslib %import verafx +%import buffers gfx_lores { %option ignore_unused @@ -627,7 +628,7 @@ gfx_lores { }} } - sub fill(uword x, ubyte y, ubyte new_color) { + sub fill(uword x, ubyte y, ubyte new_color, ubyte stack_rambank) { ; reuse a few virtual registers in ZP for variables &ubyte fillm = &cx16.r7L &ubyte seedm = &cx16.r8L @@ -639,75 +640,28 @@ gfx_lores { ; Non-recursive scanline flood fill. ; based loosely on code found here https://www.codeproject.com/Articles/6017/QuickFill-An-efficient-flood-fill-algorithm ; with the fixes applied to the seedfill_4 routine as mentioned in the comments. - const ubyte MAXDEPTH = 100 word @zp xx = x as word word @zp yy = y as word - word[MAXDEPTH] @split @shared stack_xl - word[MAXDEPTH] @split @shared stack_xr - word[MAXDEPTH] @split @shared stack_y - byte[MAXDEPTH] @shared stack_dy - cx16.r12L = 0 ; stack pointer word x1 word x2 byte dy cx16.r10L = new_color + stack.init(stack_rambank) sub push_stack(word sxl, word sxr, word sy, byte sdy) { - if cx16.r12L==MAXDEPTH - return cx16.r0s = sy+sdy if cx16.r0s>=0 and cx16.r0s<=HEIGHT-1 { -;; stack_xl[cx16.r12L] = sxl -;; stack_xr[cx16.r12L] = sxr -;; stack_y[cx16.r12L] = sy -;; stack_dy[cx16.r12L] = sdy -;; cx16.r12L++ - %asm {{ - ldy cx16.r12L - lda p8v_sxl - sta p8v_stack_xl_lsb,y - lda p8v_sxl+1 - sta p8v_stack_xl_msb,y - lda p8v_sxr - sta p8v_stack_xr_lsb,y - lda p8v_sxr+1 - sta p8v_stack_xr_msb,y - lda p8v_sy - sta p8v_stack_y_lsb,y - lda p8v_sy+1 - sta p8v_stack_y_msb,y - ldy cx16.r12L - lda p8v_sdy - sta p8v_stack_dy,y - inc cx16.r12L - }} + stack.pushw(sxl as uword) + stack.pushw(sxr as uword) + stack.pushw(sy as uword) + stack.push(sdy as ubyte) } } sub pop_stack() { -;; cx16.r12L-- -;; x1 = stack_xl[cx16.r12L] -;; x2 = stack_xr[cx16.r12L] -;; y = stack_y[cx16.r12L] -;; dy = stack_dy[cx16.r12L] - %asm {{ - dec cx16.r12L - ldy cx16.r12L - lda p8v_stack_xl_lsb,y - sta p8v_x1 - lda p8v_stack_xl_msb,y - sta p8v_x1+1 - lda p8v_stack_xr_lsb,y - sta p8v_x2 - lda p8v_stack_xr_msb,y - sta p8v_x2+1 - lda p8v_stack_y_lsb,y - sta p8v_yy - lda p8v_stack_y_msb,y - sta p8v_yy+1 - ldy cx16.r12L - lda p8v_stack_dy,y - sta p8v_dy - }} + dy = stack.pop() as byte + yy = stack.popw() as word + x2 = stack.popw() as word + x1 = stack.popw() as word yy+=dy } cx16.r11L = pget(xx as uword, lsb(yy)) ; old_color @@ -718,7 +672,7 @@ gfx_lores { push_stack(xx, xx, yy, 1) push_stack(xx, xx, yy + 1, -1) word left = 0 - while cx16.r12L!=0 { + while not stack.isempty() { pop_stack() xx = x1 if fill_scanline_left_8bpp() goto skip diff --git a/compiler/res/prog8lib/cx16/monogfx.p8 b/compiler/res/prog8lib/cx16/monogfx.p8 index 0f83bdabe..2fcfc9daf 100644 --- a/compiler/res/prog8lib/cx16/monogfx.p8 +++ b/compiler/res/prog8lib/cx16/monogfx.p8 @@ -7,6 +7,8 @@ ; NOTE: For sake of speed, NO BOUNDS CHECKING is performed in most routines! ; You'll have to make sure yourself that you're not writing outside of bitmap boundaries! +%import buffers + monogfx { %option ignore_unused @@ -733,78 +735,31 @@ invert: }} } - sub fill(uword x, uword y, bool draw) { + sub fill(uword x, uword y, bool draw, ubyte stack_rambank) { ; Non-recursive scanline flood fill. ; based loosely on code found here https://www.codeproject.com/Articles/6017/QuickFill-An-efficient-flood-fill-algorithm ; with the fixes applied to the seedfill_4 routine as mentioned in the comments. - const ubyte MAXDEPTH = 100 word @zp xx = x as word word @zp yy = y as word - word[MAXDEPTH] @split @shared stack_xl - word[MAXDEPTH] @split @shared stack_xr - word[MAXDEPTH] @split @shared stack_y - byte[MAXDEPTH] @shared stack_dy - cx16.r12L = 0 ; stack pointer word x1 word x2 byte dy + stack.init(stack_rambank) cx16.r10L = draw as ubyte sub push_stack(word sxl, word sxr, word sy, byte sdy) { - if cx16.r12L==MAXDEPTH - return cx16.r0s = sy+sdy if cx16.r0s>=0 and cx16.r0s<=height-1 { -;; stack_xl[cx16.r12L] = sxl -;; stack_xr[cx16.r12L] = sxr -;; stack_y[cx16.r12L] = sy -;; stack_dy[cx16.r12L] = sdy -;; cx16.r12L++ - %asm {{ - ldy cx16.r12L - lda p8v_sxl - sta p8v_stack_xl_lsb,y - lda p8v_sxl+1 - sta p8v_stack_xl_msb,y - lda p8v_sxr - sta p8v_stack_xr_lsb,y - lda p8v_sxr+1 - sta p8v_stack_xr_msb,y - lda p8v_sy - sta p8v_stack_y_lsb,y - lda p8v_sy+1 - sta p8v_stack_y_msb,y - ldy cx16.r12L - lda p8v_sdy - sta p8v_stack_dy,y - inc cx16.r12L - }} + stack.pushw(sxl as uword) + stack.pushw(sxr as uword) + stack.pushw(sy as uword) + stack.push(sdy as ubyte) } } sub pop_stack() { -;; cx16.r12L-- -;; x1 = stack_xl[cx16.r12L] -;; x2 = stack_xr[cx16.r12L] -;; y = stack_y[cx16.r12L] -;; dy = stack_dy[cx16.r12L] - %asm {{ - dec cx16.r12L - ldy cx16.r12L - lda p8v_stack_xl_lsb,y - sta p8v_x1 - lda p8v_stack_xl_msb,y - sta p8v_x1+1 - lda p8v_stack_xr_lsb,y - sta p8v_x2 - lda p8v_stack_xr_msb,y - sta p8v_x2+1 - lda p8v_stack_y_lsb,y - sta p8v_yy - lda p8v_stack_y_msb,y - sta p8v_yy+1 - ldy cx16.r12L - lda p8v_stack_dy,y - sta p8v_dy - }} + dy = stack.pop() as byte + yy = stack.popw() as word + x2 = stack.popw() as word + x1 = stack.popw() as word yy+=dy } cx16.r11L = pget(xx as uword, yy as uword) as ubyte ; old_color @@ -815,7 +770,7 @@ invert: push_stack(xx, xx, yy, 1) push_stack(xx, xx, yy + 1, -1) word left = 0 - while cx16.r12L!=0 { + while not stack.isempty() { pop_stack() xx = x1 if fill_scanline_left() goto skip diff --git a/compiler/res/prog8lib/virtual/monogfx.p8 b/compiler/res/prog8lib/virtual/monogfx.p8 index 811154ee3..a29c293d6 100644 --- a/compiler/res/prog8lib/virtual/monogfx.p8 +++ b/compiler/res/prog8lib/virtual/monogfx.p8 @@ -4,6 +4,7 @@ ; NOTE: For sake of speed, NO BOUNDS CHECKING is performed in most routines! ; You'll have to make sure yourself that you're not writing outside of bitmap boundaries! +%import buffers monogfx { @@ -408,36 +409,27 @@ monogfx { ; Non-recursive scanline flood fill. ; based loosely on code found here https://www.codeproject.com/Articles/6017/QuickFill-An-efficient-flood-fill-algorithm ; with the fixes applied to the seedfill_4 routine as mentioned in the comments. - const ubyte MAXDEPTH = 100 word @zp xx = x as word word @zp yy = y as word - word[MAXDEPTH] @split @shared stack_xl - word[MAXDEPTH] @split @shared stack_xr - word[MAXDEPTH] @split @shared stack_y - byte[MAXDEPTH] @shared stack_dy - cx16.r12L = 0 ; stack pointer word x1 word x2 byte dy + stack.init() cx16.r10L = draw as ubyte sub push_stack(word sxl, word sxr, word sy, byte sdy) { - if cx16.r12L==MAXDEPTH - return cx16.r0s = sy+sdy if cx16.r0s>=0 and cx16.r0s<=height-1 { - stack_xl[cx16.r12L] = sxl - stack_xr[cx16.r12L] = sxr - stack_y[cx16.r12L] = sy - stack_dy[cx16.r12L] = sdy - cx16.r12L++ + stack.pushw(sxl as uword) + stack.pushw(sxr as uword) + stack.pushw(sy as uword) + stack.push(sdy as ubyte) } } sub pop_stack() { - cx16.r12L-- - x1 = stack_xl[cx16.r12L] - x2 = stack_xr[cx16.r12L] - yy = stack_y[cx16.r12L] - dy = stack_dy[cx16.r12L] + dy = stack.pop() as byte + yy = stack.popw() as word + x2 = stack.popw() as word + x1 = stack.popw() as word yy+=dy } cx16.r11L = pget(xx as uword, yy as uword) as ubyte ; old_color @@ -448,7 +440,7 @@ monogfx { push_stack(xx, xx, yy, 1) push_stack(xx, xx, yy + 1, -1) word left = 0 - while cx16.r12L!=0 { + while not stack.isempty() { pop_stack() xx = x1 while xx >= 0 { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 6bde558f6..1e7767d63 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,8 @@ TODO ==== +virtual: importing buffers in main results in a vm error? + document the @R0 - @R15 register support for normal subroutine parameters (footgun!) make a compiler switch to disable footgun warnings diff --git a/examples/cx16/test_gfx_lores.p8 b/examples/cx16/test_gfx_lores.p8 index 1778f1b8d..2ad7342b6 100644 --- a/examples/cx16/test_gfx_lores.p8 +++ b/examples/cx16/test_gfx_lores.p8 @@ -8,6 +8,8 @@ main { + const ubyte FILL_STACK_BANK = 2 + sub start() { demofill() sys.wait(120) @@ -24,9 +26,9 @@ main { gfx_lores.line(100, 150, 240, 10, 1) gfx_lores.line(101, 150, 241, 10, 1) sys.wait(60) - gfx_lores.fill(100,100,2) - gfx_lores.fill(182,140,3) - gfx_lores.fill(182,40,1) + gfx_lores.fill(100,100,2, FILL_STACK_BANK) + gfx_lores.fill(182,140,3, FILL_STACK_BANK) + gfx_lores.fill(182,40,1, FILL_STACK_BANK) } diff --git a/examples/cx16/testmonogfx.p8 b/examples/cx16/testmonogfx.p8 index 625d4f264..47b5a5a22 100644 --- a/examples/cx16/testmonogfx.p8 +++ b/examples/cx16/testmonogfx.p8 @@ -7,6 +7,7 @@ main { + const ubyte FILL_STACK_BANK = 2 sub start() { monogfx.lores() @@ -28,7 +29,7 @@ main { monogfx.line(101, 150, 241, 10, true) monogfx.drawmode(monogfx.MODE_STIPPLE) sys.wait(60) - monogfx.fill(100,100,true) + monogfx.fill(100,100,true, FILL_STACK_BANK) } sub demo1() { diff --git a/examples/test.p8 b/examples/test.p8 index a7acf4c12..5af963529 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,106 +1,66 @@ -%import textio -%import buffers +%import monogfx %option no_sysinit %zeropage basicsafe main { sub start() { - txt.print("stack\n") - test_stack() - txt.print("\nringbuffer\n") - test_ring() - txt.print("\nsmallringbuffer\n") - test_smallring() + monogfx.lores() + + uword x + for x in 128 to 319 step 40 { + monogfx.line(x, 0, x-100, 200, true) + } + for x in 32 to 200 step 40 { + monogfx.line(x, 239, x+100, 20, true) + } + monogfx.fill(310, 230, true, 44) + + sys.wait(100) } - sub test_stack() { - stack.init(2) - txt.print_uw(stack.size()) - txt.spc() - txt.print_uw(stack.free()) - txt.nl() - stack.push(1) - stack.push(2) - stack.push(3) - stack.pushw(12345) - txt.print_uw(stack.size()) - txt.spc() - txt.print_uw(stack.free()) - txt.nl() - txt.nl() - txt.print_uw(stack.popw()) - txt.nl() - txt.print_uw(stack.pop()) - txt.nl() - txt.print_uw(stack.pop()) - txt.nl() - txt.print_uw(stack.pop()) - txt.nl() - txt.nl() - txt.print_uw(stack.size()) - txt.spc() - txt.print_uw(stack.free()) - txt.nl() - } +; sub start() { +; monogfx.hires() +; +; uword x +; for x in 128 to 639 step 64 { +; monogfx.line(x, 0, x-100, 400, true) +; } +; for x in 32 to 500 step 64 { +; monogfx.line(x, 479, x+100, 100, true) +; } +; monogfx.fill(630, 440, true, 44) +; +; sys.wait(100) +; } - sub test_ring() { - ringbuffer.init(2) - txt.print_uw(ringbuffer.size()) - txt.spc() - txt.print_uw(ringbuffer.free()) - txt.nl() - ringbuffer.put(1) - ringbuffer.put(2) - ringbuffer.put(3) - ringbuffer.putw(12345) - txt.print_uw(ringbuffer.size()) - txt.spc() - txt.print_uw(ringbuffer.free()) - txt.nl() - txt.nl() - txt.print_uw(ringbuffer.get()) - txt.nl() - txt.print_uw(ringbuffer.get()) - txt.nl() - txt.print_uw(ringbuffer.get()) - txt.nl() - txt.print_uw(ringbuffer.getw()) - txt.nl() - txt.nl() - txt.print_uw(ringbuffer.size()) - txt.spc() - txt.print_uw(ringbuffer.free()) - txt.nl() - } +; sub start() { +; gfx_hires.graphics_mode() +; +; uword x +; for x in 128 to 639 step 64 { +; gfx_hires.line(x, 0, x-100, 400, 1) +; } +; for x in 32 to 500 step 64 { +; gfx_hires.line(x, 479, x+100, 100, 1) +; } +; gfx_hires.fill(630, 440, 2, 44) +; +; sys.wait(100) +; } - sub test_smallring() { - smallringbuffer.init() - txt.print_uw(smallringbuffer.size()) - txt.spc() - txt.print_uw(smallringbuffer.free()) - txt.nl() - smallringbuffer.put(1) - smallringbuffer.put(2) - smallringbuffer.put(3) - smallringbuffer.putw(12345) - txt.print_uw(smallringbuffer.size()) - txt.spc() - txt.print_uw(smallringbuffer.free()) - txt.nl() - txt.nl() - txt.print_uw(smallringbuffer.get()) - txt.nl() - txt.print_uw(smallringbuffer.get()) - txt.nl() - txt.print_uw(smallringbuffer.get()) - txt.nl() - txt.print_uw(smallringbuffer.getw()) - txt.nl() - txt.nl() - txt.print_uw(smallringbuffer.size()) - txt.spc() - txt.print_uw(smallringbuffer.free()) - txt.nl() - } +; sub start() { +; gfx_lores.graphics_mode() +; +; uword x +; for x in 128 to 319 step 40 { +; gfx_lores.line(x, 0, x-100, 200, 1) +; } +; for x in 32 to 200 step 40 { +; gfx_lores.line(x, 239, x+100, 20, 1) +; } +; gfx_lores.fill(310, 230, 2, 44) +; +; sys.wait(100) +; } }