mirror of
https://github.com/irmen/prog8.git
synced 2024-09-10 09:54:32 +00:00
optimized all circle routines a little more. Added gfx2/monogfx safe_circle and safe_disc. Warning for when on const value.
This commit is contained in:
parent
d9389afc66
commit
723ab54f97
@ -1,6 +1,9 @@
|
|||||||
; bitmap pixel graphics module for the C64
|
; bitmap pixel graphics module for the C64
|
||||||
; only black/white monochrome 320x200 for now
|
; 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
|
; 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.
|
; 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) {
|
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
|
if radius==0
|
||||||
return
|
return
|
||||||
ubyte @zp ploty
|
ubyte @zp ploty
|
||||||
@ -273,16 +277,17 @@ hline_zero2
|
|||||||
internal_plotx = xcenter - yy
|
internal_plotx = xcenter - yy
|
||||||
internal_plot(ploty)
|
internal_plot(ploty)
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
radius--
|
radius--
|
||||||
decisionOver2 += (yy as word -radius)*2+1
|
decisionOver2 -= radius*$0002
|
||||||
}
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub disc(uword xcenter, ubyte ycenter, ubyte radius) {
|
sub disc(uword xcenter, ubyte ycenter, ubyte radius) {
|
||||||
|
; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen.
|
||||||
; Midpoint algorithm, filled
|
; Midpoint algorithm, filled
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
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)
|
||||||
horizontal_line(xcenter-yy, ycenter-radius, yy*2+1)
|
horizontal_line(xcenter-yy, ycenter-radius, yy*2+1)
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
radius--
|
radius--
|
||||||
decisionOver2 += (yy as word -radius)*2+1
|
decisionOver2 -= radius*$0002
|
||||||
}
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
; If you're memory constrained you should probably not use this built-in library,
|
; 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.
|
; 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:
|
; SCREEN MODE LIST:
|
||||||
; mode 0 = reset back to default text mode
|
; 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) {
|
sub vertical_line(uword xx, uword yy, uword lheight, ubyte color) {
|
||||||
when active_mode {
|
when active_mode {
|
||||||
1 -> {
|
1 -> {
|
||||||
@ -350,6 +371,7 @@ gfx2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, ubyte color) {
|
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.
|
; Midpoint algorithm.
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
return
|
||||||
@ -363,36 +385,91 @@ gfx2 {
|
|||||||
while xx>=yy {
|
while xx>=yy {
|
||||||
cx16.r14 = xcenter + xx
|
cx16.r14 = xcenter + xx
|
||||||
cx16.r15 = ycenter + yy
|
cx16.r15 = ycenter + yy
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
cx16.r14 = xcenter - xx
|
cx16.r14 = xcenter - xx
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
cx16.r14 = xcenter + xx
|
cx16.r14 = xcenter + xx
|
||||||
cx16.r15 = ycenter - yy
|
cx16.r15 = ycenter - yy
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
cx16.r14 = xcenter - xx
|
cx16.r14 = xcenter - xx
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
cx16.r14 = xcenter + yy
|
cx16.r14 = xcenter + yy
|
||||||
cx16.r15 = ycenter + xx
|
cx16.r15 = ycenter + xx
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
cx16.r14 = xcenter - yy
|
cx16.r14 = xcenter - yy
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
cx16.r14 = xcenter + yy
|
cx16.r14 = xcenter + yy
|
||||||
cx16.r15 = ycenter - xx
|
cx16.r15 = ycenter - xx
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
cx16.r14 = xcenter - yy
|
cx16.r14 = xcenter - yy
|
||||||
plot(cx16.r14, cx16.r15, color)
|
plotq()
|
||||||
|
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
xx--
|
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) {
|
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
|
; Midpoint algorithm, filled
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
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)
|
||||||
horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, color)
|
horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, color)
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
radius--
|
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 {
|
sub pget(uword @zp xx, uword yy) -> ubyte {
|
||||||
when active_mode {
|
when active_mode {
|
||||||
1 -> {
|
1 -> {
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
; Unlike graphics module on the C64, you can use colors() to set new drawing colors for every draw operation.
|
; 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)
|
; 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: 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 {
|
graphics {
|
||||||
@ -69,6 +73,8 @@ graphics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub circle(uword xcenter, ubyte ycenter, ubyte radius) {
|
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.r0 = xcenter - radius/2
|
||||||
;cx16.r1 = ycenter - radius/2
|
;cx16.r1 = ycenter - radius/2
|
||||||
;cx16.r2 = radius*2
|
;cx16.r2 = radius*2
|
||||||
@ -111,17 +117,21 @@ graphics {
|
|||||||
cx16.r0 = xcenter - yy
|
cx16.r0 = xcenter - yy
|
||||||
cx16.FB_cursor_position2()
|
cx16.FB_cursor_position2()
|
||||||
cx16.FB_set_pixel(stroke_color)
|
cx16.FB_set_pixel(stroke_color)
|
||||||
|
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0 {
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
} else {
|
|
||||||
xx--
|
xx--
|
||||||
decisionOver2 += (yy as word -xx)*2+1
|
decisionOver2 -= xx*$0002
|
||||||
}
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub disc(uword xcenter, ubyte ycenter, ubyte radius) {
|
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
|
if radius==0
|
||||||
return
|
return
|
||||||
ubyte @zp yy = 0
|
ubyte @zp yy = 0
|
||||||
@ -132,13 +142,14 @@ graphics {
|
|||||||
horizontal_line(xcenter-radius, ycenter-yy, radius*2+1)
|
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)
|
||||||
horizontal_line(xcenter-yy, ycenter-radius, yy*2+1)
|
horizontal_line(xcenter-yy, ycenter-radius, yy*2+1)
|
||||||
|
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
radius--
|
radius--
|
||||||
decisionOver2 += (yy as word -radius)*2+1
|
decisionOver2 -= radius*$0002
|
||||||
}
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
; For color bitmap graphics, see the gfx2 library.
|
; 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: 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 {
|
monogfx {
|
||||||
|
|
||||||
@ -229,6 +232,24 @@ _done
|
|||||||
cx16.VERA_ADDR_H &= %00000111 ; vera auto-increment off again
|
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) {
|
sub vertical_line(uword xx, uword yy, uword lheight, bool draw) {
|
||||||
cx16.r15L = monogfx.plot.maskbits[xx as ubyte & 7] ; bitmask
|
cx16.r15L = monogfx.plot.maskbits[xx as ubyte & 7] ; bitmask
|
||||||
if draw {
|
if draw {
|
||||||
@ -385,6 +406,7 @@ _done
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, bool draw) {
|
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.
|
; Midpoint algorithm.
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
return
|
||||||
@ -398,36 +420,91 @@ _done
|
|||||||
while xx>=yy {
|
while xx>=yy {
|
||||||
cx16.r14 = xcenter + xx
|
cx16.r14 = xcenter + xx
|
||||||
cx16.r15 = ycenter + yy
|
cx16.r15 = ycenter + yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - xx
|
cx16.r14 = xcenter - xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter + xx
|
cx16.r14 = xcenter + xx
|
||||||
cx16.r15 = ycenter - yy
|
cx16.r15 = ycenter - yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - xx
|
cx16.r14 = xcenter - xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter + yy
|
cx16.r14 = xcenter + yy
|
||||||
cx16.r15 = ycenter + xx
|
cx16.r15 = ycenter + xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - yy
|
cx16.r14 = xcenter - yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter + yy
|
cx16.r14 = xcenter + yy
|
||||||
cx16.r15 = ycenter - xx
|
cx16.r15 = ycenter - xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - yy
|
cx16.r14 = xcenter - yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
|
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
xx--
|
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) {
|
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
|
; Midpoint algorithm, filled
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
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)
|
||||||
horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw)
|
horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw)
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
radius--
|
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 {
|
sub pget(uword @zp xx, uword yy) -> ubyte {
|
||||||
%asm {{
|
%asm {{
|
||||||
lda xx
|
lda xx
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
; Monochrome Bitmap pixel graphics routines for the Virtual Machine
|
; Monochrome Bitmap pixel graphics routines for the Virtual Machine
|
||||||
; Using the full-screen 640x480 and 320x240 screen modes, but just black/white.
|
; 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 {
|
monogfx {
|
||||||
|
|
||||||
@ -74,6 +78,24 @@ monogfx {
|
|||||||
plot(xpos, yy, color)
|
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) {
|
sub vertical_line(uword xx, uword yy, uword lheight, bool draw) {
|
||||||
ubyte color = 0
|
ubyte color = 0
|
||||||
if draw
|
if draw
|
||||||
@ -176,6 +198,7 @@ monogfx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, bool draw) {
|
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.
|
; Midpoint algorithm.
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
return
|
||||||
@ -189,36 +212,91 @@ monogfx {
|
|||||||
while xx>=yy {
|
while xx>=yy {
|
||||||
cx16.r14 = xcenter + xx
|
cx16.r14 = xcenter + xx
|
||||||
cx16.r15 = ycenter + yy
|
cx16.r15 = ycenter + yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - xx
|
cx16.r14 = xcenter - xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter + xx
|
cx16.r14 = xcenter + xx
|
||||||
cx16.r15 = ycenter - yy
|
cx16.r15 = ycenter - yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - xx
|
cx16.r14 = xcenter - xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter + yy
|
cx16.r14 = xcenter + yy
|
||||||
cx16.r15 = ycenter + xx
|
cx16.r15 = ycenter + xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - yy
|
cx16.r14 = xcenter - yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter + yy
|
cx16.r14 = xcenter + yy
|
||||||
cx16.r15 = ycenter - xx
|
cx16.r15 = ycenter - xx
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
cx16.r14 = xcenter - yy
|
cx16.r14 = xcenter - yy
|
||||||
plot(cx16.r14, cx16.r15, draw)
|
plotq()
|
||||||
|
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
xx--
|
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) {
|
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
|
; Midpoint algorithm, filled
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
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)
|
||||||
horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw)
|
horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw)
|
||||||
yy++
|
yy++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += (yy as word)*2+1
|
|
||||||
else {
|
|
||||||
radius--
|
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)
|
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 {
|
sub pget(uword @zp xx, uword yy) -> ubyte {
|
||||||
return sys.gfx_getpixel(xx, yy)
|
return sys.gfx_getpixel(xx, yy)
|
||||||
}
|
}
|
||||||
|
@ -1348,6 +1348,9 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(whenStmt.choices.isEmpty())
|
if(whenStmt.choices.isEmpty())
|
||||||
errors.err("empty when statement", whenStmt.position)
|
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)
|
super.visit(whenStmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- is Jesko's circle algorithm faster than what we have now? https://en.wikipedia.org/wiki/Midpoint_circle_algorithm#Jesko's_Method
|
- optimize when in case of constant value (only keep choice that matches)
|
||||||
is it Correct??? Or better to use Casey's algorithm?
|
|
||||||
- revisit the seek example to see if write-seeking now works?
|
- 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)
|
- 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: 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
|
- [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
|
||||||
|
@ -61,21 +61,21 @@ main {
|
|||||||
byte decisionOver2 = 1-x as byte
|
byte decisionOver2 = 1-x as byte
|
||||||
|
|
||||||
while x>=y {
|
while x>=y {
|
||||||
txt.setcc(xcenter + x, ycenter + y as ubyte, 81, 1)
|
txt.setcc(xcenter + x, ycenter + y, 81, 1)
|
||||||
txt.setcc(xcenter - x, ycenter + y as ubyte, 81, 2)
|
txt.setcc(xcenter - x, ycenter + y, 81, 2)
|
||||||
txt.setcc(xcenter + x, ycenter - y as ubyte, 81, 3)
|
txt.setcc(xcenter + x, ycenter - y, 81, 3)
|
||||||
txt.setcc(xcenter - x, ycenter - y as ubyte, 81, 4)
|
txt.setcc(xcenter - x, ycenter - y, 81, 4)
|
||||||
txt.setcc(xcenter + y, ycenter + x as ubyte, 81, 5)
|
txt.setcc(xcenter + y, ycenter + x, 81, 5)
|
||||||
txt.setcc(xcenter - y, ycenter + x as ubyte, 81, 6)
|
txt.setcc(xcenter - y, ycenter + x, 81, 6)
|
||||||
txt.setcc(xcenter + y, ycenter - x as ubyte, 81, 7)
|
txt.setcc(xcenter + y, ycenter - x, 81, 7)
|
||||||
txt.setcc(xcenter - y, ycenter - x as ubyte, 81, 8)
|
txt.setcc(xcenter - y, ycenter - x, 81, 8)
|
||||||
y++
|
y++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += 2*y+1
|
|
||||||
else {
|
|
||||||
x--
|
x--
|
||||||
decisionOver2 += 2*(y-x)+1
|
decisionOver2 -= 2*x
|
||||||
}
|
}
|
||||||
|
decisionOver2 += 2*y
|
||||||
|
decisionOver2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,23 +89,23 @@ main {
|
|||||||
while x>=y {
|
while x>=y {
|
||||||
xx = cx-x
|
xx = cx-x
|
||||||
repeat 2*x+1 {
|
repeat 2*x+1 {
|
||||||
txt.setcc(xx, cy + y as ubyte, 81, 11)
|
txt.setcc(xx, cy + y, 81, 11)
|
||||||
txt.setcc(xx, cy - y as ubyte, 81, 12)
|
txt.setcc(xx, cy - y, 81, 12)
|
||||||
xx++
|
xx++
|
||||||
}
|
}
|
||||||
xx = cx-y
|
xx = cx-y
|
||||||
repeat 2*y+1 {
|
repeat 2*y+1 {
|
||||||
txt.setcc(xx, cy + x as ubyte, 81, 13)
|
txt.setcc(xx, cy + x, 81, 13)
|
||||||
txt.setcc(xx, cy - x as ubyte, 81, 14)
|
txt.setcc(xx, cy - x, 81, 14)
|
||||||
xx++
|
xx++
|
||||||
}
|
}
|
||||||
y++
|
y++
|
||||||
if decisionOver2<=0
|
if decisionOver2>=0 {
|
||||||
decisionOver2 += 2*y+1
|
|
||||||
else {
|
|
||||||
x--
|
x--
|
||||||
decisionOver2 += 2*(y-x)+1
|
decisionOver2 -= 2*x
|
||||||
}
|
}
|
||||||
|
decisionOver2 += 2*y
|
||||||
|
decisionOver2++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,27 @@
|
|||||||
%zeropage basicsafe
|
%import gfx2
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub pget(uword x, uword y) -> ubyte {
|
|
||||||
return lsb(x+y)
|
|
||||||
}
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
gfx2.screen_mode(2)
|
||||||
|
|
||||||
word xx
|
gfx2.safe_circle(120, 140, 200, 1)
|
||||||
word x2
|
sys.wait(30)
|
||||||
word yy
|
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
|
gfx2.safe_disc(120, 140, 200, 1)
|
||||||
xx++
|
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
|
repeat {
|
||||||
; if pget(xx as uword, yy as uword) == cx16.r11L
|
}
|
||||||
; xx++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user