diff --git a/compiler/res/prog8lib/cx16/gfx2.p8 b/compiler/res/prog8lib/cx16/gfx2.p8 index b9d79ff38..045b38874 100644 --- a/compiler/res/prog8lib/cx16/gfx2.p8 +++ b/compiler/res/prog8lib/cx16/gfx2.p8 @@ -6,7 +6,6 @@ ; Note: for compatible graphics code that words on C64 too, use the "graphics" module instead. ; Note: there is no color palette manipulation here, you have to do that yourself or use the "palette" module. -; TODO this is in development. Add line drawing, circles and discs (like the graphics module has) gfx2 { @@ -15,6 +14,7 @@ gfx2 { uword width = 0 uword height = 0 ubyte bpp = 0 + ubyte monochrome_dont_stipple_flag = false ; set to false to enable stippling mode in monochrome displaymodes sub screen_mode(ubyte mode) { ; mode 0 = bitmap 320 x 240 x 1c monochrome @@ -77,6 +77,7 @@ gfx2 { } sub clear_screen() { + monochrome_stipple(false) position(0, 0) when active_mode { 0 -> { @@ -98,6 +99,10 @@ gfx2 { position(0, 0) } + sub monochrome_stipple(ubyte enable) { + monochrome_dont_stipple_flag = ~enable + } + sub rect(uword x, uword y, uword width, uword height, ubyte color) { if width==0 or height==0 return @@ -289,8 +294,8 @@ gfx2 { word @zp decisionOver2 = (1 as word)-radius while radius>=yy { - horizontal_line(xcenter-radius, ycenter+yy, radius*2+1, color) - horizontal_line(xcenter-radius, ycenter-yy, radius*2+1, color) + horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, color) + horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, color) horizontal_line(xcenter-yy, ycenter+radius, yy*2+1, color) horizontal_line(xcenter-yy, ycenter-radius, yy*2+1, color) yy++ @@ -307,26 +312,53 @@ gfx2 { ubyte[8] bits = [128, 64, 32, 16, 8, 4, 2, 1] uword addr ubyte value + when active_mode { 0 -> { - addr = x/8 + y*(320/8) - value = bits[lsb(x)&7] - cx16.vpoke_or(0, addr, value) + %asm {{ + lda x + eor y + ora monochrome_dont_stipple_flag + and #1 + }} + if_nz { + addr = x/8 + y*(320/8) + value = bits[lsb(x)&7] + if color + cx16.vpoke_or(0, addr, value) + else { + value = ~value + cx16.vpoke_and(0, addr, value) + } + } } 128 -> { - addr = x/8 + y*(640/8) - value = bits[lsb(x)&7] - cx16.vpoke_or(0, addr, value) + %asm {{ + lda x + eor y + ora monochrome_dont_stipple_flag + and #1 + }} + if_nz { + addr = x/8 + y*(640/8) + value = bits[lsb(x)&7] + if color + cx16.vpoke_or(0, addr, value) + else { + value = ~value + cx16.vpoke_and(0, addr, value) + } + } } 1 -> { void addr_mul_320_add_24(y, x) ; 24 bits result is in r0 and r1L value = lsb(cx16.r1) cx16.vpoke(value, cx16.r0, color) + ; activate vera auto-increment mode so next_pixel() can be used after this + cx16.VERA_ADDR_H = (cx16.VERA_ADDR_H & %00000111) | %00010000 + color = cx16.VERA_DATA0 } } - ; activate vera auto-increment mode so next_pixel() can be used after this - cx16.VERA_ADDR_H = (cx16.VERA_ADDR_H & %00000111) | %00010000 - color = cx16.VERA_DATA0 } sub position(uword @zp x, uword y) { @@ -424,10 +456,18 @@ gfx2 { lda cx16.VERA_ADDR_H and #%111 ; don't auto-increment, we have to do that manually because of the ora sta cx16.VERA_ADDR_H + lda color + sta P8ZP_SCRATCH_B1 ldy #8 -- lda cx16.VERA_DATA0 +- lda P8ZP_SCRATCH_B1 + bne + ; white color, plot normally + lda cx16.VERA_DATA1 + eor #255 ; black color, keep only the other pixels + and cx16.VERA_DATA0 + bra ++ ++ lda cx16.VERA_DATA0 ora cx16.VERA_DATA1 - sta cx16.VERA_DATA0 ++ sta cx16.VERA_DATA0 lda cx16.VERA_ADDR_L clc adc cx16.r2 diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 0ceb58999..8568e05ce 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -91,10 +91,11 @@ gfx2 (cx16 only) Full-screen multicolor bitmap graphics routines, available on the Cx16 machine only. - multiple full-screen resolutions: 640 * 480 monochrome, and 320 * 240 monochrome and 256 colors -- clearing screen, switching screen mode -- drawing pixels +- clearing screen, switching screen mode, also back to text mode is possible. +- drawing individual pixels +- drawing lines, rectangles, filled rectangles, circles, discs - drawing text inside the bitmap -- lines, rectangles, circles, discs. +- in monochrome mode, it's possible to use a stippled drawing pattern to simulate a shade of gray. palette (cx16 only) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 44edbf0c7..9c27b7022 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,7 +2,8 @@ TODO ==== -- implement gfx2's rect, fillrect, horizontal_line and vertical_line in graphics modules as well. +- nice error msg for float as for loop var +- implement gfx2's rect, fillrect, horizontal_line and vertical_line in graphics modules as well. (and optimize bresenham line to use vert/horiz line if possible) - detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation - hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine) - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' diff --git a/examples/cx16/highresbitmap.p8 b/examples/cx16/highresbitmap.p8 new file mode 100644 index 000000000..6511ebb65 --- /dev/null +++ b/examples/cx16/highresbitmap.p8 @@ -0,0 +1,87 @@ +%target cx16 +%import gfx2 +%import floats +%import textio +%zeropage basicsafe + +main { + + sub start () { + gfx2.text_charset(3) + + test_monochrome() + + gfx2.screen_mode(255) + txt.print("done!\n") + } + + sub test_monochrome() { + gfx2.screen_mode(128) + uword yy + uword xx + word ww + + yy = 20 + xx = 20 + gfx2.monochrome_stipple(false) + gfx2.rect(xx, yy, 250, 80, 1) + gfx2.monochrome_stipple(true) + gfx2.fillrect(xx+2, yy+2, 250-4, 80-4, 1) + gfx2.monochrome_stipple(false) + gfx2.fillrect(xx+20, yy+20, 200, 30, 1) + gfx2.rect(xx+21, yy+21, 200-2, 30-2, 0) + + gfx2.text(xx+30, yy+32, 0, @"High Res Bitmap Example") + + ; gfx2.monochrome_stipple(true) + gfx2.horizontal_line(10, 240, 620, 1) + gfx2.vertical_line(320, 10, 460, 1) + gfx2.text(320, 242, 1, @"0,0") + gfx2.text(322, 10, 1, @"Y-axis") + gfx2.text(590, 242, 1, @"X-axis") + for ww in -10 to 10 { + xx = (ww*30) + 320 as uword + gfx2.vertical_line(xx, 239, 3, 1) + } + for ww in -7 to 7 { + yy = (ww*30) + 240 as uword + gfx2.horizontal_line(319, yy, 3, 1) + } + + gfx2.monochrome_stipple(false) + float y_f + for ww in -600 to 600 { + y_f = sin(ww as float / 60.0)*150 + gfx2.plot(ww/2 + 320 as uword, (y_f + 240) as uword, 1) + } + gfx2.text(480, 100, 1, @"sin(x)") + + for ww in -300 to 300 { + y_f = cos(ww as float/30.0)*60 - (ww as float)/1.7 + gfx2.plot(ww + 320 as uword, (y_f + 240) as uword, 1) + } + gfx2.text(80, 420, 1, @"cos(x)+x") + + cx16.wait(3*60) + + gfx2.circle(320, 240, 220, 1) + gfx2.circle(320, 240, 210, 1) + gfx2.circle(320, 240, 200, 1) + gfx2.circle(320, 240, 190, 1) + gfx2.monochrome_stipple(true) + gfx2.disc(320, 240, 140, 1) + gfx2.monochrome_stipple(false) + gfx2.disc(320, 240, 90, 1) + gfx2.disc(320, 240, 40, 0) + + cx16.wait(2*60) + + repeat 255 { + xx=rndw() % 640 ; TODO doesn't work correctly, truncates + yy=rndw() % 480 ; TODO doesn't work correctly, truncates + gfx2.line(xx, yy, rndw() % 640, rndw() % 480, 1) + } + + cx16.wait(1*60) + } +} diff --git a/examples/test.p8 b/examples/test.p8 index 8b4eccfbb..e376da444 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,46 +7,17 @@ main { sub start () { - uword length - uword total = 0 - length=200 - count() - txt.print_uw(total) - txt.chrout('\n') - length=255 - count() - txt.print_uw(total) - txt.chrout('\n') - length=256 - count() - txt.print_uw(total) - txt.chrout('\n') - length=257 - count() - txt.print_uw(total) - txt.chrout('\n') - length=9999 - count() - txt.print_uw(total) - txt.chrout('\n') + ; TODO uword var = rndw() % 640 doesn't work??? works if its in an expression. - test_stack.test() - - - sub count() { - total = 0 - if length>256 { - repeat length-1 - total++ - } else { - uword total2 - repeat lsb(length-1) - total++ -; repeat (length-1) as ubyte ; TODO lsb(length-1) doesn't work!?!?!? -; total++ - } + x_f = -300.0 + for ww in -300 to 300 { + ;fl = ww as float / 10.0 ; TODO doesn't work??? + y_f = cos(x_f/30)*60 - x_f/1.7 + gfx2.plot(ww + 320 as uword, (y_f + 240) as uword, 1) + x_f += 1.0 } + }