From 723ab54f97437ba865a26dfc7c3649800d023015 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 5 Nov 2023 16:39:36 +0100 Subject: [PATCH] optimized all circle routines a little more. Added gfx2/monogfx safe_circle and safe_disc. Warning for when on const value. --- compiler/res/prog8lib/c64/graphics.p8 | 23 +-- compiler/res/prog8lib/cx16/gfx2.p8 | 141 +++++++++++++++-- compiler/res/prog8lib/cx16/graphics.p8 | 27 +++- compiler/res/prog8lib/cx16/monogfx.p8 | 141 +++++++++++++++-- compiler/res/prog8lib/virtual/monogfx.p8 | 142 ++++++++++++++++-- .../compiler/astprocessing/AstChecker.kt | 3 + docs/source/todo.rst | 4 +- examples/line-circle-txt.p8 | 40 ++--- examples/test.p8 | 33 ++-- 9 files changed, 452 insertions(+), 102 deletions(-) diff --git a/compiler/res/prog8lib/c64/graphics.p8 b/compiler/res/prog8lib/c64/graphics.p8 index 698a7df69..d31f6a87e 100644 --- a/compiler/res/prog8lib/c64/graphics.p8 +++ b/compiler/res/prog8lib/c64/graphics.p8 @@ -1,6 +1,9 @@ ; bitmap pixel graphics module for the C64 ; only black/white monochrome 320x200 for now ; +; 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! +; ; Sets character matrix and bitmap screen memory at a higher memory location $5c00-$7fff ; so that the program itself can be larger without starting to overwrite the graphics memory. @@ -244,7 +247,8 @@ hline_zero2 } sub circle(uword xcenter, ubyte ycenter, ubyte radius) { - ; Midpoint algorithm + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. + ; Midpoint algorithm. if radius==0 return ubyte @zp ploty @@ -273,16 +277,17 @@ hline_zero2 internal_plotx = xcenter - yy internal_plot(ploty) yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { radius-- - decisionOver2 += (yy as word -radius)*2+1 + decisionOver2 -= radius*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ } } sub disc(uword xcenter, ubyte ycenter, ubyte radius) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. ; Midpoint algorithm, filled if radius==0 return @@ -295,12 +300,12 @@ hline_zero2 horizontal_line(xcenter-yy, ycenter+radius, yy*2+1) horizontal_line(xcenter-yy, ycenter-radius, yy*2+1) yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { radius-- - decisionOver2 += (yy as word -radius)*2+1 + decisionOver2 -= radius*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ } } diff --git a/compiler/res/prog8lib/cx16/gfx2.p8 b/compiler/res/prog8lib/cx16/gfx2.p8 index 4520fd41f..91c2a5db6 100644 --- a/compiler/res/prog8lib/cx16/gfx2.p8 +++ b/compiler/res/prog8lib/cx16/gfx2.p8 @@ -10,6 +10,9 @@ ; If you're memory constrained you should probably not use this built-in library, ; but make a copy in your project only containing the code for the required resolution. ; +; 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! +; ; ; SCREEN MODE LIST: ; mode 0 = reset back to default text mode @@ -203,6 +206,24 @@ gfx2 { } } + sub safe_horizontal_line(uword xx, uword yy, uword length, bool draw) { + ; does bounds checking and clipping + if msb(yy)&$80!=0 or yy>=height + return + if msb(xx)&$80!=0 { + length += xx + xx = 0 + } + if xx>=width + return + if xx+length>width + length = width-xx + if length>width + return + + horizontal_line(xx, yy, length, draw) + } + sub vertical_line(uword xx, uword yy, uword lheight, ubyte color) { when active_mode { 1 -> { @@ -350,6 +371,7 @@ gfx2 { } sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, ubyte color) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. ; Midpoint algorithm. if radius==0 return @@ -363,36 +385,91 @@ gfx2 { while xx>=yy { cx16.r14 = xcenter + xx cx16.r15 = ycenter + yy - plot(cx16.r14, cx16.r15, color) + plotq() cx16.r14 = xcenter - xx - plot(cx16.r14, cx16.r15, color) + plotq() cx16.r14 = xcenter + xx cx16.r15 = ycenter - yy - plot(cx16.r14, cx16.r15, color) + plotq() cx16.r14 = xcenter - xx - plot(cx16.r14, cx16.r15, color) + plotq() cx16.r14 = xcenter + yy cx16.r15 = ycenter + xx - plot(cx16.r14, cx16.r15, color) + plotq() cx16.r14 = xcenter - yy - plot(cx16.r14, cx16.r15, color) + plotq() cx16.r14 = xcenter + yy cx16.r15 = ycenter - xx - plot(cx16.r14, cx16.r15, color) + plotq() cx16.r14 = xcenter - yy - plot(cx16.r14, cx16.r15, color) + plotq() yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { xx-- - decisionOver2 += (yy as word -xx)*2+1 + decisionOver2 -= xx*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ + } + + sub plotq() { + ; cx16.r14 = x, cx16.r15 = y, color=color. + plot(cx16.r14, cx16.r15, color) + } + } + + sub safe_circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, ubyte color) { + ; This version does bounds checks and clipping, but is a lot slower. + ; Midpoint algorithm. + if radius==0 + return + + ubyte @zp xx = radius + ubyte @zp yy = 0 + word @zp decisionOver2 = (1 as word)-xx + ; R14 = internal plot X + ; R15 = internal plot Y + + while xx>=yy { + cx16.r14 = xcenter + xx + cx16.r15 = ycenter + yy + plotq() + cx16.r14 = xcenter - xx + plotq() + cx16.r14 = xcenter + xx + cx16.r15 = ycenter - yy + plotq() + cx16.r14 = xcenter - xx + plotq() + cx16.r14 = xcenter + yy + cx16.r15 = ycenter + xx + plotq() + cx16.r14 = xcenter - yy + plotq() + cx16.r14 = xcenter + yy + cx16.r15 = ycenter - xx + plotq() + cx16.r14 = xcenter - yy + plotq() + + yy++ + if decisionOver2>=0 { + xx-- + decisionOver2 -= xx*$0002 + } + decisionOver2 += yy*$0002 + decisionOver2++ + } + + sub plotq() { + ; cx16.r14 = x, cx16.r15 = y, color=color. + safe_plot(cx16.r14, cx16.r15, color) } } sub disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, ubyte color) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. ; Midpoint algorithm, filled if radius==0 return @@ -405,12 +482,35 @@ gfx2 { horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, color) horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, color) yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { radius-- - decisionOver2 += (yy as word -radius)*2+1 + decisionOver2 -= radius*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ + } + } + + sub safe_disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, ubyte color) { + ; This version does bounds checks and clipping, but is a lot slower. + ; Midpoint algorithm, filled + if radius==0 + return + ubyte @zp yy = 0 + word @zp decisionOver2 = (1 as word)-radius + + while radius>=yy { + safe_horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, color) + safe_horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, color) + safe_horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, color) + safe_horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, color) + yy++ + if decisionOver2>=0 { + radius-- + decisionOver2 -= radius*$0002 + } + decisionOver2 += yy*$0002 + decisionOver2++ } } @@ -467,6 +567,15 @@ gfx2 { } } + sub safe_plot(uword xx, uword yy, ubyte color) { + ; A plot that does bounds checks to see if the pixel is inside the screen. + if msb(xx)&$80!=0 or msb(yy)&$80!=0 + return + if xx >= width or yy >= height + return + plot(xx, yy, color) + } + sub pget(uword @zp xx, uword yy) -> ubyte { when active_mode { 1 -> { diff --git a/compiler/res/prog8lib/cx16/graphics.p8 b/compiler/res/prog8lib/cx16/graphics.p8 index a424ab184..b0bdf469f 100644 --- a/compiler/res/prog8lib/cx16/graphics.p8 +++ b/compiler/res/prog8lib/cx16/graphics.p8 @@ -7,6 +7,10 @@ ; Unlike graphics module on the C64, you can use colors() to set new drawing colors for every draw operation. ; For other resolutions or other color modes, use the "gfx2" or "monogfx" module instead. (which is Cx16-specific) ; Note: there is no color palette manipulation here, you have to do that yourself or use the "palette" module. +; +; 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! +; graphics { @@ -69,6 +73,8 @@ graphics { } sub circle(uword xcenter, ubyte ycenter, ubyte radius) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. + ;cx16.r0 = xcenter - radius/2 ;cx16.r1 = ycenter - radius/2 ;cx16.r2 = radius*2 @@ -111,17 +117,21 @@ graphics { cx16.r0 = xcenter - yy cx16.FB_cursor_position2() cx16.FB_set_pixel(stroke_color) + yy++ - if decisionOver2<=0 { - decisionOver2 += (yy as word)*2+1 - } else { + if decisionOver2>=0 { xx-- - decisionOver2 += (yy as word -xx)*2+1 + decisionOver2 -= xx*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ } } sub disc(uword xcenter, ubyte ycenter, ubyte radius) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. + ; Midpoint algorithm, filled + if radius==0 return ubyte @zp yy = 0 @@ -132,13 +142,14 @@ graphics { horizontal_line(xcenter-radius, ycenter-yy, radius*2+1) horizontal_line(xcenter-yy, ycenter+radius, yy*2+1) horizontal_line(xcenter-yy, ycenter-radius, yy*2+1) + yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { radius-- - decisionOver2 += (yy as word -radius)*2+1 + decisionOver2 -= radius*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ } } diff --git a/compiler/res/prog8lib/cx16/monogfx.p8 b/compiler/res/prog8lib/cx16/monogfx.p8 index 92257c2f1..e1e6c3069 100644 --- a/compiler/res/prog8lib/cx16/monogfx.p8 +++ b/compiler/res/prog8lib/cx16/monogfx.p8 @@ -5,6 +5,9 @@ ; For color bitmap graphics, see the gfx2 library. ; ; NOTE: a lot of the code here is similar or the same to that in gfx2 +; 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! +; monogfx { @@ -229,6 +232,24 @@ _done cx16.VERA_ADDR_H &= %00000111 ; vera auto-increment off again } + sub safe_horizontal_line(uword xx, uword yy, uword length, bool draw) { + ; does bounds checking and clipping + if msb(yy)&$80!=0 or yy>=height + return + if msb(xx)&$80!=0 { + length += xx + xx = 0 + } + if xx>=width + return + if xx+length>width + length = width-xx + if length>width + return + + horizontal_line(xx, yy, length, draw) + } + sub vertical_line(uword xx, uword yy, uword lheight, bool draw) { cx16.r15L = monogfx.plot.maskbits[xx as ubyte & 7] ; bitmask if draw { @@ -385,6 +406,7 @@ _done } sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, bool draw) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. ; Midpoint algorithm. if radius==0 return @@ -398,36 +420,91 @@ _done while xx>=yy { cx16.r14 = xcenter + xx cx16.r15 = ycenter + yy - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter + xx cx16.r15 = ycenter - yy - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter + yy cx16.r15 = ycenter + xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - yy - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter + yy cx16.r15 = ycenter - xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - yy - plot(cx16.r14, cx16.r15, draw) + plotq() yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { xx-- - decisionOver2 += (yy as word -xx)*2+1 + decisionOver2 -= xx*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ + } + + sub plotq() { + ; cx16.r14 = x, cx16.r15 = y, draw=draw + plot(cx16.r14, cx16.r15, draw) + } + } + + sub safe_circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, bool draw) { + ; Does bounds checking and clipping. + ; Midpoint algorithm. + if radius==0 + return + + ubyte @zp xx = radius + ubyte @zp yy = 0 + word @zp decisionOver2 = (1 as word)-xx + ; R14 = internal plot X + ; R15 = internal plot Y + + while xx>=yy { + cx16.r14 = xcenter + xx + cx16.r15 = ycenter + yy + plotq() + cx16.r14 = xcenter - xx + plotq() + cx16.r14 = xcenter + xx + cx16.r15 = ycenter - yy + plotq() + cx16.r14 = xcenter - xx + plotq() + cx16.r14 = xcenter + yy + cx16.r15 = ycenter + xx + plotq() + cx16.r14 = xcenter - yy + plotq() + cx16.r14 = xcenter + yy + cx16.r15 = ycenter - xx + plotq() + cx16.r14 = xcenter - yy + plotq() + + yy++ + if decisionOver2>=0 { + xx-- + decisionOver2 -= xx*$0002 + } + decisionOver2 += yy*$0002 + decisionOver2++ + } + + sub plotq() { + ; cx16.r14 = x, cx16.r15 = y, draw=draw + safe_plot(cx16.r14, cx16.r15, draw) } } sub disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. ; Midpoint algorithm, filled if radius==0 return @@ -440,12 +517,35 @@ _done horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, draw) horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw) yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { radius-- - decisionOver2 += (yy as word -radius)*2+1 + decisionOver2 -= radius*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ + } + } + + sub safe_disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) { + ; Does bounds checking and clipping. + ; Midpoint algorithm, filled + if radius==0 + return + ubyte @zp yy = 0 + word @zp decisionOver2 = (1 as word)-radius + + while radius>=yy { + safe_horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, draw) + safe_horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, draw) + safe_horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, draw) + safe_horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw) + yy++ + if decisionOver2>=0 { + radius-- + decisionOver2 -= radius*$0002 + } + decisionOver2 += yy*$0002 + decisionOver2++ } } @@ -497,6 +597,15 @@ _done } } + sub safe_plot(uword xx, uword yy, bool draw) { + ; A plot that does bounds checks to see if the pixel is inside the screen. + if msb(xx)&$80!=0 or msb(yy)&$80!=0 + return + if xx >= width or yy >= height + return + plot(xx, yy, draw) + } + sub pget(uword @zp xx, uword yy) -> ubyte { %asm {{ lda xx diff --git a/compiler/res/prog8lib/virtual/monogfx.p8 b/compiler/res/prog8lib/virtual/monogfx.p8 index 1bcf1446a..b1f7cbd40 100644 --- a/compiler/res/prog8lib/virtual/monogfx.p8 +++ b/compiler/res/prog8lib/virtual/monogfx.p8 @@ -1,5 +1,9 @@ ; Monochrome Bitmap pixel graphics routines for the Virtual Machine ; Using the full-screen 640x480 and 320x240 screen modes, but just black/white. +; +; 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! + monogfx { @@ -74,6 +78,24 @@ monogfx { plot(xpos, yy, color) } + sub safe_horizontal_line(uword xx, uword yy, uword length, bool draw) { + ; does bounds checking and clipping + if msb(yy)&$80!=0 or yy>=height + return + if msb(xx)&$80!=0 { + length += xx + xx = 0 + } + if xx>=width + return + if xx+length>width + length = width-xx + if length>width + return + + horizontal_line(xx, yy, length, draw) + } + sub vertical_line(uword xx, uword yy, uword lheight, bool draw) { ubyte color = 0 if draw @@ -176,6 +198,7 @@ monogfx { } sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, bool draw) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. ; Midpoint algorithm. if radius==0 return @@ -189,36 +212,91 @@ monogfx { while xx>=yy { cx16.r14 = xcenter + xx cx16.r15 = ycenter + yy - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter + xx cx16.r15 = ycenter - yy - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter + yy cx16.r15 = ycenter + xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - yy - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter + yy cx16.r15 = ycenter - xx - plot(cx16.r14, cx16.r15, draw) + plotq() cx16.r14 = xcenter - yy - plot(cx16.r14, cx16.r15, draw) + plotq() yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { xx-- - decisionOver2 += (yy as word -xx)*2+1 + decisionOver2 -= xx*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ + } + + sub plotq() { + ; cx16.r14 = x, cx16.r15 = y, draw=draw + plot(cx16.r14, cx16.r15, draw) + } + } + + sub safe_circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, bool draw) { + ; Does bounds checking and clipping. + ; Midpoint algorithm. + if radius==0 + return + + ubyte @zp xx = radius + ubyte @zp yy = 0 + word @zp decisionOver2 = (1 as word)-xx + ; R14 = internal plot X + ; R15 = internal plot Y + + while xx>=yy { + cx16.r14 = xcenter + xx + cx16.r15 = ycenter + yy + plotq() + cx16.r14 = xcenter - xx + plotq() + cx16.r14 = xcenter + xx + cx16.r15 = ycenter - yy + plotq() + cx16.r14 = xcenter - xx + plotq() + cx16.r14 = xcenter + yy + cx16.r15 = ycenter + xx + plotq() + cx16.r14 = xcenter - yy + plotq() + cx16.r14 = xcenter + yy + cx16.r15 = ycenter - xx + plotq() + cx16.r14 = xcenter - yy + plotq() + + yy++ + if decisionOver2>=0 { + xx-- + decisionOver2 -= xx*$0002 + } + decisionOver2 += yy*$0002 + decisionOver2++ + } + + sub plotq() { + ; cx16.r14 = x, cx16.r15 = y, draw=draw + safe_plot(cx16.r14, cx16.r15, draw) } } sub disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. ; Midpoint algorithm, filled if radius==0 return @@ -231,12 +309,35 @@ monogfx { horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, draw) horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw) yy++ - if decisionOver2<=0 - decisionOver2 += (yy as word)*2+1 - else { + if decisionOver2>=0 { radius-- - decisionOver2 += (yy as word -radius)*2+1 + decisionOver2 -= radius*$0002 } + decisionOver2 += yy*$0002 + decisionOver2++ + } + } + + sub safe_disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) { + ; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen. + ; Midpoint algorithm, filled + if radius==0 + return + ubyte @zp yy = 0 + word @zp decisionOver2 = (1 as word)-radius + + while radius>=yy { + safe_horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, draw) + safe_horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, draw) + safe_horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, draw) + safe_horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw) + yy++ + if decisionOver2>=0 { + radius-- + decisionOver2 -= radius*$0002 + } + decisionOver2 += yy*$0002 + decisionOver2++ } } @@ -255,6 +356,15 @@ monogfx { sys.gfx_plot(xx, yy, 0) } + sub safe_plot(uword xx, uword yy, bool draw) { + ; A plot that does bounds checks to see if the pixel is inside the screen. + if msb(xx)&$80!=0 or msb(yy)&$80!=0 + return + if xx >= width or yy >= height + return + plot(xx, yy, draw) + } + sub pget(uword @zp xx, uword yy) -> ubyte { return sys.gfx_getpixel(xx, yy) } diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 1a845cdd5..c0486b1f5 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -1348,6 +1348,9 @@ internal class AstChecker(private val program: Program, if(whenStmt.choices.isEmpty()) errors.err("empty when statement", whenStmt.position) + if(whenStmt.condition.constValue(program)!=null) + errors.warn("when-value is a constant and will always result in the same choice", whenStmt.condition.position) + super.visit(whenStmt) } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 377082c14..388c9bda6 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,10 +1,8 @@ TODO ==== -- is Jesko's circle algorithm faster than what we have now? https://en.wikipedia.org/wiki/Midpoint_circle_algorithm#Jesko's_Method - is it Correct??? Or better to use Casey's algorithm? +- optimize when in case of constant value (only keep choice that matches) - revisit the seek example to see if write-seeking now works? - - remove unused interned strings in the resulting code (for example from removed if/else blocks) - [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... - [on branch: ir-less-branch-opcodes] IR: reduce the number of branch instructions such as BEQ, BEQR, etc (gradually), replace with CMP(I) + status branch instruction diff --git a/examples/line-circle-txt.p8 b/examples/line-circle-txt.p8 index 621f7e882..f28e45bde 100644 --- a/examples/line-circle-txt.p8 +++ b/examples/line-circle-txt.p8 @@ -61,21 +61,21 @@ main { byte decisionOver2 = 1-x as byte while x>=y { - txt.setcc(xcenter + x, ycenter + y as ubyte, 81, 1) - txt.setcc(xcenter - x, ycenter + y as ubyte, 81, 2) - txt.setcc(xcenter + x, ycenter - y as ubyte, 81, 3) - txt.setcc(xcenter - x, ycenter - y as ubyte, 81, 4) - txt.setcc(xcenter + y, ycenter + x as ubyte, 81, 5) - txt.setcc(xcenter - y, ycenter + x as ubyte, 81, 6) - txt.setcc(xcenter + y, ycenter - x as ubyte, 81, 7) - txt.setcc(xcenter - y, ycenter - x as ubyte, 81, 8) + txt.setcc(xcenter + x, ycenter + y, 81, 1) + txt.setcc(xcenter - x, ycenter + y, 81, 2) + txt.setcc(xcenter + x, ycenter - y, 81, 3) + txt.setcc(xcenter - x, ycenter - y, 81, 4) + txt.setcc(xcenter + y, ycenter + x, 81, 5) + txt.setcc(xcenter - y, ycenter + x, 81, 6) + txt.setcc(xcenter + y, ycenter - x, 81, 7) + txt.setcc(xcenter - y, ycenter - x, 81, 8) y++ - if decisionOver2<=0 - decisionOver2 += 2*y+1 - else { + if decisionOver2>=0 { x-- - decisionOver2 += 2*(y-x)+1 + decisionOver2 -= 2*x } + decisionOver2 += 2*y + decisionOver2++ } } @@ -89,23 +89,23 @@ main { while x>=y { xx = cx-x repeat 2*x+1 { - txt.setcc(xx, cy + y as ubyte, 81, 11) - txt.setcc(xx, cy - y as ubyte, 81, 12) + txt.setcc(xx, cy + y, 81, 11) + txt.setcc(xx, cy - y, 81, 12) xx++ } xx = cx-y repeat 2*y+1 { - txt.setcc(xx, cy + x as ubyte, 81, 13) - txt.setcc(xx, cy - x as ubyte, 81, 14) + txt.setcc(xx, cy + x, 81, 13) + txt.setcc(xx, cy - x, 81, 14) xx++ } y++ - if decisionOver2<=0 - decisionOver2 += 2*y+1 - else { + if decisionOver2>=0 { x-- - decisionOver2 += 2*(y-x)+1 + decisionOver2 -= 2*x } + decisionOver2 += 2*y + decisionOver2++ } } } diff --git a/examples/test.p8 b/examples/test.p8 index 2320e386b..f60fec790 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,22 +1,27 @@ -%zeropage basicsafe +%import gfx2 main { - - sub pget(uword x, uword y) -> ubyte { - return lsb(x+y) - } - sub start() { + gfx2.screen_mode(2) - word xx - word x2 - word yy + gfx2.safe_circle(120, 140, 200, 1) + sys.wait(30) + gfx2.safe_circle(520, 140, 200, 1) + sys.wait(30) + gfx2.safe_circle(120, 340, 200, 1) + sys.wait(30) + gfx2.safe_circle(520, 340, 200, 1) + sys.wait(30) - if xx <= x2 and pget(xx as uword, yy as uword) == cx16.r11L - xx++ + gfx2.safe_disc(120, 140, 200, 1) + sys.wait(30) + gfx2.safe_disc(520, 140, 200, 1) + sys.wait(30) + gfx2.safe_disc(120, 340, 200, 1) + sys.wait(30) + gfx2.safe_disc(520, 340, 200, 1) -; if xx <= x2 -; if pget(xx as uword, yy as uword) == cx16.r11L -; xx++ + repeat { + } } }