From 7d4695c5b2c9bc6df65213c65035f3a9073b5d10 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 17 Jul 2022 15:04:15 +0200 Subject: [PATCH] cx16: graphics module y resolution corrected from 200 to 240. added 'cx16/circles' example. --- compiler/res/prog8lib/cx16/graphics.p8 | 37 ++++++---- compiler/test/TestCompilerOnExamples.kt | 1 + docs/source/todo.rst | 1 + examples/cx16/circles.p8 | 89 +++++++++++++++++++++++++ examples/test.p8 | 14 ++-- 5 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 examples/cx16/circles.p8 diff --git a/compiler/res/prog8lib/cx16/graphics.p8 b/compiler/res/prog8lib/cx16/graphics.p8 index 453b0b3a4..97d52385a 100644 --- a/compiler/res/prog8lib/cx16/graphics.p8 +++ b/compiler/res/prog8lib/cx16/graphics.p8 @@ -2,15 +2,20 @@ %import textio ; Bitmap pixel graphics module for the CommanderX16 -; wraps the graphics functions that are in ROM. -; only black/white monochrome 320x200 for now. (i.e. truncated at the bottom) -; For full-screen 640x480 or 320x240 graphics, use the "gfx2" module instead. (but that is Cx16-specific) +; Wraps the graphics functions that are in ROM. +; Only lo-res 320x240 256 color mode for now. +; 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" 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. graphics { const uword WIDTH = 320 - const ubyte HEIGHT = 200 + const ubyte HEIGHT = 240 + + + ubyte stroke_color = 1 + ubyte background_color = 0 sub enable_bitmap_mode() { ; enable bitmap screen, erase it and set colors to black/white. @@ -27,10 +32,18 @@ graphics { sub clear_screen(ubyte pixelcolor, ubyte bgcolor) { + stroke_color = pixelcolor + background_color = bgcolor cx16.GRAPH_set_colors(pixelcolor, pixelcolor, bgcolor) cx16.GRAPH_clear() } + sub colors(ubyte stroke, ubyte fill) { + ; this routine is only available on the cx16, other targets can't change colors on the fly + cx16.GRAPH_set_colors(stroke, fill, background_color) + stroke_color = stroke + } + sub line(uword @zp x1, ubyte @zp y1, uword @zp x2, ubyte @zp y2) { cx16.GRAPH_draw_line(x1, y1, x2, y2) } @@ -71,31 +84,31 @@ graphics { cx16.r0 = xcenter + xx cx16.r1 = ycenter + yy cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) cx16.r0 = xcenter - xx cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) cx16.r0 = xcenter + xx cx16.r1 = ycenter - yy cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) cx16.r0 = xcenter - xx cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) cx16.r0 = xcenter + yy cx16.r1 = ycenter + xx cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) cx16.r0 = xcenter - yy cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) cx16.r0 = xcenter + yy cx16.r1 = ycenter - xx cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) cx16.r0 = xcenter - yy cx16.FB_cursor_position2() - cx16.FB_set_pixel(1) + cx16.FB_set_pixel(stroke_color) yy++ if decisionOver2<=0 { decisionOver2 += (yy as word)*2+1 diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index ab0661f3d..a484ad48f 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -94,6 +94,7 @@ class TestCompilerOnExamplesCx16: FunSpec({ "amiga", "bdmusic", "bobs", + "circles", "cobramk3-gfx", "colorbars", "datetime", diff --git a/docs/source/todo.rst b/docs/source/todo.rst index f38f56b5d..92d7f4365 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,6 +3,7 @@ TODO For next release ^^^^^^^^^^^^^^^^ +- uword x, ubyte radius; (x as word - radius) > 0 is ok , but (x as word - radius) >=0 is incorrect? - add item to XZeropage that enables an option that if zeropage=FULL or KERNALSAFE, moves the cx16 virtual registers to ZP, same location as on x16 (can be done on C64 only for now) Remove those addresses from the ZP free pool = allocate them in ZP like Cx16Zeropage does Adapt the code in AstPreprocessor that relocates the registers as well. diff --git a/examples/cx16/circles.p8 b/examples/cx16/circles.p8 new file mode 100644 index 000000000..6b1e3c8dd --- /dev/null +++ b/examples/cx16/circles.p8 @@ -0,0 +1,89 @@ +%import floats +%import graphics + +; note: this program is tuned for the CX16, but with some minor modifications can run on other systems too. + +main { + const ubyte MAX_NUM_CIRCLES = 80 + const ubyte GROWTH_RATE = 2 + uword[MAX_NUM_CIRCLES] circle_x + uword[MAX_NUM_CIRCLES] circle_y + ubyte[MAX_NUM_CIRCLES] circle_radius + ubyte num_circles = 0 + + sub start() { + graphics.enable_bitmap_mode() + + repeat { + graphics.clear_screen(1, 0) + num_circles = 0 + draw_circles() + } + } + + sub draw_circles() { + uword @zp x + uword @zp y + ubyte @zp radius + + while num_circles bool { + if num_circles==0 + return true + ubyte @zp c + for c in 0 to num_circles-1 { + if distance(c) < (radius as uword) + circle_radius[c] + return false + } + return true + } + + sub distance(ubyte cix) -> uword { + word dx = x as word - circle_x[cix] + word dy = y as word - circle_y[cix] + uword sqx = dx*dx as uword + uword sqy = dy*dy as uword + return sqrt16(sqx + sqy) + } + +; sub distance(ubyte cix) -> uword { +; float dx = x as float - circle_x[cix] +; float dy = y as float - circle_y[cix] +; return floats.sqrt(dx*dx + dy*dy) as uword +; } + + sub not_edge() -> bool { + if x as word - radius < 0 + return false + if x + radius >= graphics.WIDTH + return false + if y as word - radius < 0 + return false + if y + radius >= graphics.HEIGHT + return false + return true + } + } +} diff --git a/examples/test.p8 b/examples/test.p8 index a08d742e4..1057397e3 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,11 +2,15 @@ %zeropage basicsafe main { - sub func(ubyte bb) { - bb++ - } - sub start() { - func("abc") + ubyte ci + ubyte from=10 + ubyte end=1 + + for ci in from to end { + txt.print_ub(ci) + txt.spc() + } + txt.nl() } }