diff --git a/compiler/res/prog8lib/cx16/gfx2.p8 b/compiler/res/prog8lib/cx16/gfx_hires4.p8 similarity index 58% rename from compiler/res/prog8lib/cx16/gfx2.p8 rename to compiler/res/prog8lib/cx16/gfx_hires4.p8 index 6cf739afc..f67d0faf3 100644 --- a/compiler/res/prog8lib/cx16/gfx2.p8 +++ b/compiler/res/prog8lib/cx16/gfx_hires4.p8 @@ -1,117 +1,49 @@ ; Bitmap pixel graphics routines for the CommanderX16 -; Custom routines to use the full-screen 640x480 and 320x240 screen modes. +; Custom routines to use the full-screen 640x480 in 4 color mode. +; (monochrome mode can be used via the monogfx module) ; (These modes are not supported by the documented GRAPH_xxxx kernal routines) ; ; No text layer is currently shown, text can be drawn as part of the bitmap itself. ; Note: for similar graphics routines that also work on the C-64, use the "graphics" module instead. ; Note: for identical routines for a monochrome 1 bpp screen, use the "monogfx" module instead. ; Note: for color palette manipulation, use the "palette" module or write Vera registers yourself. -; Note: this library implements code for various resolutions and color depths. This takes up memory. -; 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! +; NOTE: the bitmap screen data is positioned in vram at $00000 +; This is compatible with the CX16's screen mode 128. (void cx16.set_screen_mode(128)) ; -; NOTE: the bitmap screen data is positioned in vram at $0:0000 -; -; NOTE: In the future, these routines might be split out to separate modules, 1 for each screen mode, -; so they can be optimized a lot better. There's already a "gfx_lores" module with a few routines for lores 256C mode. -; -; SCREEN MODE LIST: -; mode 0 = reset back to default text mode -; mode 1 = bitmap 320 x 240 x 256c (8 bpp) -; mode 2 = bitmap 640 x 480 x 4c (2 bpp) -; mode 3 = bitmap 320 x 240 x 4c (not yet implemented: just use 256c, there's enough vram for that) -; mode 4 = bitmap 320 x 240 x 16c (not yet implemented: just use 256c, there's enough vram for that) -; mode 5 = bitmap 640 x 400 x 16c (not yet implemented) -gfx2 { +gfx_hires4 { %option ignore_unused - ; read-only control variables: - ubyte active_mode = 0 - uword width = 0 - uword height = 0 - ubyte bpp = 0 + const uword WIDTH = 640 + const uword HEIGHT = 480 - sub screen_mode(ubyte mode) { + sub graphics_mode() { + ; set hires 4c mode cx16.VERA_CTRL=0 - when mode { - 1 -> { - ; lores 256c - cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11001111) | %00100000 ; enable only layer 1 - cx16.VERA_DC_HSCALE = 64 - cx16.VERA_DC_VSCALE = 64 - cx16.VERA_L1_CONFIG = %00000111 - cx16.VERA_L1_MAPBASE = 0 - cx16.VERA_L1_TILEBASE = 0 - } - 2 -> { - ; highres 4c - cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11001111) | %00100000 ; enable only layer 1 - cx16.VERA_DC_HSCALE = 128 - cx16.VERA_DC_VSCALE = 128 - cx16.VERA_L1_CONFIG = %00000101 - cx16.VERA_L1_MAPBASE = 0 - cx16.VERA_L1_TILEBASE = %00000001 - } - else -> { - ; back to default text mode - if active_mode!=0 { - cx16.r15L = cx16.VERA_DC_VIDEO & %00000111 ; retain chroma + output mode - cbm.CINT() - cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11111000) | cx16.r15L - } - } - } - - init_mode(mode) - if active_mode!=0 - clear_screen(0) + cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11001111) | %00100000 ; enable only layer 1 + cx16.VERA_DC_HSCALE = 128 + cx16.VERA_DC_VSCALE = 128 + cx16.VERA_L1_CONFIG = %00000101 + cx16.VERA_L1_MAPBASE = 0 + cx16.VERA_L1_TILEBASE = %00000001 + clear_screen(0) } - sub init_mode(ubyte mode) { - ; set the internal configuration variables corresponding to the given screenmode - ; doesn't manipulate Vera / the actual display mode - active_mode = mode - when mode { - 1 -> { - width = 320 - height = 240 - bpp = 8 - } - 2 -> { - width = 640 - height = 480 - bpp = 2 - } - else -> { - width = 0 - height = 0 - bpp = 0 - active_mode = 0 - } - } + sub text_mode() { + ; back to normal text mode + cx16.r15L = cx16.VERA_DC_VIDEO & %00000111 ; retain chroma + output mode + cbm.CINT() + cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11111000) | cx16.r15L } sub clear_screen(ubyte color) { position(0, 0) - when active_mode { - 1 -> { - ; lores 256c - repeat 240/2 - cs_innerloop640(color) - } - 2 -> { - ; highres 4c - ubyte[] colors = [%00000000, %01010101, %10101010, %11111111] - color = colors[color&3] - repeat 480/4 - cs_innerloop640(color) - } - } + ubyte[] colors = [%00000000, %01010101, %10101010, %11111111] + color = colors[color&3] + repeat 480/4 + cs_innerloop640(color) position(0, 0) } @@ -155,22 +87,22 @@ gfx2 { ; Draw a filled rectangle of the given size and color. ; To fill the whole screen, use clear_screen(color) instead - it is much faster. ; This safe version does bounds checking and clipping. - if xx>=width or yy>=width + if xx>=WIDTH or yy>=WIDTH return if msb(xx)&$80!=0 { rwidth += xx xx = 0 } - if xx>=width + if xx>=WIDTH return - if xx+rwidth>width - rwidth = width-xx - if rwidth>width + if xx+rwidth>WIDTH + rwidth = WIDTH-xx + if rwidth>WIDTH return - if yy + rheight > height - rheight = height-yy - if rheight>height + if yy + rheight > HEIGHT + rheight = HEIGHT-yy + if rheight>HEIGHT return repeat rheight { @@ -182,137 +114,93 @@ gfx2 { sub horizontal_line(uword xx, uword yy, uword length, ubyte color) { if length==0 return - when active_mode { - 1 -> { - ; lores 256c - position(xx, yy) - %asm {{ - lda p8v_color - ldx p8v_length+1 - beq + - ldy #0 -- sta cx16.VERA_DATA0 - iny - bne - - dex - bne - -+ ldy p8v_length ; remaining - beq + -- sta cx16.VERA_DATA0 - dey - bne - -+ - }} - } - 2 -> { - ; highres 4c ....also mostly usable for lores 4c? - color &= 3 - ubyte[4] colorbits - ubyte ii - for ii in 3 downto 0 { - colorbits[ii] = color - color <<= 2 - } - void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) - %asm {{ - lda cx16.VERA_ADDR_H - and #%00000111 ; no auto advance - sta cx16.VERA_ADDR_H - stz cx16.VERA_CTRL ; setup vera addr 0 - lda cx16.r1 - and #1 - sta cx16.VERA_ADDR_H - lda cx16.r0 - sta cx16.VERA_ADDR_L - lda cx16.r0+1 - sta cx16.VERA_ADDR_M - ldx p8v_xx - }} + ; highres 4c ....also mostly usable for lores 4c? + color &= 3 + ubyte[4] colorbits + ubyte ii + for ii in 3 downto 0 { + colorbits[ii] = color + color <<= 2 + } + void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) + %asm {{ + lda cx16.VERA_ADDR_H + and #%00000111 ; no auto advance + sta cx16.VERA_ADDR_H + stz cx16.VERA_CTRL ; setup vera addr 0 + lda cx16.r1 + and #1 + sta cx16.VERA_ADDR_H + lda cx16.r0 + sta cx16.VERA_ADDR_L + lda cx16.r0+1 + sta cx16.VERA_ADDR_M + ldx p8v_xx + }} - repeat length { - %asm {{ - txa - and #3 - tay - lda cx16.VERA_DATA0 - and p8b_gfx2.p8s_plot.p8v_mask4c,y - ora p8v_colorbits,y - sta cx16.VERA_DATA0 - cpy #%00000011 ; next vera byte? - bne ++ - inc cx16.VERA_ADDR_L - bne ++ - inc cx16.VERA_ADDR_M + repeat length { + %asm {{ + txa + and #3 + tay + lda cx16.VERA_DATA0 + and p8b_gfx_hires4.p8s_plot.p8v_mask4c,y + ora p8v_colorbits,y + sta cx16.VERA_DATA0 + cpy #%00000011 ; next vera byte? + bne ++ + inc cx16.VERA_ADDR_L + bne ++ + inc cx16.VERA_ADDR_M + bne + - inc cx16.VERA_ADDR_H + inc cx16.VERA_ADDR_H + inx ; next pixel - }} - } - } + }} } } sub safe_horizontal_line(uword xx, uword yy, uword length, ubyte color) { ; does bounds checking and clipping - if msb(yy)&$80!=0 or yy>=height + if msb(yy)&$80!=0 or yy>=HEIGHT return if msb(xx)&$80!=0 { length += xx xx = 0 } - if xx>=width + if xx>=WIDTH return - if xx+length>width - length = width-xx - if length>width + if xx+length>WIDTH + length = WIDTH-xx + if length>WIDTH return horizontal_line(xx, yy, length, color) } sub vertical_line(uword xx, uword yy, uword lheight, ubyte color) { - when active_mode { - 1 -> { - ; lores 256c - ; set vera auto-increment to 320 pixel increment (=next line) - position(xx,yy) - cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & %00000111 | (14<<4) - %asm {{ - ldy p8v_lheight - beq + - lda p8v_color -- sta cx16.VERA_DATA0 - dey - bne - -+ - }} - } - 2 -> { - ; highres 4c - ; use TWO vera adress pointers simultaneously one for reading, one for writing, so auto-increment is possible - if lheight==0 - return - position2(xx,yy,true) - set_both_strides(13) ; 160 increment = 1 line in 640 px 4c mode - ;; color &= 3 - ;; color <<= gfx2.plot.shift4c[lsb(xx) & 3] - cx16.r2L = lsb(xx) & 3 - when color & 3 { - 0 -> color = 0 - 1 -> color = gfx2.plot.shiftedleft_4c_1[cx16.r2L] - 2 -> color = gfx2.plot.shiftedleft_4c_2[cx16.r2L] - 3 -> color = gfx2.plot.shiftedleft_4c_3[cx16.r2L] - } - ubyte @shared mask = gfx2.plot.mask4c[lsb(xx) & 3] - repeat lheight { - %asm {{ - lda cx16.VERA_DATA0 - and p8v_mask - ora p8v_color - sta cx16.VERA_DATA1 - }} - } - } + ; highres 4c + ; use TWO vera adress pointers simultaneously one for reading, one for writing, so auto-increment is possible + if lheight==0 + return + position2(xx,yy,true) + set_both_strides(13) ; 160 increment = 1 line in 640 px 4c mode + ;; color &= 3 + ;; color <<= gfx2.plot.shift4c[lsb(xx) & 3] + cx16.r2L = lsb(xx) & 3 + when color & 3 { + 0 -> color = 0 + 1 -> color = gfx_hires4.plot.shiftedleft_4c_1[cx16.r2L] + 2 -> color = gfx_hires4.plot.shiftedleft_4c_2[cx16.r2L] + 3 -> color = gfx_hires4.plot.shiftedleft_4c_3[cx16.r2L] + } + ubyte @shared mask = gfx_hires4.plot.mask4c[lsb(xx) & 3] + repeat lheight { + %asm {{ + lda cx16.VERA_DATA0 + and p8v_mask + ora p8v_color + sta cx16.VERA_DATA1 + }} } sub set_both_strides(ubyte stride) { @@ -327,17 +215,17 @@ gfx2 { sub safe_vertical_line(uword xx, uword yy, uword lheight, ubyte color) { ; does bounds checking and clipping - if msb(yy)&$80!=0 or yy>=height + if msb(yy)&$80!=0 or yy>=HEIGHT return - if msb(xx)&$80!=0 or xx>=width + if msb(xx)&$80!=0 or xx>=WIDTH return if msb(yy)&$80!=0 { lheight += yy yy = 0 } - if yy+lheight>height - lheight = height-yy - if lheight>height + if yy+lheight>HEIGHT + lheight = HEIGHT-yy + if lheight>HEIGHT return vertical_line(xx, yy, lheight, color) @@ -622,107 +510,68 @@ gfx2 { ubyte[4] shiftedleft_4c_2 = [2<<6, 2<<4, 2<<2, 2<<0] ubyte[4] shiftedleft_4c_3 = [3<<6, 3<<4, 3<<2, 3<<0] - when active_mode { - 1 -> { - ; lores 256c - void addr_mul_24_for_lores_256c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) - %asm {{ - stz cx16.VERA_CTRL - lda cx16.r1 - ora #%00010000 ; enable auto-increment so next_pixel() can be used after this - sta cx16.VERA_ADDR_H - lda cx16.r0+1 - sta cx16.VERA_ADDR_M - lda cx16.r0 - sta cx16.VERA_ADDR_L - lda p8v_color - sta cx16.VERA_DATA0 - }} - } - 2 -> { - ; highres 4c ....also mostly usable for lores 4c? - void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) - cx16.r2L = lsb(xx) & 3 ; xbits - ; color &= 3 - ; color <<= shift4c[cx16.r2L] - when color & 3 { - 0 -> color = 0 - 1 -> color = shiftedleft_4c_1[cx16.r2L] - 2 -> color = shiftedleft_4c_2[cx16.r2L] - 3 -> color = shiftedleft_4c_3[cx16.r2L] - } - %asm {{ - stz cx16.VERA_CTRL - lda cx16.r1L - sta cx16.VERA_ADDR_H - lda cx16.r0H - sta cx16.VERA_ADDR_M - lda cx16.r0L - sta cx16.VERA_ADDR_L - ldy cx16.r2L ; xbits - lda p8v_mask4c,y - and cx16.VERA_DATA0 - ora p8v_color - sta cx16.VERA_DATA0 - }} - } + ; highres 4c ....also mostly usable for lores 4c? + void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) + cx16.r2L = lsb(xx) & 3 ; xbits + ; color &= 3 + ; color <<= shift4c[cx16.r2L] + when color & 3 { + 0 -> color = 0 + 1 -> color = shiftedleft_4c_1[cx16.r2L] + 2 -> color = shiftedleft_4c_2[cx16.r2L] + 3 -> color = shiftedleft_4c_3[cx16.r2L] } + %asm {{ + stz cx16.VERA_CTRL + lda cx16.r1L + sta cx16.VERA_ADDR_H + lda cx16.r0H + sta cx16.VERA_ADDR_M + lda cx16.r0L + sta cx16.VERA_ADDR_L + ldy cx16.r2L ; xbits + lda p8v_mask4c,y + and cx16.VERA_DATA0 + ora p8v_color + sta cx16.VERA_DATA0 + }} } 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 + if xx >= WIDTH or yy >= HEIGHT return plot(xx, yy, color) } sub pget(uword @zp xx, uword yy) -> ubyte { - when active_mode { - 1 -> { - ; lores 256c - void addr_mul_24_for_lores_256c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) - %asm {{ - stz cx16.VERA_CTRL - lda cx16.r1 - sta cx16.VERA_ADDR_H - lda cx16.r0+1 - sta cx16.VERA_ADDR_M - lda cx16.r0 - sta cx16.VERA_ADDR_L - lda cx16.VERA_DATA0 - }} - } - 2 -> { - ; hires 4c - void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) - %asm {{ - stz cx16.VERA_CTRL - lda cx16.r1L - sta cx16.VERA_ADDR_H - lda cx16.r0H - sta cx16.VERA_ADDR_M - lda cx16.r0L - sta cx16.VERA_ADDR_L - lda cx16.VERA_DATA0 - pha - lda p8v_xx - and #3 - tay - lda p8b_gfx2.p8s_plot.p8v_shift4c,y - tay - pla - cpy #0 - beq + -- lsr a - dey - bne - -+ and #3 - }} - } - else -> return 0 - } + void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) + %asm {{ + stz cx16.VERA_CTRL + lda cx16.r1L + sta cx16.VERA_ADDR_H + lda cx16.r0H + sta cx16.VERA_ADDR_M + lda cx16.r0L + sta cx16.VERA_ADDR_L + lda cx16.VERA_DATA0 + pha + lda p8v_xx + and #3 + tay + lda p8b_gfx_hires4.p8s_plot.p8v_shift4c,y + tay + pla + cpy #0 + beq + +- lsr a + dey + bne - ++ and #3 + rts + }} } sub fill(uword x, uword y, ubyte new_color) { @@ -754,7 +603,7 @@ gfx2 { if cx16.r12L==MAXDEPTH return cx16.r0s = sy+sdy - if cx16.r0s>=0 and cx16.r0s<=height-1 { + if cx16.r0s>=0 and cx16.r0s<=HEIGHT-1 { ;; stack_xl[cx16.r12L] = sxl ;; stack_xr[cx16.r12L] = sxr ;; stack_y[cx16.r12L] = sy @@ -811,29 +660,23 @@ gfx2 { cx16.r11L = pget(xx as uword, yy as uword) ; old_color if cx16.r11L == cx16.r10L return - if xx<0 or xx>width-1 or yy<0 or yy>height-1 + if xx<0 or xx>WIDTH-1 or yy<0 or yy>HEIGHT-1 return - if gfx2.active_mode == 2 set_color_masks() + set_color_masks() push_stack(xx, xx, yy, 1) push_stack(xx, xx, yy + 1, -1) word left = 0 while cx16.r12L!=0 { pop_stack() xx = x1 - when active_mode { - 1 -> if fill_scanline_left_8bpp() goto skip - 2 -> if fill_scanline_left_2bpp() goto skip - } + if fill_scanline_left_2bpp() goto skip left = xx + 1 if left < x1 push_stack(left, x1 - 1, yy, -dy) xx = x1 + 1 do { - when active_mode { - 1 -> fill_scanline_right_8bpp() - 2 -> fill_scanline_right_2bpp() - } + fill_scanline_right_2bpp() push_stack(left, xx - 1, yy, dy) if xx > x2 + 1 push_stack(x2 + 1, xx - 1, yy, -dy) @@ -859,35 +702,9 @@ skip: cx16.VERA_CTRL = 0 } - sub fill_scanline_left_8bpp() -> bool { - void addr_mul_24_for_lores_256c(yy as uword, xx as uword) ; 24 bits result is in r0 and r1L (highest byte) - cx16.r1L |= %00011000 ; auto decrement enabled - set_vera_address() - cx16.r9s = xx - while xx >= 0 { - if cx16.VERA_DATA0 != cx16.r11L - break - cx16.VERA_DATA1 = cx16.r10L - xx-- - } - return xx==cx16.r9s - } - - sub fill_scanline_right_8bpp() { - void addr_mul_24_for_lores_256c(yy as uword, xx as uword) ; 24 bits result is in r0 and r1L (highest byte) - cx16.r1L |= %00010000 ; auto increment enabled - set_vera_address() - while xx <= width-1 { - if cx16.VERA_DATA0 != cx16.r11L - break - cx16.VERA_DATA1 = cx16.r10L - xx++ - } - } - sub fill_scanline_left_2bpp() -> bool { uword vx = xx as uword - void gfx2.addr_mul_24_for_highres_4c(yy as uword,vx) + void gfx_hires4.addr_mul_24_for_highres_4c(yy as uword,vx) cx16.r1L |= %0001_1000 ; auto decrement set_vera_address() cmask = amask[lsb(vx) & 3] ; set the color mask for the first color pel @@ -931,7 +748,7 @@ set_byte: } sub fill_scanline_right_2bpp() { - void gfx2.addr_mul_24_for_highres_4c(yy as uword,xx as uword) + void gfx_hires4.addr_mul_24_for_highres_4c(yy as uword,xx as uword) cx16.r1L |= %00010000 ; auto increment set_vera_address() cmask = amask[lsb(xx) & 3] ; set the color mask for the first color pel @@ -965,7 +782,7 @@ set_byte: } set_byte: cx16.VERA_DATA1 = nvub - if xx >= gfx2.width-1 break + if xx >= WIDTH-1 break cmask = $C0 } } @@ -977,16 +794,7 @@ set_byte: } sub position(uword @zp xx, uword yy) { - when active_mode { - 1 -> { - ; lores 256c - void addr_mul_24_for_lores_256c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) - } - 2 -> { - ; highres 4c - void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) - } - } + void addr_mul_24_for_highres_4c(yy, xx) ; 24 bits result is in r0 and r1L (highest byte) cx16.r2L = cx16.r1L cx16.vaddr(cx16.r2L, cx16.r0, 0, 1) } @@ -1068,83 +876,36 @@ set_byte: ubyte[8] @shared char_bitmap_bytes_left ubyte[8] @shared char_bitmap_bytes_right - when active_mode { - 1 -> { - ; lores 256c - while @(sctextptr)!=0 { - chardataptr = charset_addr + (@(sctextptr) as uword)*8 - cx16.vaddr(charset_bank, chardataptr, 1, 1) - repeat 8 { - position(xx,yy) - yy++ - %asm {{ - ldx p8v_color - lda cx16.VERA_DATA1 - sta P8ZP_SCRATCH_B1 - ldy #8 -- asl P8ZP_SCRATCH_B1 - bcc + - stx cx16.VERA_DATA0 ; write a pixel - bra ++ -+ lda cx16.VERA_DATA0 ; don't write a pixel, but do advance to the next address -+ dey - bne - - }} - } - xx+=8 - yy-=8 - sctextptr++ - } - } - 2 -> { - ; hires 4c - ; we're going to use a few cx16 registers to make sure every variable is in zeropage in the inner loop. - cx16.r11L = color - while @(sctextptr)!=0 { - chardataptr = charset_addr + (@(sctextptr) as uword)*8 - cx16.vaddr(charset_bank, chardataptr, 1, 1) ; for reading the chardata from Vera data channel 1 - position(xx, yy) ; only calculated once, we update vera address in the loop instead - cx16.VERA_ADDR_H &= $0f ; no auto increment - repeat 8 { - cx16.r10L = cx16.VERA_DATA1 ; get the next 8 horizontal character bits - cx16.r7 = xx - repeat 8 { - cx16.r10L <<= 1 - if_cs { - cx16.r2L = cx16.r7L & 3 ; xbits - when cx16.r11L & 3 { - 1 -> cx16.r12L = gfx2.plot.shiftedleft_4c_1[cx16.r2L] - 2 -> cx16.r12L = gfx2.plot.shiftedleft_4c_2[cx16.r2L] - 3 -> cx16.r12L = gfx2.plot.shiftedleft_4c_3[cx16.r2L] - else -> cx16.r12L = 0 - } - cx16.VERA_DATA0 = cx16.VERA_DATA0 & gfx2.plot.mask4c[cx16.r2L] | cx16.r12L - } - cx16.r7++ - if (cx16.r7 & 3) == 0 { - ; increment the pixel address by one - %asm {{ - stz cx16.VERA_CTRL - clc - lda cx16.VERA_ADDR_L - adc #1 - sta cx16.VERA_ADDR_L - lda cx16.VERA_ADDR_M - adc #0 - sta cx16.VERA_ADDR_M - lda cx16.VERA_ADDR_H - adc #0 - sta cx16.VERA_ADDR_H - }} - } + ; we're going to use a few cx16 registers to make sure every variable is in zeropage in the inner loop. + cx16.r11L = color + while @(sctextptr)!=0 { + chardataptr = charset_addr + (@(sctextptr) as uword)*8 + cx16.vaddr(charset_bank, chardataptr, 1, 1) ; for reading the chardata from Vera data channel 1 + position(xx, yy) ; only calculated once, we update vera address in the loop instead + cx16.VERA_ADDR_H &= $0f ; no auto increment + repeat 8 { + cx16.r10L = cx16.VERA_DATA1 ; get the next 8 horizontal character bits + cx16.r7 = xx + repeat 8 { + cx16.r10L <<= 1 + if_cs { + cx16.r2L = cx16.r7L & 3 ; xbits + when cx16.r11L & 3 { + 1 -> cx16.r12L = gfx_hires4.plot.shiftedleft_4c_1[cx16.r2L] + 2 -> cx16.r12L = gfx_hires4.plot.shiftedleft_4c_2[cx16.r2L] + 3 -> cx16.r12L = gfx_hires4.plot.shiftedleft_4c_3[cx16.r2L] + else -> cx16.r12L = 0 } - - ; increment pixel address to the next line + cx16.VERA_DATA0 = cx16.VERA_DATA0 & gfx_hires4.plot.mask4c[cx16.r2L] | cx16.r12L + } + cx16.r7++ + if (cx16.r7 & 3) == 0 { + ; increment the pixel address by one %asm {{ stz cx16.VERA_CTRL clc lda cx16.VERA_ADDR_L - adc #(640-8)/4 + adc #1 sta cx16.VERA_ADDR_L lda cx16.VERA_ADDR_M adc #0 @@ -1154,10 +915,25 @@ set_byte: sta cx16.VERA_ADDR_H }} } - xx+=8 - sctextptr++ } + + ; increment pixel address to the next line + %asm {{ + stz cx16.VERA_CTRL + clc + lda cx16.VERA_ADDR_L + adc #(640-8)/4 + sta cx16.VERA_ADDR_L + lda cx16.VERA_ADDR_M + adc #0 + sta cx16.VERA_ADDR_M + lda cx16.VERA_ADDR_H + adc #0 + sta cx16.VERA_ADDR_H + }} } + xx+=8 + sctextptr++ } } @@ -1228,50 +1004,4 @@ set_byte: rts }} } - - asmsub addr_mul_24_for_lores_256c(uword yy @R0, uword xx @AY) clobbers(A) -> uword @R0, ubyte @R1 { - ; yy * 320 + xx (24 bits calculation) - %asm {{ - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda cx16.r0 - sta P8ZP_SCRATCH_B1 - lda cx16.r0+1 - sta cx16.r1 - sta P8ZP_SCRATCH_REG - lda cx16.r0 - asl a - rol P8ZP_SCRATCH_REG - asl a - rol P8ZP_SCRATCH_REG - asl a - rol P8ZP_SCRATCH_REG - asl a - rol P8ZP_SCRATCH_REG - asl a - rol P8ZP_SCRATCH_REG - asl a - rol P8ZP_SCRATCH_REG - sta cx16.r0 - lda P8ZP_SCRATCH_B1 - clc - adc P8ZP_SCRATCH_REG - sta cx16.r0+1 - bcc + - inc cx16.r1 -+ ; now add the value to this 24-bits number - lda cx16.r0 - clc - adc P8ZP_SCRATCH_W1 - sta cx16.r0 - lda cx16.r0+1 - adc P8ZP_SCRATCH_W1+1 - sta cx16.r0+1 - bcc + - inc cx16.r1 -+ lda cx16.r1 - rts - }} - } - } diff --git a/compiler/res/prog8lib/cx16/verafx.p8 b/compiler/res/prog8lib/cx16/verafx.p8 index 3bf1e0bd4..7812a6aef 100644 --- a/compiler/res/prog8lib/cx16/verafx.p8 +++ b/compiler/res/prog8lib/cx16/verafx.p8 @@ -28,7 +28,7 @@ verafx { sub clear(ubyte vbank, uword vaddr, ubyte data, uword num_longwords) { ; use cached 4-byte write to quickly clear a portion of the video memory to a given byte value - ; this routine is around 3 times faster as gfx2.clear_screen() + ; this routine is around 3 times faster as gfx_hires4/gfx_lores.clear_screen() cx16.VERA_CTRL = 0 cx16.VERA_ADDR_H = vbank | %00110000 ; 4-byte increment cx16.VERA_ADDR_M = msb(vaddr) diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 30ed22b75..530329da2 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -142,7 +142,8 @@ class TestCompilerOnExamplesCx16: FunSpec({ "spotlight", "starszoom", "tehtriz", - "testgfx2", + "test_gfx_lores", + "test_gfx_hires4", "testmonogfx", ), listOf(false, true) diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 75cff6445..51b9bec59 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -687,7 +687,7 @@ Bitmap graphics routines: This library is available both on the C64 and the cx16. It uses the ROM based graphics routines on the latter, and it is a very small library because of that. -On the cx16 there's also the ``gfx2`` library if you want more features and different screen modes. See below for that one. +On the cx16 there's also various other graphics modules if you want more features and different screen modes. See below for those. Read the `graphics source code `_ to see what's in there. (Note: slight variations for different compiler targets) @@ -899,9 +899,9 @@ Information about the exposed debug registers is in the `emulator's documentatio monogfx (cx16 and virtual) --------------------------- Full-screen lores or hires monochrome bitmap graphics routines, available on the Cx16 machine only. -Same interface as gfx2, but is optimized for monochrome (1 bpp) screens. -- lores 320*240 or hires 640*480 bitmap mode, monochrome +- two resolutions: lores 320*240 or hires 640*480 bitmap mode +- optimized routines for monochrome (2-color) graphics - clearing screen, switching screen mode, also back to text mode - drawing and reading individual pixels - drawing lines, rectangles, filled rectangles, circles, discs @@ -913,30 +913,25 @@ Read the `monogfx source code `_ -to see what's in there. - - -gfx_lores (cx16 only) ----------------------- -Heavily optimized graphics routines for just the single screen mode: lores 320*240, 256c (8bpp) -This is screen mode 1 from the gfx2 module (and also compatible with X16's basic screen mode 128). - Read the `gfx_lores source code `_ +or `gfx_hires4 source code `_ to see what's in there. +They share the same routines. + palette (cx16 only) -------------------- diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 6a520349e..5d1978cbb 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,8 +1,7 @@ TODO ==== -Transform gfx2 into gfx_hires -Add a eor mode to gfx_lores / gfx_hires +Add a eor mode to gfx_lores / gfx_hires. Once that's done in gfx_lores, convert Paint to use this module Improve register load order in subroutine call args assignments: in certain situations, the "wrong" order of evaluation of function call arguments is done which results @@ -53,7 +52,6 @@ Future Things and Ideas Libraries: -- gfx2: add EOR mode support like in monogfx and see PAINT for inspiration. Self modifying code to keep it optimized? - fix the problems in atari target, and flesh out its libraries. - c128 target: make syslib more complete (missing kernal routines)? - pet32 target: make syslib more complete (missing kernal routines)? diff --git a/examples/cx16/amiga.p8 b/examples/cx16/amiga.p8 index e71cd60f7..d482ebf3c 100644 --- a/examples/cx16/amiga.p8 +++ b/examples/cx16/amiga.p8 @@ -1,38 +1,38 @@ %import textio %import palette %import string -%import gfx2 +%import gfx_hires4 ; Mockup of a classic Amiga Workbench screen. main { sub start() { - gfx2.screen_mode(2) ; select 640*480 mode, 4 colors + gfx_hires4.graphics_mode() ; select 640*480 mode, 4 colors mouse.set_pointer_image() cx16.mouse_config(-1, 640/8, 240/8) uword[4] amigacolors = [$aaa, $000, $fff, $68c] ; gray, black, white, lightblue palette.set_rgb(amigacolors, len(amigacolors)) cx16.VERA_DC_VSCALE = 64 ; have the vertical resolution so it is 640*240 - more or less Amiga's default non interlaced mode - gfx2.text_charset(1) + gfx_hires4.text_charset(1) screen_titlebar() window_workbench() window_system() window_shell() - gfx2.text(280, 210, 1, iso:"640x480(240) 4 colors") - gfx2.text(280, 220, 1, iso:"Mockup drawn using Prog8 gfx2 library") + gfx_hires4.text(240, 210, 1, iso:"640x480(240) 4 colors") + gfx_hires4.text(240, 220, 1, iso:"Mockup drawn using Prog8 gfx_hires4 library") repeat { } } sub screen_titlebar() { - gfx2.fillrect(0, 0, gfx2.width, 10, 2) - gfx2.text(8,1, 1, iso:"AmigaOS 3.1 2,002,448 graphics mem 16,504,384 other mem") - gfx2.horizontal_line(0, 10, gfx2.width, 1) - widget.window_order_icon(gfx2.width-widget.window_order_icon.width, 0, false) + gfx_hires4.fillrect(0, 0, gfx_hires4.WIDTH, 10, 2) + gfx_hires4.text(8,1, 1, iso:"AmigaOS 3.1 2,002,448 graphics mem 16,504,384 other mem") + gfx_hires4.horizontal_line(0, 10, gfx_hires4.WIDTH, 1) + widget.window_order_icon(gfx_hires4.WIDTH-widget.window_order_icon.width, 0, false) } @@ -43,25 +43,25 @@ main { const uword height = 220 widget.window_titlebar(win_x, win_y, width, iso:"Workbench", false) - ; gfx2.fillrect(win_x+3, win_y+11, width-4, height-11-2,0) ; clear window pane + ; gfx_hires4.fillrect(win_x+3, win_y+11, width-4, height-11-2,0) ; clear window pane widget.window_leftborder(win_x, win_y, height, false) widget.window_bottomborder(win_x, win_y, width, height) widget.window_rightborder(win_x, win_y, width, height, false) - vector_v(win_x+width - 390, win_y+height-20) - vector_v(win_x+width - 390 -14, win_y+height-20) + vector_v(win_x+width - 430, win_y+height-20) + vector_v(win_x+width - 430 -14, win_y+height-20) widget.icon(45,40, iso:"Ram Disk") widget.icon(45,90, iso:"Workbench3.1") } sub vector_v(uword x, uword y) { - gfx2.horizontal_line(x, y, 12, 1) - gfx2.horizontal_line(x+16, y+16, 11,1) - gfx2.line(x,y,x+16,y+16,1) - gfx2.line(x+11,y,x+16+5,y+10,1) - gfx2.line(x+16+5,y+10,x+47,y-16,1) - gfx2.line(x+16+10,y+16,x+46+12,y-16,1) + gfx_hires4.horizontal_line(x, y, 12, 1) + gfx_hires4.horizontal_line(x+16, y+16, 11,1) + gfx_hires4.line(x,y,x+16,y+16,1) + gfx_hires4.line(x+11,y,x+16+5,y+10,1) + gfx_hires4.line(x+16+5,y+10,x+47,y-16,1) + gfx_hires4.line(x+16+10,y+16,x+46+12,y-16,1) } sub window_system() { @@ -71,7 +71,7 @@ main { const uword win_y = 40 widget.window_titlebar(win_x, win_y, width, iso:"System", false) - gfx2.fillrect(win_x+3, win_y+11, width-4, height-11-2, 0) ; clear window pane + gfx_hires4.fillrect(win_x+3, win_y+11, width-4, height-11-2, 0) ; clear window pane widget.window_leftborder(win_x, win_y, height, false) widget.window_bottomborder(win_x, win_y, width, height) widget.window_rightborder(win_x, win_y, width, height, false) @@ -90,14 +90,14 @@ main { const uword height = 65 widget.window_titlebar(win_x, win_y, width, iso:"AmigaShell", true) - gfx2.fillrect(win_x+3, win_y+11, width-4, height-11-2,0) ; clear window pane + gfx_hires4.fillrect(win_x+3, win_y+11, width-4, height-11-2,0) ; clear window pane widget.window_leftborder(win_x, win_y, height, true) widget.window_bottomborder(win_x, win_y, width, height) widget.window_rightborder(win_x, win_y, width, height, true) - gfx2.text(win_x+5, win_y+12, 1, iso:"New Shell process 3") - gfx2.text(win_x+5, win_y+12+8, 1, iso:"3.Workbench3.1:>") - gfx2.fillrect(win_x+5+17*8, win_y+12+8, 8, 8, 1) ; cursor + gfx_hires4.text(win_x+5, win_y+12, 1, iso:"New Shell process 3") + gfx_hires4.text(win_x+5, win_y+12+8, 1, iso:"3.Workbench3.1:>") + gfx_hires4.fillrect(win_x+5+17*8, win_y+12+8, 8, 8, 1) ; cursor } } @@ -147,15 +147,15 @@ mouse { widget { sub highlightedrect(uword x, uword y, uword width, uword height, bool fill, bool active) { - gfx2.horizontal_line(x, y, width, 2) - gfx2.vertical_line(x, y+1, height-1, 2) - gfx2.vertical_line(x+width-1, y+1, height-1, 1) - gfx2.horizontal_line(x+1, y+height-1, width-2, 1) + gfx_hires4.horizontal_line(x, y, width, 2) + gfx_hires4.vertical_line(x, y+1, height-1, 2) + gfx_hires4.vertical_line(x+width-1, y+1, height-1, 1) + gfx_hires4.horizontal_line(x+1, y+height-1, width-2, 1) if fill { if active - gfx2.fillrect(x+1,y+1,width-2,height-2, 3) + gfx_hires4.fillrect(x+1,y+1,width-2,height-2, 3) else - gfx2.fillrect(x+1,y+1,width-2,height-2, 0) + gfx_hires4.fillrect(x+1,y+1,width-2,height-2, 0) } } @@ -165,17 +165,17 @@ widget { highlightedrect(x, y, width, height, false, false) uword middlex = x+width/2+1 ubyte halfstring = string.length(caption) * 4 - gfx2.text(middlex-halfstring,y+height+1,1,caption) - gfx2.disc(x+width/4+4, y+height/2, height/2-3, 1) - gfx2.fillrect(x+20,y+12,width/2,height/2-4,3) + gfx_hires4.text(middlex-halfstring,y+height+1,1,caption) + gfx_hires4.disc(x+width/4+4, y+height/2, height/2-3, 1) + gfx_hires4.fillrect(x+20,y+12,width/2,height/2-4,3) } sub window_titlebar(uword x, uword y, uword width, uword titlestr, bool active) { const ubyte height = 11 widget.highlightedrect(x+widget.window_close_icon.width, y, width-64, height, true, active) - gfx2.plot(x+widget.window_close_icon.width, y+height-1, 1) ; correct bottom left corner - gfx2.text(x+26, y+1, 1, titlestr) + gfx_hires4.plot(x+widget.window_close_icon.width, y+height-1, 1) ; correct bottom left corner + gfx_hires4.text(x+26, y+1, 1, titlestr) widget.window_close_icon(x, y, active) widget.window_order_icon(x+width-22, y, active) widget.window_flipsize_icon(x+width-44, y, active) @@ -185,66 +185,66 @@ widget { const uword width = 22 const uword height = 11 highlightedrect(x, y, width, height, true, active) - gfx2.plot(x, y+height-1, 1) ; correct bottom left corner - gfx2.rect(x+5, y+2, width-9, height-4, 1) - gfx2.rect(x+5, y+2, 7, 4, 1) - gfx2.fillrect(x+6, y+3, 5, 2, 2) + gfx_hires4.plot(x, y+height-1, 1) ; correct bottom left corner + gfx_hires4.rect(x+5, y+2, width-9, height-4, 1) + gfx_hires4.rect(x+5, y+2, 7, 4, 1) + gfx_hires4.fillrect(x+6, y+3, 5, 2, 2) } sub window_order_icon(uword x, uword y, bool active) { const uword width = 22 const uword height = 11 highlightedrect(x, y, width, height, true, active) - gfx2.plot(x, y+height-1, 1) ; correct bottom left corner - gfx2.rect(x+4, y+2, 10, 5, 1) ; back - gfx2.fillrect(x+9, y+5, 8, 3, 2) ; white front - gfx2.rect(x+8, y+4, 10, 5, 1) ; front + gfx_hires4.plot(x, y+height-1, 1) ; correct bottom left corner + gfx_hires4.rect(x+4, y+2, 10, 5, 1) ; back + gfx_hires4.fillrect(x+9, y+5, 8, 3, 2) ; white front + gfx_hires4.rect(x+8, y+4, 10, 5, 1) ; front } sub window_close_icon(uword x, uword y, bool active) { const uword width = 20 const uword height = 11 highlightedrect(x, y, width, height, true, active) - gfx2.plot(x, y+height-1, 1) ; correct bottom left corner - gfx2.rect(x+7, y+3, 5, 5, 1) - gfx2.fillrect(x+8, y+4, 3, 3, 2) + gfx_hires4.plot(x, y+height-1, 1) ; correct bottom left corner + gfx_hires4.rect(x+7, y+3, 5, 5, 1) + gfx_hires4.fillrect(x+8, y+4, 3, 3, 2) } sub window_leftborder(uword x, uword y, uword height, bool active) { - gfx2.vertical_line(x, y, height, 2) + gfx_hires4.vertical_line(x, y, height, 2) ubyte color = 0 if active color = 3 - gfx2.vertical_line(x+1, y+11, height-11, color) - gfx2.vertical_line(x+2, y+11, height-11, 1) + gfx_hires4.vertical_line(x+1, y+11, height-11, color) + gfx_hires4.vertical_line(x+2, y+11, height-11, 1) } sub window_bottomborder(uword x, uword y, uword width, uword height) { - gfx2.horizontal_line(x+3, y+height-2, width-3, 2) - gfx2.horizontal_line(x, y+height-1, width, 1) + gfx_hires4.horizontal_line(x+3, y+height-2, width-3, 2) + gfx_hires4.horizontal_line(x, y+height-1, width, 1) } sub window_rightborder(uword x, uword y, uword width, uword height, bool active) { - gfx2.vertical_line(x+width-1-16, y+11, height-13,2) - gfx2.vertical_line(x+width-1, y+11, height-11,1) + gfx_hires4.vertical_line(x+width-1-16, y+11, height-13,2) + gfx_hires4.vertical_line(x+width-1, y+11, height-11,1) ubyte color = 0 if active color = 3 - gfx2.fillrect(x+width-1-15, y+11, 15, height-12, color) + gfx_hires4.fillrect(x+width-1-15, y+11, 15, height-12, color) - gfx2.horizontal_line(x+width-1-13, y+height-3, 11, 1) - gfx2.vertical_line(x+width-1-3, y+height-3-5, 5, 1) - gfx2.line(x+width-1-13,y+height-3, x+width-1-3, y+height-3-5, 1) - gfx2.horizontal_line(x+width-1-16, y+height-10, 16, 2) + gfx_hires4.horizontal_line(x+width-1-13, y+height-3, 11, 1) + gfx_hires4.vertical_line(x+width-1-3, y+height-3-5, 5, 1) + gfx_hires4.line(x+width-1-13,y+height-3, x+width-1-3, y+height-3-5, 1) + gfx_hires4.horizontal_line(x+width-1-16, y+height-10, 16, 2) highlightedrect(x+width-13, y+12, 10, height-43, false, false) - gfx2.horizontal_line(x+width-1-16, y+height-11, 16, 1) - gfx2.horizontal_line(x+width-1-16, y+height-20, 16, 2) - gfx2.horizontal_line(x+width-1-16, y+height-21, 16, 1) - gfx2.horizontal_line(x+width-1-16, y+height-30, 16, 2) - gfx2.line(x+width-1-13, y+height-23, x+width-9, y+height-28, 1) - gfx2.line(x+width-1-3, y+height-23, x+width-9, y+height-28, 1) - gfx2.line(x+width-1-13, y+height-18, x+width-9, y+height-13, 1) - gfx2.line(x+width-1-3, y+height-18, x+width-9, y+height-13, 1) + gfx_hires4.horizontal_line(x+width-1-16, y+height-11, 16, 1) + gfx_hires4.horizontal_line(x+width-1-16, y+height-20, 16, 2) + gfx_hires4.horizontal_line(x+width-1-16, y+height-21, 16, 1) + gfx_hires4.horizontal_line(x+width-1-16, y+height-30, 16, 2) + gfx_hires4.line(x+width-1-13, y+height-23, x+width-9, y+height-28, 1) + gfx_hires4.line(x+width-1-3, y+height-23, x+width-9, y+height-28, 1) + gfx_hires4.line(x+width-1-13, y+height-18, x+width-9, y+height-13, 1) + gfx_hires4.line(x+width-1-3, y+height-18, x+width-9, y+height-13, 1) } } diff --git a/examples/cx16/circles.p8 b/examples/cx16/circles.p8 index 3aa639e8a..6ff1353d4 100644 --- a/examples/cx16/circles.p8 +++ b/examples/cx16/circles.p8 @@ -1,4 +1,4 @@ -%import gfx2 +%import gfx_lores %import math @@ -12,11 +12,11 @@ main { ubyte background_color sub start() { - gfx2.screen_mode(1) + gfx_lores.graphics_mode() repeat { background_color = math.rnd() - gfx2.clear_screen(background_color) + gfx_lores.clear_screen(background_color) num_circles = 0 draw_circles() } @@ -28,8 +28,8 @@ main { ubyte @zp radius while num_circles bool { if x as word - radius < 0 return false - if x + radius >= gfx2.width + if x + radius >= gfx_lores.WIDTH return false if y as word - radius < 0 return false - if y + radius >= gfx2.height + if y + radius >= gfx_lores.HEIGHT return false return true } diff --git a/examples/cx16/kefrenbars.p8 b/examples/cx16/kefrenbars.p8 index 26bee4a3e..abc5d999f 100644 --- a/examples/cx16/kefrenbars.p8 +++ b/examples/cx16/kefrenbars.p8 @@ -1,6 +1,6 @@ %import palette %import math -%import gfx2 +%import gfx_lores %option no_sysinit ; Vertical rasterbars a.k.a. "Kefren bars" @@ -22,7 +22,7 @@ main { ] palette.set_rgb(&colors, len(colors)) - gfx2.screen_mode(1) ; lores 256 colors + gfx_lores.graphics_mode() ; lores 256 colors cx16.VERA_DC_VSCALE = 0 ; display trick spoiler.......: stretch 1 line of display all the way to the bottom cx16.enable_irq_handlers(true) cx16.set_line_irq_handler(0, &irq.irqhandler) @@ -54,15 +54,15 @@ irq { anim2 = av2 next_irq_line = 0 ; erase the bars - gfx2.horizontal_line(0, 0, 320, 3) -; gfx2.position(0, 0) + gfx_lores.horizontal_line(0, 0, 320, 3) +; gfx_lores.position(0, 0) ; repeat 10 { -; gfx2.next_pixels(pixels, len(pixels)) +; gfx_lores.next_pixels(pixels, len(pixels)) ; } } else { ; add new bar on top - gfx2.position(math.sin8u(anim1)/2 + math.cos8u(anim2)/2 + $0010, 0) - gfx2.next_pixels(pixels, len(pixels)) + gfx_lores.position(math.sin8u(anim1)/2 + math.cos8u(anim2)/2 + $0010, 0) + gfx_lores.next_pixels(pixels, len(pixels)) } sys.set_rasterline(next_irq_line) diff --git a/examples/cx16/snow.p8 b/examples/cx16/snow.p8 index 5e2a36d14..babf6af02 100644 --- a/examples/cx16/snow.p8 +++ b/examples/cx16/snow.p8 @@ -1,21 +1,21 @@ %import math -%import gfx2 +%import gfx_lores main { sub start() { - gfx2.screen_mode(1) + gfx_lores.graphics_mode() uword[128] @split flakes1_xx - uword[128] @split flakes1_yy + ubyte[128] flakes1_yy uword[128] @split flakes2_xx - uword[128] @split flakes2_yy + ubyte[128] flakes2_yy ubyte @zp idx for idx in 0 to 127 { flakes1_xx[idx] = math.rndw() % 320 - flakes1_yy[idx] = math.rndw() % 240 + flakes1_yy[idx] = math.rnd() % 240 flakes2_xx[idx] = math.rndw() % 320 - flakes2_yy[idx] = math.rndw() % 240 + flakes2_yy[idx] = math.rnd() % 240 } draw_screen() @@ -28,18 +28,19 @@ main { repeat { for idx in 0 to len(flakes1_xx)-1 { - gfx2.plot(flakes1_xx[idx], flakes1_yy[idx], FALLING_SNOW_COLOR) - gfx2.plot(flakes2_xx[idx], flakes2_yy[idx], FALLING_SNOW_COLOR2) + gfx_lores.plot(flakes1_xx[idx], flakes1_yy[idx], FALLING_SNOW_COLOR) + gfx_lores.plot(flakes2_xx[idx], flakes2_yy[idx], FALLING_SNOW_COLOR2) } sys.waitvsync() + sys.waitvsync() for idx in 0 to len(flakes1_xx)-1 { if flakes1_yy[idx]==239 { ; reached the floor - gfx2.plot(flakes1_xx[idx], flakes1_yy[idx], PILED_SNOW_COLOR) + gfx_lores.plot(flakes1_xx[idx], flakes1_yy[idx], PILED_SNOW_COLOR) flakes1_yy[idx] = 0 flakes1_xx[idx] = math.rndw() % 320 - } else if gfx2.pget(flakes1_xx[idx], flakes1_yy[idx]+1) in PILED_SNOW_COLORS { + } else if gfx_lores.pget(flakes1_xx[idx], flakes1_yy[idx]+1) in PILED_SNOW_COLORS { ; pile up ; TODO somehow prevent growing horizontally/diagonally like a crystal uword @zp snowx = flakes1_xx[idx] @@ -53,23 +54,23 @@ main { pilex1 = snowx+1 pilex2 = snowx-1 } - ubyte pixel_side1 = gfx2.pget(pilex1, flakes1_yy[idx]+1) - ubyte pixel_side2 = gfx2.pget(pilex2, flakes1_yy[idx]+1) + ubyte pixel_side1 = gfx_lores.pget(pilex1, flakes1_yy[idx]+1) + ubyte pixel_side2 = gfx_lores.pget(pilex2, flakes1_yy[idx]+1) if pixel_side1 == 0 or pixel_side1 == FALLING_SNOW_COLOR2 { - gfx2.plot(snowx, flakes1_yy[idx], 0) - gfx2.plot(pilex1, flakes1_yy[idx]+1, PILED_SNOW_COLOR) + gfx_lores.plot(snowx, flakes1_yy[idx], 0) + gfx_lores.plot(pilex1, flakes1_yy[idx]+1, PILED_SNOW_COLOR) } else if pixel_side2 == 0 or pixel_side2 == FALLING_SNOW_COLOR2 { - gfx2.plot(snowx, flakes1_yy[idx], 0) - gfx2.plot(pilex2, flakes1_yy[idx]+1, PILED_SNOW_COLOR) + gfx_lores.plot(snowx, flakes1_yy[idx], 0) + gfx_lores.plot(pilex2, flakes1_yy[idx]+1, PILED_SNOW_COLOR) } else { - gfx2.plot(snowx, flakes1_yy[idx], PILED_SNOW_COLOR) + gfx_lores.plot(snowx, flakes1_yy[idx], PILED_SNOW_COLOR) } } flakes1_yy[idx] = 0 flakes1_xx[idx] = math.rndw() % 320 } else { ; fall - gfx2.plot(flakes1_xx[idx], flakes1_yy[idx], 0) + gfx_lores.plot(flakes1_xx[idx], flakes1_yy[idx], 0) flakes1_yy[idx]++ when math.rnd() & 3 { 1 -> { @@ -93,13 +94,13 @@ main { ; reached the floor, don't pile up just fall again flakes2_yy[idx] = 0 flakes2_xx[idx] = math.rndw() % 320 - } else if gfx2.pget(flakes2_xx[idx], flakes2_yy[idx]+1) in PILED_SNOW_COLORS { + } else if gfx_lores.pget(flakes2_xx[idx], flakes2_yy[idx]+1) in PILED_SNOW_COLORS { ; reached an obstruction, don't pile up just fall again flakes2_yy[idx] = 0 flakes2_xx[idx] = math.rndw() % 320 } else { ; fall normally - gfx2.plot(flakes2_xx[idx], flakes2_yy[idx], 0) + gfx_lores.plot(flakes2_xx[idx], flakes2_yy[idx], 0) flakes2_yy[idx]+=1 when math.rnd() & 3 { 1 -> { @@ -121,10 +122,10 @@ main { } sub draw_screen() { - gfx2.text(32, 130, 2, sc: "******************" ) - gfx2.text(40, 140, 5, sc: "happy holidays !" ) - gfx2.text(32, 150, 5, sc: "from commander x16" ) - gfx2.text(32, 160, 2, sc: "******************" ) + gfx_lores.text(32, 130, 2, sc: "******************" ) + gfx_lores.text(40, 140, 5, sc: "happy holidays !" ) + gfx_lores.text(32, 150, 5, sc: "from commander x16" ) + gfx_lores.text(32, 160, 2, sc: "******************" ) ; draw a tree @@ -132,11 +133,11 @@ main { ubyte maxwidth = 20 ubyte branchesy = 100 - gfx2.fillrect(TREEX-5, 210, 10, 30, 9) + gfx_lores.fillrect(TREEX-5, 210, 10, 30, 9) repeat 5 { ubyte width for width in 1 to maxwidth { - gfx2.horizontal_line(TREEX-width/2, branchesy, width, 5) + gfx_lores.horizontal_line(TREEX-width/2, branchesy, width, 5) branchesy++ } branchesy -= maxwidth/2 diff --git a/examples/cx16/test_gfx_hires4.p8 b/examples/cx16/test_gfx_hires4.p8 new file mode 100644 index 000000000..aa10ca694 --- /dev/null +++ b/examples/cx16/test_gfx_hires4.p8 @@ -0,0 +1,73 @@ +%import gfx_hires4 +%import textio +%import math + +%option no_sysinit +%zeropage basicsafe + + +main { + + sub start() { + gfx_hires4.graphics_mode() + draw() + sys.wait(120) + gfx_hires4.text_mode() + txt.print("done!\n") + } + + sub draw() { + gfx_hires4.rect(10,10, 1, 1, 4) + gfx_hires4.rect(20,10, 2, 1, 4) + gfx_hires4.rect(30,10, 3, 1, 4) + gfx_hires4.rect(40,10, 1, 2, 4) + gfx_hires4.rect(50,10, 1, 3, 4) + gfx_hires4.rect(60,10, 2, 2, 4) + gfx_hires4.rect(70,10, 3, 3, 4) + gfx_hires4.rect(80,10, 4, 4, 4) + gfx_hires4.rect(90,10, 5, 5, 4) + gfx_hires4.rect(100,10, 8, 8, 4) + gfx_hires4.rect(110,10, 20, 5, 4) + gfx_hires4.rect(80, 80, 200, 140, 4) + + gfx_hires4.fillrect(10,40, 1, 1, 5) + gfx_hires4.fillrect(20,40, 2, 1, 5) + gfx_hires4.fillrect(30,40, 3, 1, 5) + gfx_hires4.fillrect(40,40, 1, 2, 5) + gfx_hires4.fillrect(50,40, 1, 3, 5) + gfx_hires4.fillrect(60,40, 2, 2, 5) + gfx_hires4.fillrect(70,40, 3, 3, 5) + gfx_hires4.fillrect(80,40, 4, 4, 5) + gfx_hires4.fillrect(90,40, 5, 5, 5) + gfx_hires4.fillrect(100,40, 8, 8, 5) + gfx_hires4.fillrect(110,40, 20, 5, 5) + gfx_hires4.fillrect(82, 82, 200-4, 140-4, 5) + + ubyte i + for i in 0 to 254 step 4 { + uword x1 = ((gfx_hires4.WIDTH-256)/2 as uword) + math.sin8u(i) + uword y1 = (gfx_hires4.HEIGHT-128)/2 + math.cos8u(i)/2 + uword x2 = ((gfx_hires4.WIDTH-64)/2 as uword) + math.sin8u(i)/4 + uword y2 = (gfx_hires4.HEIGHT-64)/2 + math.cos8u(i)/4 + gfx_hires4.line(x1, y1, x2, y2, i+1) + } + + sys.wait(60) + gfx_hires4.clear_screen(2) + gfx_hires4.clear_screen(0) + + ubyte radius + + for radius in 110 downto 8 step -4 { + gfx_hires4.circle(gfx_hires4.WIDTH/2, (gfx_hires4.HEIGHT/2 as ubyte), radius, radius) + } + + gfx_hires4.disc(gfx_hires4.WIDTH/2, gfx_hires4.HEIGHT/2, 80, 2) + + ubyte tp + for tp in 0 to 15 { + gfx_hires4.text(19+tp,20+tp*11, 7, sc:"ScreenCODE text! 1234![]<>#$%&*()") + } + + } +} diff --git a/examples/cx16/test_gfx_lores.p8 b/examples/cx16/test_gfx_lores.p8 new file mode 100644 index 000000000..1778f1b8d --- /dev/null +++ b/examples/cx16/test_gfx_lores.p8 @@ -0,0 +1,93 @@ +%import gfx_lores +%import textio +%import math + +%option no_sysinit +%zeropage basicsafe + + +main { + + sub start() { + demofill() + sys.wait(120) + demo2() + + gfx_lores.text_mode() + txt.print("done!\n") + } + + sub demofill() { + gfx_lores.graphics_mode() + gfx_lores.circle(160, 120, 110, 1) + gfx_lores.rect(180, 5, 25, 190, 1) + gfx_lores.line(100, 150, 240, 10, 1) + gfx_lores.line(101, 150, 241, 10, 1) + sys.wait(60) + gfx_lores.fill(100,100,2) + gfx_lores.fill(182,140,3) + gfx_lores.fill(182,40,1) + + } + + sub demo2 () { + gfx_lores.text_charset(3) + draw() + sys.wait(120) + } + + sub draw() { + gfx_lores.rect(10,10, 1, 1, 4) + gfx_lores.rect(20,10, 2, 1, 4) + gfx_lores.rect(30,10, 3, 1, 4) + gfx_lores.rect(40,10, 1, 2, 4) + gfx_lores.rect(50,10, 1, 3, 4) + gfx_lores.rect(60,10, 2, 2, 4) + gfx_lores.rect(70,10, 3, 3, 4) + gfx_lores.rect(80,10, 4, 4, 4) + gfx_lores.rect(90,10, 5, 5, 4) + gfx_lores.rect(100,10, 8, 8, 4) + gfx_lores.rect(110,10, 20, 5, 4) + gfx_lores.rect(80, 80, 200, 140, 4) + + gfx_lores.fillrect(10,40, 1, 1, 5) + gfx_lores.fillrect(20,40, 2, 1, 5) + gfx_lores.fillrect(30,40, 3, 1, 5) + gfx_lores.fillrect(40,40, 1, 2, 5) + gfx_lores.fillrect(50,40, 1, 3, 5) + gfx_lores.fillrect(60,40, 2, 2, 5) + gfx_lores.fillrect(70,40, 3, 3, 5) + gfx_lores.fillrect(80,40, 4, 4, 5) + gfx_lores.fillrect(90,40, 5, 5, 5) + gfx_lores.fillrect(100,40, 8, 8, 5) + gfx_lores.fillrect(110,40, 20, 5, 5) + gfx_lores.fillrect(82, 82, 200-4, 140-4, 5) + + ubyte i + for i in 0 to 254 step 4 { + uword x1 = ((gfx_lores.WIDTH-256)/2 as uword) + math.sin8u(i) + ubyte y1 = (gfx_lores.HEIGHT-128)/2 + math.cos8u(i)/2 + uword x2 = ((gfx_lores.WIDTH-64)/2 as uword) + math.sin8u(i)/4 + ubyte y2 = (gfx_lores.HEIGHT-64)/2 + math.cos8u(i)/4 + gfx_lores.line(x1, y1, x2, y2, i+1) + } + + sys.wait(60) + gfx_lores.clear_screen(2) + gfx_lores.clear_screen(0) + + ubyte radius + + for radius in 110 downto 8 step -4 { + gfx_lores.circle(gfx_lores.WIDTH/2, (gfx_lores.HEIGHT/2 as ubyte), radius, radius) + } + + gfx_lores.disc(gfx_lores.WIDTH/2, gfx_lores.HEIGHT/2, 80, 2) + + ubyte tp + for tp in 0 to 15 { + gfx_lores.text(19+tp,20+tp*11, 7, sc:"ScreenCODE text! 1234![]<>#$%&*()") + } + + } +} diff --git a/examples/cx16/testgfx2.p8 b/examples/cx16/testgfx2.p8 deleted file mode 100644 index 50f8ba2ba..000000000 --- a/examples/cx16/testgfx2.p8 +++ /dev/null @@ -1,98 +0,0 @@ -%import gfx2 -%import textio -%import math - -%option no_sysinit -%zeropage basicsafe - - -main { - - sub start() { - gfx2.screen_mode(1) - demofill() - sys.wait(120) - demo2() - - gfx2.screen_mode(0) - txt.print("done!\n") - } - - sub demofill() { - - gfx2.circle(160, 120, 110, 1) - gfx2.rect(180, 5, 25, 190, 1) - gfx2.line(100, 150, 240, 10, 1) - gfx2.line(101, 150, 241, 10, 1) - sys.wait(60) - gfx2.fill(100,100,2) - gfx2.fill(182,140,3) - gfx2.fill(182,40,1) - - } - - sub demo2 () { - gfx2.text_charset(3) - gfx2.screen_mode(1) - draw() - sys.wait(120) - gfx2.screen_mode(2) - draw() - sys.wait(120) - } - - sub draw() { - gfx2.rect(10,10, 1, 1, 4) - gfx2.rect(20,10, 2, 1, 4) - gfx2.rect(30,10, 3, 1, 4) - gfx2.rect(40,10, 1, 2, 4) - gfx2.rect(50,10, 1, 3, 4) - gfx2.rect(60,10, 2, 2, 4) - gfx2.rect(70,10, 3, 3, 4) - gfx2.rect(80,10, 4, 4, 4) - gfx2.rect(90,10, 5, 5, 4) - gfx2.rect(100,10, 8, 8, 4) - gfx2.rect(110,10, 20, 5, 4) - gfx2.rect(80, 80, 200, 140, 4) - - gfx2.fillrect(10,40, 1, 1, 5) - gfx2.fillrect(20,40, 2, 1, 5) - gfx2.fillrect(30,40, 3, 1, 5) - gfx2.fillrect(40,40, 1, 2, 5) - gfx2.fillrect(50,40, 1, 3, 5) - gfx2.fillrect(60,40, 2, 2, 5) - gfx2.fillrect(70,40, 3, 3, 5) - gfx2.fillrect(80,40, 4, 4, 5) - gfx2.fillrect(90,40, 5, 5, 5) - gfx2.fillrect(100,40, 8, 8, 5) - gfx2.fillrect(110,40, 20, 5, 5) - gfx2.fillrect(82, 82, 200-4, 140-4, 5) - - ubyte i - for i in 0 to 254 step 4 { - uword x1 = ((gfx2.width-256)/2 as uword) + math.sin8u(i) - uword y1 = (gfx2.height-128)/2 + math.cos8u(i)/2 - uword x2 = ((gfx2.width-64)/2 as uword) + math.sin8u(i)/4 - uword y2 = (gfx2.height-64)/2 + math.cos8u(i)/4 - gfx2.line(x1, y1, x2, y2, i+1) - } - - sys.wait(60) - gfx2.clear_screen(2) - gfx2.clear_screen(0) - - ubyte radius - - for radius in 110 downto 8 step -4 { - gfx2.circle(gfx2.width/2, (gfx2.height/2 as ubyte), radius, radius) - } - - gfx2.disc(gfx2.width/2, gfx2.height/2, 80, 2) - - ubyte tp - for tp in 0 to 15 { - gfx2.text(19+tp,20+tp*11, 7, sc:"ScreenCODE text! 1234![]<>#$%&*()") - } - - } -} diff --git a/examples/test.p8 b/examples/test.p8 index 20c950c80..5624d78a5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,35 +1,15 @@ %import textio -%import gfx2 -%import gfx_lores +%import gfx_hires4 %option no_sysinit %zeropage basicsafe main { sub start() { - gfx_lores.graphics_mode() - - ; gfx2.screen_mode(1) - gfx_lores.text_charset(1) - for cx16.r9L in 0 to 10 { - gfx_lores.text(50+cx16.r9L, 20+cx16.r9L, cx16.r9L, sc:"the quick brown fox 12345") - } - gfx_lores.text_charset(2) - for cx16.r9L in 0 to 10 { - gfx_lores.text(50+cx16.r9L, 40+cx16.r9L, cx16.r9L, sc:"the quick brown fox 12345") - } - gfx_lores.text_charset(3) - for cx16.r9L in 0 to 10 { - gfx_lores.text(50+cx16.r9L, 60+cx16.r9L, cx16.r9L, sc:"the quick brown fox 12345") - } - gfx_lores.text_charset(4) - for cx16.r9L in 0 to 10 { - gfx_lores.text(50+cx16.r9L, 80+cx16.r9L, cx16.r9L, sc:"the quick brown fox 12345") - } - gfx_lores.text_charset(5) - for cx16.r9L in 0 to 10 { - gfx_lores.text(50+cx16.r9L, 100+cx16.r9L, cx16.r9L, sc:"the quick brown fox 12345") - } + gfx_hires4.graphics_mode() + gfx_hires4.circle(300, 250, 200, 3) + gfx_hires4.rect(320, 10, 20, 200, 3) + gfx_hires4.fill(310, 310, 2) repeat { }