diff --git a/examples/cx16/gfx2.p8 b/compiler/res/prog8lib/cx16/gfx2.p8 similarity index 73% rename from examples/cx16/gfx2.p8 rename to compiler/res/prog8lib/cx16/gfx2.p8 index 00e81d185..50185675f 100644 --- a/examples/cx16/gfx2.p8 +++ b/compiler/res/prog8lib/cx16/gfx2.p8 @@ -1,9 +1,4 @@ %target cx16 -%import textio -%import graphics -%import test_stack -%zeropage basicsafe -%option no_sysinit ; Bitmap pixel graphics module for the CommanderX16 ; Custom routines to use the full-screen 640x480 and 320x240 screen modes. @@ -11,54 +6,55 @@ ; For compatible graphics code that words on C64 too, use the "graphics" module instead. -; TODO this is in development. +; TODO this is in development. Add line drawing, circles and discs (like the graphics module has) -main { - - sub start () { - ubyte[] modes = [0, 1, 128] - ubyte mode - for mode in modes { - gfx2.set_mode(mode) - -; gfx2.location(20, 50) +;main { +; +; sub start () { +; ubyte[] modes = [0, 1, 128] +; ubyte mode +; for mode in modes { +; gfx2.set_mode(mode) +; +; gfx2.position(20, 50) ; repeat 200 { ; gfx2.next_pixel(255) ; } +; +; draw() +; cx16.wait(120) +; } +; } +; +; sub draw() { +; uword offset +; ubyte angle +; uword x +; uword y +; when gfx2.active_mode { +; 0, 1 -> { +; for offset in 0 to 90 step 3 { +; for angle in 0 to 255 { +; x = $0008+sin8u(angle)/2 +; y = $0008+cos8u(angle)/2 +; gfx2.plot(x+offset*2,y+offset, lsb(x+y)) +; } +; } +; } +; 128 -> { +; for offset in 0 to 190 step 6 { +; for angle in 0 to 255 { +; x = $0008+sin8u(angle) +; y = $0008+cos8u(angle) +; gfx2.plot(x+offset*2,y+offset, 1) +; } +; } +; } +; } +; } +;} - draw() - cx16.wait(120) - } - } - - sub draw() { - uword offset - ubyte angle - uword x - uword y - when gfx2.active_mode { - 0, 1 -> { - for offset in 0 to 90 step 3 { - for angle in 0 to 255 { - x = $0008+sin8u(angle)/2 - y = $0008+cos8u(angle)/2 - gfx2.plot(x+offset*2,y+offset, lsb(x+y)) - } - } - } - 128 -> { - for offset in 0 to 190 step 6 { - for angle in 0 to 255 { - x = $0008+sin8u(angle) - y = $0008+cos8u(angle) - gfx2.plot(x+offset*2,y+offset, 1) - } - } - } - } - } -} gfx2 { @@ -111,16 +107,22 @@ gfx2 { height = 480 bpp = 1 } + 255 -> { + ; back to default text mode and colors + cx16.VERA_CTRL = %10000000 ; reset VERA and palette + c64.CINT() ; back to text mode + width = 0 + height = 0 + bpp = 0 + } } active_mode = mode - clear_screen() + if bpp + clear_screen() } sub clear_screen() { - cx16.VERA_CTRL = 0 - cx16.VERA_ADDR_H = %00010000 - cx16.VERA_ADDR_M = 0 - cx16.VERA_ADDR_L = 0 + position(0, 0) when active_mode { 0 -> { ; 320 x 240 x 1c @@ -138,6 +140,7 @@ gfx2 { cs_innerloop640() } } + position(0, 0) } sub plot(uword x, uword y, ubyte color) { @@ -148,17 +151,17 @@ gfx2 { 0 -> { addr = x/8 + y*(320/8) value = bits[lsb(x)&7] - cx16.vpoke_or(addr, 0, value) + cx16.vpoke_or(0, addr, value) } 128 -> { addr = x/8 + y*(640/8) value = bits[lsb(x)&7] - cx16.vpoke_or(addr, 0, value) + cx16.vpoke_or(0, addr, value) } 1 -> { void addr_mul_320_add_24(y, x) ; 24 bits result is in r0 and r1L ubyte bank = lsb(cx16.r1) - cx16.vpoke(cx16.r0, bank, color) + cx16.vpoke(bank, cx16.r0, color) } } ; activate vera auto-increment mode so next_pixel() can be used after this @@ -166,21 +169,21 @@ gfx2 { return } - sub location(uword x, uword y) { + sub position(uword x, uword y) { uword address when active_mode { 0 -> { address = y*(320/8) + x/8 - cx16.vaddr(address, 0, 0, 1) + cx16.vaddr(0, address, 0, 1) } 128 -> { address = y*(640/8) + x/8 - cx16.vaddr(address, 0, 0, 1) + cx16.vaddr(0, address, 0, 1) } 1 -> { void addr_mul_320_add_24(y, x) ; 24 bits result is in r0 and r1L ubyte bank = lsb(cx16.r1) - cx16.vaddr(cx16.r0, bank, 0, 1) + cx16.vaddr(bank, cx16.r0, 0, 1) } } } @@ -207,6 +210,22 @@ gfx2 { } } + asmsub set_8_pixels_from_bits(ubyte bits @R0, ubyte oncolor @A, ubyte offcolor @Y) { + %asm {{ + phx + ldx #8 +- asl cx16.r0 + bcc + + sta cx16.VERA_DATA0 + bra ++ ++ sty cx16.VERA_DATA0 ++ dex + bne - + plx + rts + }} + } + asmsub cs_innerloop640() { %asm {{ ldy #80 diff --git a/examples/cx16/imageviewer/bmp_module.p8 b/examples/cx16/imageviewer/bmp_module.p8 index 4e0b6c122..5a79709d6 100644 --- a/examples/cx16/imageviewer/bmp_module.p8 +++ b/examples/cx16/imageviewer/bmp_module.p8 @@ -1,5 +1,5 @@ %target cx16 -%import graphics +%import gfx2 %import diskio bmp_module { @@ -46,7 +46,7 @@ bmp_module { total_read += size repeat bm_data_offset - total_read void c64.CHRIN() - graphics.clear_screen(1, 0) + gfx2.clear_screen() palette.set_bgra(&palette0, num_colors) decode_bitmap() load_ok = true @@ -62,14 +62,14 @@ bmp_module { sub start_plot() { offsetx = 0 offsety = 0 - if width < graphics.WIDTH - offsetx = (graphics.WIDTH - width - 1) / 2 - if height < graphics.HEIGHT - offsety = (graphics.HEIGHT - height - 1) / 2 - if width > graphics.WIDTH - width = graphics.WIDTH - if height > graphics.HEIGHT-1 - height = graphics.HEIGHT-1 + if width < gfx2.width + offsetx = (gfx2.width - width - 1) / 2 + if height < gfx2.height + offsety = (gfx2.height - height - 1) / 2 + if width > gfx2.width + width = gfx2.width + if height > gfx2.height + height = gfx2.height } sub decode_bitmap() { @@ -81,31 +81,31 @@ bmp_module { uword y ubyte b for y in height-1 downto 0 { - cx16.FB_cursor_position(offsetx, offsety+y) + gfx2.position(offsetx, offsety+y) when bpp { 8 -> { for x in 0 to width-1 - cx16.FB_set_pixel(c64.CHRIN()) + gfx2.next_pixel(c64.CHRIN()) } 4 -> { for x in 0 to width-1 step 2 { b = c64.CHRIN() - cx16.FB_set_pixel(b>>4) - cx16.FB_set_pixel(b&15) + gfx2.next_pixel(b>>4) + gfx2.next_pixel(b&15) } } 2 -> { for x in 0 to width-1 step 4 { b = c64.CHRIN() - cx16.FB_set_pixel(b>>6) - cx16.FB_set_pixel(b>>4 & 3) - cx16.FB_set_pixel(b>>2 & 3) - cx16.FB_set_pixel(b & 3) + gfx2.next_pixel(b>>6) + gfx2.next_pixel(b>>4 & 3) + gfx2.next_pixel(b>>2 & 3) + gfx2.next_pixel(b & 3) } } 1 -> { for x in 0 to width-1 step 8 - cx16.FB_set_8_pixels_opaque(c64.CHRIN(), 255, 255, 0) + gfx2.set_8_pixels_from_bits(c64.CHRIN(), 1, 0) } } diff --git a/examples/cx16/imageviewer/ci_module.p8 b/examples/cx16/imageviewer/ci_module.p8 index 7a450c138..d984d3f64 100644 --- a/examples/cx16/imageviewer/ci_module.p8 +++ b/examples/cx16/imageviewer/ci_module.p8 @@ -1,5 +1,5 @@ %target cx16 -%import graphics +%import gfx2 %import textio %import diskio %option no_sysinit @@ -77,7 +77,7 @@ ci_module { uword palette_size = num_colors*2 if palette_format palette_size += num_colors ; 3 - if width > graphics.WIDTH { + if width > gfx2.width { txt.print("image is too wide for the display!\n") } else if compression!=0 { txt.print("compressed image not yet supported!\n") ; TODO implement the various decompressions @@ -91,23 +91,20 @@ ci_module { } else { ; uncompressed bitmap data. read it a scanline at a time and display as we go. ; restrict height to the maximun that can be displayed - if height > graphics.HEIGHT - height = graphics.HEIGHT - graphics.enable_bitmap_mode() + if height > gfx2.height + height = gfx2.height if palette_format palette.set_rgb8(buffer, num_colors) else palette.set_rgb4(buffer, num_colors) - graphics.clear_screen(1,0) - cx16.r0 = 0 - cx16.r1 = 0 - cx16.FB_cursor_position() + gfx2.clear_screen() + gfx2.position(0 ,0) uword scanline_size = width * bpp / 8 ubyte y for y in 0 to lsb(height)-1 { void diskio.f_read(buffer, scanline_size) when bpp { - 8 -> cx16.FB_set_pixels_from_buf(buffer, scanline_size) ; FB_set_pixels in rom v38 crashes with a size > 255 so we use our own replacement for now + 8 -> gfx2.next_pixels(buffer, scanline_size) 4 -> display_scanline_16c(buffer, scanline_size) 2 -> display_scanline_4c(buffer, scanline_size) 1 -> display_scanline_2c(buffer, scanline_size) diff --git a/examples/cx16/imageviewer/iff_module.p8 b/examples/cx16/imageviewer/iff_module.p8 index f7ce8cd23..a67064c7d 100644 --- a/examples/cx16/imageviewer/iff_module.p8 +++ b/examples/cx16/imageviewer/iff_module.p8 @@ -1,5 +1,5 @@ %target cx16 -%import graphics +%import gfx2 %import textio %import diskio @@ -104,7 +104,7 @@ iff_module { skip_chunk() } else if chunk_id == "body" { - graphics.clear_screen(1, 0) + gfx2.clear_screen() if camg & $0004 height /= 2 ; interlaced: just skip every odd scanline later if camg & $0080 and have_cmap @@ -178,14 +178,14 @@ iff_module { interleave_stride = (bitplane_stride as uword) * num_planes offsetx = 0 offsety = 0 - if width < graphics.WIDTH - offsetx = (graphics.WIDTH - width - 1) / 2 - if height < graphics.HEIGHT - offsety = (graphics.HEIGHT - height - 1) / 2 - if width > graphics.WIDTH - width = graphics.WIDTH - if height > graphics.HEIGHT-1 - height = graphics.HEIGHT-1 + if width < gfx2.width + offsetx = (gfx2.width - width - 1) / 2 + if height < gfx2.height + offsety = (gfx2.height - height - 1) / 2 + if width > gfx2.width + width = gfx2.width + if height > gfx2.height + height = gfx2.height } sub decode_raw() { @@ -196,7 +196,7 @@ iff_module { diskio.f_read_exact(scanline_data_ptr, interleave_stride) if interlaced diskio.f_read_exact(scanline_data_ptr, interleave_stride) - cx16.FB_cursor_position(offsetx, offsety+y) + gfx2.position(offsetx, offsety+y) planar_to_chunky_scanline() } } @@ -209,7 +209,7 @@ iff_module { decode_rle_scanline() if interlaced decode_rle_scanline() - cx16.FB_cursor_position(offsetx, offsety+y) + gfx2.position(offsetx, offsety+y) planar_to_chunky_scanline() } } @@ -296,7 +296,7 @@ _masks .byte 128, 64, 32, 16, 8, 4, 2, 1 ; } ; bits >>= 8-num_planes - cx16.FB_set_pixel(bits) + gfx2.next_pixel(bits) } } } @@ -305,6 +305,8 @@ _masks .byte 128, 64, 32, 16, 8, 4, 2, 1 if num_cycles==0 return + ; TODO implement Blend Shifting see http://www.effectgames.com/demos/canvascycle/palette.js + ubyte changed = false ubyte ci for ci in 0 to num_cycles-1 { diff --git a/examples/cx16/imageviewer/imageviewer.p8 b/examples/cx16/imageviewer/imageviewer.p8 index c868d2c2a..87f2f07ed 100644 --- a/examples/cx16/imageviewer/imageviewer.p8 +++ b/examples/cx16/imageviewer/imageviewer.p8 @@ -1,5 +1,5 @@ %target cx16 -%import graphics +%import gfx2 %import textio %import diskio %import koala_module @@ -10,8 +10,6 @@ %zeropage basicsafe -; TODO use the gfx2 graphics module for full-screen 320x240 display instead of 320x200 truncated. - main { sub start() { ; trick to check if we're running on sdcard or host system shared folder @@ -19,20 +17,19 @@ main { if strlen(diskio.status(8)) { txt.print("enter image file name or just enter for all on disk: ") ubyte i = txt.input_chars(diskio.filename) - graphics.enable_bitmap_mode() + gfx2.set_mode(1) ; 320*240, 256c if i attempt_load(diskio.filename) else show_pics_sdcard() - txt.print("\nnothing more to do.\n") + ; txt.print("\nnothing more to do.\n") } else txt.print("files are read with sequential file loading.\nin the emulator this currently only works with files on an sd-card image.\nsorry :(\n") - repeat { - ; - } + gfx2.set_mode(255) ; back to default text mode and palette + txt.print("that was all folks!\n") } sub show_pics_sdcard() { @@ -53,64 +50,71 @@ main { } sub attempt_load(uword filenameptr) { - txt.print(">> ") - txt.print(filenameptr) - txt.chrout('\n') + ;txt.print(">> ") + ;txt.print(filenameptr) + ;txt.chrout('\n') uword extension = filenameptr + rfind(filenameptr, '.') if strcmp(extension, ".iff")==0 { - txt.print("loading ") - txt.print("iff\n") - if iff_module.show_image(filenameptr) - txt.clear_screen() - else - txt.print("load error!\n") - if iff_module.num_cycles { - repeat 500 { - cx16.wait(1) - iff_module.cycle_colors_each_jiffy() + ;txt.print("loading ") + ;txt.print("iff\n") + if iff_module.show_image(filenameptr) { + if iff_module.num_cycles { + repeat 500 { + cx16.wait(1) + iff_module.cycle_colors_each_jiffy() + } } + else + cx16.wait(180) + } else { + load_error(filenameptr) } - else - cx16.wait(120) } else if strcmp(extension, ".pcx")==0 { - txt.print("loading ") - txt.print("pcx\n") - if pcx_module.show_image(filenameptr) - txt.clear_screen() - else - txt.print("load error!\n") - cx16.wait(120) + ;txt.print("loading ") + ;txt.print("pcx\n") + if pcx_module.show_image(filenameptr) { + cx16.wait(180) + } else { + load_error(filenameptr) + } } else if strcmp(extension, ".koa")==0 { - txt.print("loading ") - txt.print("koala\n") - if koala_module.show_image(filenameptr) - txt.clear_screen() - else - txt.print("load error!\n") - cx16.wait(120) + ;txt.print("loading ") + ;txt.print("koala\n") + if koala_module.show_image(filenameptr) { + cx16.wait(180) + } else { + load_error(filenameptr) + } } else if strcmp(extension, ".bmp")==0 { - txt.print("loading ") - txt.print("bmp\n") - if bmp_module.show_image(filenameptr) - txt.clear_screen() - else - txt.print("load error!\n") - cx16.wait(120) + ;txt.print("loading ") + ;txt.print("bmp\n") + if bmp_module.show_image(filenameptr) { + cx16.wait(180) + } else { + load_error(filenameptr) + } } ; else if strcmp(extension, ".ci")==0 { ; txt.print("loading ") ; txt.print("ci\n") -; if ci_module.show_image(filenameptr) -; txt.clear_screen() -; else -; txt.print("load error!\n") -; cx16.wait(120) +; if bmp_module.ci_module(filenameptr) { +; cx16.wait(180) +; } else { +; load_error(filenameptr) +; } ; } } + sub load_error(uword filenameptr) { + gfx2.set_mode(255) ; back to default text mode and palette + txt.print(filenameptr) + txt.print(": load error\n") + exit(1) + } + sub extension_equals(uword stringptr, uword extensionptr) -> ubyte { ubyte ix = rfind(stringptr, '.') return ix<255 and strcmp(stringptr+ix, extensionptr)==0 diff --git a/examples/cx16/imageviewer/koala_module.p8 b/examples/cx16/imageviewer/koala_module.p8 index f297ed23d..6282cadb3 100644 --- a/examples/cx16/imageviewer/koala_module.p8 +++ b/examples/cx16/imageviewer/koala_module.p8 @@ -1,5 +1,5 @@ %target cx16 -%import graphics +%import gfx2 %import diskio %import c64colors @@ -33,14 +33,17 @@ koala_module { ; theoretically you could put the 8-pixel array in zeropage to squeeze out another tiny bit of performance ubyte[8] pixels - graphics.clear_screen(1, 0) + gfx2.clear_screen() + uword offsety = (gfx2.height - 200) / 2 for cy in 0 to 24*8 step 8 { + uword posy = cy + offsety for cx in 0 to 39 { + uword posx = cx as uword * 8 for d in 0 to 7 { - cx16.FB_cursor_position(cx as uword * 8, cy as uword + d) + gfx2.position(posx, posy + d) get_8_pixels() - cx16.FB_set_pixels(pixels, 8) + gfx2.next_pixels(pixels, 8) } } cy_times_forty += 40 diff --git a/examples/cx16/imageviewer/pcx_module.p8 b/examples/cx16/imageviewer/pcx_module.p8 index dc09a652c..18d09ff75 100644 --- a/examples/cx16/imageviewer/pcx_module.p8 +++ b/examples/cx16/imageviewer/pcx_module.p8 @@ -1,5 +1,5 @@ %target cx16 -%import graphics +%import gfx2 %import textio %import diskio @@ -22,7 +22,7 @@ pcx_module { uword num_colors = 2**bits_per_pixel if number_of_planes == 1 { if (width & 7) == 0 { - graphics.clear_screen(1, 0) + gfx2.clear_screen() if palette_format==2 palette.set_grayscale() else if num_colors == 16 @@ -76,24 +76,24 @@ bitmap { y_ok = true py = 0 px = 0 - if width < graphics.WIDTH - offsetx = (graphics.WIDTH - width - 1) / 2 - if height < graphics.HEIGHT - offsety = (graphics.HEIGHT - height - 1) / 2 + if width < gfx2.width + offsetx = (gfx2.width - width) / 2 + if height < gfx2.height + offsety = (gfx2.height - height) / 2 status = (not c64.READST()) or c64.READST()==64 } sub next_scanline() { px = 0 py++ - y_ok = py < graphics.HEIGHT-1 - cx16.FB_cursor_position(offsetx, offsety+py) + y_ok = py < gfx2.height + gfx2.position(offsetx, offsety+py) status = (not c64.READST()) or c64.READST()==64 } sub do1bpp(uword width, uword height) -> ubyte { start_plot(width, height) - cx16.FB_cursor_position(offsetx, offsety) + gfx2.position(offsetx, offsety) while py < height and status { ubyte b = c64.CHRIN() if b>>6==3 { @@ -101,12 +101,12 @@ bitmap { ubyte dat = c64.CHRIN() repeat b { if y_ok - cx16.FB_set_8_pixels_opaque(dat, 255, 255, 0) + gfx2.set_8_pixels_from_bits(dat, 1, 0) px += 8 } } else { if y_ok - cx16.FB_set_8_pixels_opaque(b, 255, 255, 0) + gfx2.set_8_pixels_from_bits(b, 1, 0) px += 8 } if px==width @@ -118,7 +118,7 @@ bitmap { sub do4bpp(uword width, uword height) -> ubyte { start_plot(width, height) - cx16.FB_cursor_position(offsetx, offsety) + gfx2.position(offsetx, offsety) while py < height and status { ubyte b = c64.CHRIN() if b>>6==3 { @@ -126,14 +126,14 @@ bitmap { ubyte dat = c64.CHRIN() if y_ok repeat b { - cx16.FB_set_pixel(dat>>4) - cx16.FB_set_pixel(dat & 15) + gfx2.next_pixel(dat>>4) + gfx2.next_pixel(dat & 15) } px += b*2 } else { if y_ok { - cx16.FB_set_pixel(b>>4) - cx16.FB_set_pixel(b & 15) + gfx2.next_pixel(b>>4) + gfx2.next_pixel(b & 15) } px += 2 } @@ -146,7 +146,7 @@ bitmap { sub do8bpp(uword width, uword height) -> ubyte { start_plot(width, height) - cx16.FB_cursor_position(offsetx, offsety) + gfx2.position(offsetx, offsety) while py < height and status { ubyte b = c64.CHRIN() if b>>6==3 { @@ -154,11 +154,11 @@ bitmap { ubyte dat = c64.CHRIN() if y_ok repeat b - cx16.FB_set_pixel(dat) + gfx2.next_pixel(dat) px += b } else { if y_ok - cx16.FB_set_pixel(b) + gfx2.next_pixel(b) px++ } if px==width diff --git a/examples/cx16/testgfx2.p8 b/examples/cx16/testgfx2.p8 new file mode 100644 index 000000000..0208d1d41 --- /dev/null +++ b/examples/cx16/testgfx2.p8 @@ -0,0 +1,46 @@ +%target cx16 +%import gfx2 +%import textio +%zeropage basicsafe + +main { + + sub start () { + ubyte[] modes = [0, 1, 128] + ubyte mode + for mode in modes { + gfx2.set_mode(mode) + draw() + cx16.wait(120) + } + gfx2.set_mode(255) + txt.print("done!\n") + } + + sub draw() { + uword offset + ubyte angle + uword x + uword y + when gfx2.active_mode { + 0, 1 -> { + for offset in 0 to 90 step 3 { + for angle in 0 to 255 { + x = $0008+sin8u(angle)/2 + y = $0008+cos8u(angle)/2 + gfx2.plot(x+offset*2,y+offset, lsb(x+y)) + } + } + } + 128 -> { + for offset in 0 to 190 step 6 { + for angle in 0 to 255 { + x = $0008+sin8u(angle) + y = $0008+cos8u(angle) + gfx2.plot(x+offset*2,y+offset, 1) + } + } + } + } + } +} diff --git a/examples/test.p8 b/examples/test.p8 index b8286e9a3..ab20a7996 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,6 +8,13 @@ main { + ; TODO the R0 is loaded as a WORD even though its type is specified as a BYTE...: + asmsub set_8_pixels_from_bits(ubyte bits @R0, ubyte oncolor @A, ubyte offcolor @Y) { + + } + + + asmsub derp(ubyte value @A, uword address @R0) { %asm {{ rts