diff --git a/compiler/res/prog8lib/cx16/gfx2.p8 b/compiler/res/prog8lib/cx16/gfx2.p8 index f3c4023ed..6d24ef61e 100644 --- a/compiler/res/prog8lib/cx16/gfx2.p8 +++ b/compiler/res/prog8lib/cx16/gfx2.p8 @@ -29,7 +29,7 @@ gfx2 { uword width = 0 uword height = 0 ubyte bpp = 0 - bool monochrome_dont_stipple_flag = false ; set to false to enable stippling mode in monochrome displaymodes + bool monochrome_dont_stipple_flag = true ; set to false to enable stippling mode in monochrome displaymodes sub screen_mode(ubyte mode) { cx16.VERA_CTRL=0 diff --git a/compiler/res/prog8lib/cx16/graphics.p8 b/compiler/res/prog8lib/cx16/graphics.p8 index 3be270615..a424ab184 100644 --- a/compiler/res/prog8lib/cx16/graphics.p8 +++ b/compiler/res/prog8lib/cx16/graphics.p8 @@ -5,7 +5,7 @@ ; 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) +; 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. diff --git a/compiler/res/prog8lib/cx16/monogfx.p8 b/compiler/res/prog8lib/cx16/monogfx.p8 new file mode 100644 index 000000000..d4c293374 --- /dev/null +++ b/compiler/res/prog8lib/cx16/monogfx.p8 @@ -0,0 +1,727 @@ +; Monochrome Bitmap pixel graphics routines for the CommanderX16 +; Using the full-screen 640x480 and 320x240 screen modes, in 1 bpp mode (black/white). +; +; No text layer is currently shown, but text can be drawn as part of the bitmap itself. +; For color bitmap graphics, see the gfx2 library. +; +; NOTE: a lot of the code here is similar or the same to that in gfx2 + +monogfx { + + %option no_symbol_prefixing + + ; read-only control variables: + uword width = 0 + uword height = 0 + bool dont_stipple_flag = true ; set to false to enable stippling mode + + sub lores() { + ; enable 320*240 bitmap mode + cx16.VERA_CTRL=0 + 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 = %00000100 + cx16.VERA_L1_MAPBASE = 0 + cx16.VERA_L1_TILEBASE = 0 + width = 320 + height = 240 + clear_screen() + } + + sub hires() { + ; enable 640*480 bitmap mode + cx16.VERA_CTRL=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 = %00000100 + cx16.VERA_L1_MAPBASE = 0 + cx16.VERA_L1_TILEBASE = %00000001 + width = 640 + height = 480 + clear_screen() + } + + sub textmode() { + ; 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() { + stipple(false) + position(0, 0) + when width { + 320 -> { + repeat 240/2/8 + cs_innerloop640() + } + 640 -> { + repeat 480/8 + cs_innerloop640() + } + } + position(0, 0) + } + + sub stipple(bool enable) { + dont_stipple_flag = not enable + } + + sub rect(uword xx, uword yy, uword rwidth, uword rheight, bool draw) { + if rwidth==0 or rheight==0 + return + horizontal_line(xx, yy, rwidth, draw) + if rheight==1 + return + horizontal_line(xx, yy+rheight-1, rwidth, draw) + vertical_line(xx, yy+1, rheight-2, draw) + if rwidth==1 + return + vertical_line(xx+rwidth-1, yy+1, rheight-2, draw) + } + + sub fillrect(uword xx, uword yy, uword rwidth, uword rheight, bool draw) { + if rwidth==0 + return + repeat rheight { + horizontal_line(xx, yy, rwidth, draw) + yy++ + } + } + + sub horizontal_line(uword xx, uword yy, uword length, bool draw) { + ubyte[9] masked_starts = [ 0, %00000001, %00000011, %00000111, %00001111, %00011111, %00111111, %01111111, %11111111] + ubyte[9] masked_ends = [ 0, %10000000, %11000000, %11100000, %11110000, %11111000, %11111100, %11111110, %11111111] + + if length==0 + return + ubyte separate_pixels = (8-lsb(xx)) & 7 + if separate_pixels as uword > length + separate_pixels = lsb(length) + if separate_pixels { + if dont_stipple_flag { + position(xx,yy) + cx16.VERA_ADDR_H &= %00000111 ; vera auto-increment off + if draw + cx16.VERA_DATA0 |= masked_starts[separate_pixels] + else + cx16.VERA_DATA0 &= ~masked_starts[separate_pixels] + xx += separate_pixels + } else { + repeat separate_pixels { + plot(xx, yy, draw) + xx++ + } + } + length -= separate_pixels + } + if length { + position(xx, yy) + separate_pixels = lsb(length) & 7 + xx += length & $fff8 + %asm {{ + lsr length+1 + ror length + lsr length+1 + ror length + lsr length+1 + ror length + lda draw + bne + + ldy #0 ; black + bra _loop ++ lda dont_stipple_flag + beq _stipple + ldy #255 ; don't stipple + bra _loop +_stipple lda yy + and #1 ; determine stipple pattern to use + bne + + ldy #%01010101 + bra _loop ++ ldy #%10101010 +_loop lda length + ora length+1 + beq _done + sty cx16.VERA_DATA0 + lda length + bne + + dec length+1 ++ dec length + bra _loop +_done + }} + + if dont_stipple_flag { + cx16.VERA_ADDR_H &= %00000111 ; vera auto-increment off + if draw + cx16.VERA_DATA0 |= masked_ends[separate_pixels] + else + cx16.VERA_DATA0 &= ~masked_ends[separate_pixels] + } else { + repeat separate_pixels { + plot(xx, yy, draw) + xx++ + } + } + } + cx16.VERA_ADDR_H &= %00000111 ; vera auto-increment off again + } + + sub vertical_line(uword xx, uword yy, uword lheight, bool draw) { + cx16.r15L = monogfx.plot.maskbits[xx as ubyte & 7] ; bitmask + if draw { + if dont_stipple_flag { + ; draw continuous line. + position2(xx,yy,true) + if width==320 + set_both_strides(11) ; 40 increment = 1 line in 320 px monochrome + else + set_both_strides(12) ; 80 increment = 1 line in 640 px monochrome + repeat lheight { + %asm {{ + lda cx16.VERA_DATA0 + ora cx16.r15L + sta cx16.VERA_DATA1 + }} + } + } else { + ; draw stippled line. + if xx&1 { + yy++ + lheight-- + } + position2(xx,yy,true) + if width==320 + set_both_strides(12) ; 80 increment = 2 line in 320 px monochrome + else + set_both_strides(13) ; 160 increment = 2 line in 640 px monochrome + repeat lheight/2 { + %asm {{ + lda cx16.VERA_DATA0 + ora cx16.r15L + sta cx16.VERA_DATA1 + }} + } + } + } else { + position2(xx,yy,true) + cx16.r15 = ~cx16.r15 ; erase pixels + if width==320 + set_both_strides(11) ; 40 increment = 1 line in 320 px monochrome + else + set_both_strides(12) ; 80 increment = 1 line in 640 px monochrome + repeat lheight { + %asm {{ + lda cx16.VERA_DATA0 + and cx16.r15L + sta cx16.VERA_DATA1 + }} + } + } + + sub set_both_strides(ubyte stride) { + stride <<= 4 + cx16.VERA_CTRL = 0 + cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & %00000111 | stride + cx16.VERA_CTRL = 1 + cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & %00000111 | stride + } + + } + + sub line(uword @zp x1, uword @zp y1, uword @zp x2, uword @zp y2, bool draw) { + ; Bresenham algorithm. + ; This code special-cases various quadrant loops to allow simple ++ and -- operations. + if y1>y2 { + ; make sure dy is always positive to have only 4 instead of 8 special cases + cx16.r0 = x1 + x1 = x2 + x2 = cx16.r0 + cx16.r0 = y1 + y1 = y2 + y2 = cx16.r0 + } + word @zp dx = (x2 as word)-x1 + word @zp dy = (y2 as word)-y1 + + if dx==0 { + vertical_line(x1, y1, abs(dy) as uword +1, draw) + return + } + if dy==0 { + if x1>x2 + x1=x2 + horizontal_line(x1, y1, abs(dx) as uword +1, draw) + return + } + + word @zp d = 0 + cx16.r1L = true ; 'positive_ix' + if dx < 0 { + dx = -dx + cx16.r1L = false + } + word @zp dx2 = dx*2 + word @zp dy2 = dy*2 + cx16.r14 = x1 ; internal plot X + + if dx >= dy { + if cx16.r1L { + repeat { + plot(cx16.r14, y1, draw) + if cx16.r14==x2 + return + cx16.r14++ + d += dy2 + if d > dx { + y1++ + d -= dx2 + } + } + } else { + repeat { + plot(cx16.r14, y1, draw) + if cx16.r14==x2 + return + cx16.r14-- + d += dy2 + if d > dx { + y1++ + d -= dx2 + } + } + } + } + else { + if cx16.r1L { + repeat { + plot(cx16.r14, y1, draw) + if y1 == y2 + return + y1++ + d += dx2 + if d > dy { + cx16.r14++ + d -= dy2 + } + } + } else { + repeat { + plot(cx16.r14, y1, draw) + if y1 == y2 + return + y1++ + d += dx2 + if d > dy { + cx16.r14-- + d -= dy2 + } + } + } + } + } + + sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, bool draw) { + ; 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 + plot(cx16.r14, cx16.r15, draw) + cx16.r14 = xcenter - xx + plot(cx16.r14, cx16.r15, draw) + cx16.r14 = xcenter + xx + cx16.r15 = ycenter - yy + plot(cx16.r14, cx16.r15, draw) + cx16.r14 = xcenter - xx + plot(cx16.r14, cx16.r15, draw) + cx16.r14 = xcenter + yy + cx16.r15 = ycenter + xx + plot(cx16.r14, cx16.r15, draw) + cx16.r14 = xcenter - yy + plot(cx16.r14, cx16.r15, draw) + cx16.r14 = xcenter + yy + cx16.r15 = ycenter - xx + plot(cx16.r14, cx16.r15, draw) + cx16.r14 = xcenter - yy + plot(cx16.r14, cx16.r15, draw) + + yy++ + if decisionOver2<=0 + decisionOver2 += (yy as word)*2+1 + else { + xx-- + decisionOver2 += (yy as word -xx)*2+1 + } + } + } + + sub disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) { + ; Midpoint algorithm, filled + if radius==0 + return + ubyte @zp yy = 0 + word @zp decisionOver2 = (1 as word)-radius + + while radius>=yy { + horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, draw) + horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, draw) + horizontal_line(xcenter-yy, ycenter+radius, yy*$0002+1, draw) + horizontal_line(xcenter-yy, ycenter-radius, yy*$0002+1, draw) + yy++ + if decisionOver2<=0 + decisionOver2 += (yy as word)*2+1 + else { + radius-- + decisionOver2 += (yy as word -radius)*2+1 + } + } + } + + sub plot(uword @zp xx, uword @zp yy, bool @zp draw) { + ubyte[8] @shared maskbits = [128, 64, 32, 16, 8, 4, 2, 1] + if draw { + ; solid color or perhaps stipple + %asm {{ + lda xx + eor yy + ora dont_stipple_flag + and #1 + }} + if_nz { + prepare() + %asm {{ + tsb cx16.VERA_DATA0 + }} + } + } else { + ; only erase + prepare() + %asm {{ + trb cx16.VERA_DATA0 + }} + } + + sub prepare() { + %asm {{ + lda xx + and #7 + pha ; xbits + }} + xx /= 8 + if width==320 + xx += yy*(320/8) + else + xx += yy*(640/8) + %asm {{ + stz cx16.VERA_CTRL + stz cx16.VERA_ADDR_H + lda xx+1 + sta cx16.VERA_ADDR_M + lda xx + sta cx16.VERA_ADDR_L + ply ; xbits + lda maskbits,y + }} + } + } + + sub pget(uword @zp xx, uword yy) -> ubyte { + %asm {{ + lda xx + and #7 + pha ; xbits + }} + xx /= 8 + if width==320 + xx += yy*(320/8) + else + xx += yy*(640/8) + + %asm {{ + stz cx16.VERA_CTRL + stz cx16.VERA_ADDR_H + lda xx+1 + sta cx16.VERA_ADDR_M + lda xx + sta cx16.VERA_ADDR_L + ply ; xbits + lda plot.maskbits,y + and cx16.VERA_DATA0 + beq + + lda #1 ++ rts + }} + } + + sub fill(word @zp xx, word @zp yy, bool draw) { + ; Non-recursive scanline flood fill. + ; based loosely on code found here https://www.codeproject.com/Articles/6017/QuickFill-An-efficient-flood-fill-algorithm + ; with the fixes applied to the seedfill_4 routine as mentioned in the comments. + const ubyte MAXDEPTH = 48 + word[MAXDEPTH] @split @shared stack_xl + word[MAXDEPTH] @split @shared stack_xr + word[MAXDEPTH] @split @shared stack_y + byte[MAXDEPTH] @shared stack_dy + cx16.r12L = 0 ; stack pointer + word x1 + word x2 + byte dy + cx16.r10L = draw as ubyte + sub push_stack(word sxl, word sxr, word sy, byte sdy) { + if cx16.r12L==MAXDEPTH + return + cx16.r0s = sy+sdy + if cx16.r0s>=0 and cx16.r0s<=height-1 { +;; stack_xl[cx16.r12L] = sxl +;; stack_xr[cx16.r12L] = sxr +;; stack_y[cx16.r12L] = sy +;; stack_dy[cx16.r12L] = sdy +;; cx16.r12L++ + %asm {{ + ldy cx16.r12L + lda sxl + sta stack_xl_lsb,y + lda sxl+1 + sta stack_xl_msb,y + lda sxr + sta stack_xr_lsb,y + lda sxr+1 + sta stack_xr_msb,y + lda sy + sta stack_y_lsb,y + lda sy+1 + sta stack_y_msb,y + ldy cx16.r12L + lda sdy + sta stack_dy,y + inc cx16.r12L + }} + } + } + sub pop_stack() { +;; cx16.r12L-- +;; x1 = stack_xl[cx16.r12L] +;; x2 = stack_xr[cx16.r12L] +;; y = stack_y[cx16.r12L] +;; dy = stack_dy[cx16.r12L] + %asm {{ + dec cx16.r12L + ldy cx16.r12L + lda stack_xl_lsb,y + sta x1 + lda stack_xl_msb,y + sta x1+1 + lda stack_xr_lsb,y + sta x2 + lda stack_xr_msb,y + sta x2+1 + lda stack_y_lsb,y + sta yy + lda stack_y_msb,y + sta yy+1 + ldy cx16.r12L + lda stack_dy,y + sta dy + }} + yy+=dy + } + 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 + return + push_stack(xx, xx, yy, 1) + push_stack(xx, xx, yy + 1, -1) + word left = 0 + while cx16.r12L { + pop_stack() + xx = x1 + while xx >= 0 and pget(xx as uword, yy as uword) == cx16.r11L { + plot(xx as uword, yy as uword, cx16.r10L) + xx-- + } + if xx >= x1 + goto skip + + left = xx + 1 + if left < x1 + push_stack(left, x1 - 1, yy, -dy) + xx = x1 + 1 + + do { + while xx <= width-1 and pget(xx as uword, yy as uword) == cx16.r11L { + plot(xx as uword, yy as uword, cx16.r10L) + xx++ + } + push_stack(left, xx - 1, yy, dy) + if xx > x2 + 1 + push_stack(x2 + 1, xx - 1, yy, -dy) +skip: + xx++ + while xx <= x2 and pget(xx as uword, yy as uword) != cx16.r11L + xx++ + left = xx + } until xx>x2 + } + } + + sub position(uword @zp xx, uword yy) { + if width==320 + cx16.r0 = yy*(320/8) + else + cx16.r0 = yy*(640/8) + cx16.vaddr(0, cx16.r0+xx/8, 0, 1) + } + + sub position2(uword @zp xx, uword yy, bool also_port_1) { + position(xx, yy) + if also_port_1 + cx16.vaddr_clone(0) + } + + const ubyte charset_bank = $1 + const uword charset_addr = $f000 ; in bank 1, so $1f000 + + sub text_charset(ubyte charset) { + ; -- select the text charset to use with the text() routine + ; the charset number is the same as for the cx16.screen_set_charset() ROM function. + ; 1 = ISO charset, 2 = PETSCII uppercase+graphs, 3= PETSCII uppercase+lowercase. + cx16.screen_set_charset(charset, 0) + } + + sub text(uword @zp xx, uword yy, bool draw, uword sctextptr) { + ; -- Write some text at the given pixel position. The text string must be in screencode encoding (not petscii!). + ; You must also have called text_charset() first to select and prepare the character set to use. + uword chardataptr + ubyte[8] @shared char_bitmap_bytes_left + ubyte[8] @shared char_bitmap_bytes_right + + cx16.r3 = sctextptr + while @(cx16.r3) { + chardataptr = charset_addr + @(cx16.r3) * $0008 + ; copy the character bitmap into RAM + cx16.vaddr_autoincr(charset_bank, chardataptr, 0, 1) + %asm {{ + ; pre-shift the bits + lda text.xx + and #7 + sta P8ZP_SCRATCH_B1 + ldy #0 +- lda cx16.VERA_DATA0 + stz P8ZP_SCRATCH_REG + ldx P8ZP_SCRATCH_B1 + cpx #0 + beq + +- lsr a + ror P8ZP_SCRATCH_REG + dex + bne - ++ sta char_bitmap_bytes_left,y + lda P8ZP_SCRATCH_REG + sta char_bitmap_bytes_right,y + iny + cpy #8 + bne -- + }} + ; left part of shifted char + position2(xx, yy, true) + set_autoincrs() + if draw { + %asm {{ + ldy #0 +- lda char_bitmap_bytes_left,y + ora cx16.VERA_DATA1 + sta cx16.VERA_DATA0 + iny + cpy #8 + bne - + }} + } else { + %asm {{ + ldy #0 +- lda char_bitmap_bytes_left,y + eor #255 + and cx16.VERA_DATA1 + sta cx16.VERA_DATA0 + iny + cpy #8 + bne - + }} + } + ; right part of shifted char + if lsb(xx) & 7 { + position2(xx+8, yy, true) + set_autoincrs() + if draw { + %asm {{ + ldy #0 +- lda char_bitmap_bytes_right,y + ora cx16.VERA_DATA1 + sta cx16.VERA_DATA0 + iny + cpy #8 + bne - + }} + } else { + %asm {{ + ldy #0 +- lda char_bitmap_bytes_right,y + eor #255 + and cx16.VERA_DATA1 + sta cx16.VERA_DATA0 + iny + cpy #8 + bne - + }} + } + } + cx16.r3++ + xx += 8 + } + + sub set_autoincrs() { + ; set autoincrements to go to next pixel row (40 or 80 increment) + if width==320 { + cx16.VERA_CTRL = 0 + cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & $0f | (11<<4) + cx16.VERA_CTRL = 1 + cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & $0f | (11<<4) + } else { + cx16.VERA_CTRL = 0 + cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & $0f | (12<<4) + cx16.VERA_CTRL = 1 + cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & $0f | (12<<4) + } + } + } + + asmsub cs_innerloop640() clobbers(Y) { + %asm {{ + ldy #80 +- stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + stz cx16.VERA_DATA0 + dey + bne - + rts + }} + } +} diff --git a/compiler/test/TestCompilerOnExamples.kt b/compiler/test/TestCompilerOnExamples.kt index 591a887fe..10e4fafaf 100644 --- a/compiler/test/TestCompilerOnExamples.kt +++ b/compiler/test/TestCompilerOnExamples.kt @@ -122,6 +122,7 @@ class TestCompilerOnExamplesCx16: FunSpec({ "spotlight", "tehtriz", "testgfx2", + "testmonogfx", ), listOf(false, true) ) diff --git a/docs/source/libraries.rst b/docs/source/libraries.rst index 66b0633be..56c8f3068 100644 --- a/docs/source/libraries.rst +++ b/docs/source/libraries.rst @@ -447,18 +447,34 @@ to see what's in there. Information about the exposed debug registers is in the `emulator's documentation `_. +monogfx (cx16 only) +-------------------- +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. -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, also back to text mode is possible. +- lores 320*240 or hires 640*480 bitmap mode, monochrome +- clearing screen, switching screen mode, also back to text mode +- drawing and reading individual pixels +- drawing lines, rectangles, filled rectangles, circles, discs +- flood fill +- drawing text inside the bitmap +- can draw using a stipple pattern (alternate black/white pixels) + +Read the `source code `_ +to see what's in there. + + +gfx2 (cx16 only) +----------------- +Full-screen multicolor bitmap graphics routines, available on the Cx16 machine only. +Same interface as monogfx, but for color screens. For 1 bpp monochrome screens, use monogfx. + +- multiple full-screen bitmap color resolutions +- clearing screen, switching screen mode, also back to text mode - drawing and reading individual pixels - drawing lines, rectangles, filled rectangles, circles, discs - flood fill - drawing text inside the bitmap -- in monochrome mode, it's possible to use a stippled drawing pattern to simulate a shade of gray. Read the `source code `_ to see what's in there. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 3253dae4a..3032d17ef 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,8 @@ TODO ==== +- gfx2 and monogfx rect draw problem in monochrome modes one of the small rectangles is drawn garbled +- make monogfx the new graphics module? also change c64 and c128 graphics modules - add %option verafxmuls in block to enable transparent verafx muls use for that block only + add warning message to docs to not use it it in prg AND irq code - [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 .... diff --git a/examples/cx16/highresbitmap.p8 b/examples/cx16/highresbitmap.p8 index da75f01e2..10a999178 100644 --- a/examples/cx16/highresbitmap.p8 +++ b/examples/cx16/highresbitmap.p8 @@ -1,4 +1,4 @@ -%import gfx2 +%import monogfx %import floats %import textio %import math @@ -7,77 +7,77 @@ main { sub start () { - gfx2.text_charset(3) + monogfx.text_charset(3) test_monochrome() - gfx2.screen_mode(0) + monogfx.textmode() txt.print("done!\n") } sub test_monochrome() { - gfx2.screen_mode(5) + monogfx.hires() 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) + monogfx.stipple(false) + monogfx.rect(xx, yy, 250, 80, 1) + monogfx.stipple(true) + monogfx.fillrect(xx+2, yy+2, 250-4, 80-4, 1) + monogfx.stipple(false) + monogfx.fillrect(xx+20, yy+20, 200, 30, 1) + monogfx.rect(xx+21, yy+21, 200-2, 30-2, 0) - gfx2.text(xx+30, yy+32, 0, sc:"High Res Bitmap Example") + monogfx.text(xx+30, yy+32, 0, sc:"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, sc:"0,0") - gfx2.text(322, 10, 1, sc:"Y-axis") - gfx2.text(590, 242, 1, sc:"X-axis") + ; monogfx.stipple(true) + monogfx.horizontal_line(10, 240, 620, 1) + monogfx.vertical_line(320, 10, 460, 1) + monogfx.text(320, 242, 1, sc:"0,0") + monogfx.text(322, 10, 1, sc:"Y-axis") + monogfx.text(590, 242, 1, sc:"X-axis") for ww in -10 to 10 { xx = (ww*30) + 320 as uword - gfx2.vertical_line(xx, 239, 3, 1) + monogfx.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) + monogfx.horizontal_line(319, yy, 3, 1) } - gfx2.monochrome_stipple(false) + monogfx.stipple(false) float y_f for ww in -600 to 600 { y_f = floats.sin(ww as float / 60.0)*150 - gfx2.plot(ww/2 + 320 as uword, (y_f + 240) as uword, 1) + monogfx.plot(ww/2 + 320 as uword, (y_f + 240) as uword, 1) } - gfx2.text(480, 100, 1, sc:"sin(x)") + monogfx.text(480, 100, 1, sc:"sin(x)") for ww in -300 to 300 { y_f = floats.cos(ww as float/30.0)*60 - (ww as float)/1.7 - gfx2.plot(ww + 320 as uword, (y_f + 240) as uword, 1) + monogfx.plot(ww + 320 as uword, (y_f + 240) as uword, 1) } - gfx2.text(80, 420, 1, sc:"cos(x)+x") + monogfx.text(80, 420, 1, sc:"cos(x)+x") sys.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) + monogfx.circle(320, 240, 220, 1) + monogfx.circle(320, 240, 210, 1) + monogfx.circle(320, 240, 200, 1) + monogfx.circle(320, 240, 190, 1) + monogfx.stipple(true) + monogfx.disc(320, 240, 140, 1) + monogfx.stipple(false) + monogfx.disc(320, 240, 90, 1) + monogfx.disc(320, 240, 40, 0) sys.wait(2*60) repeat 255 - gfx2.line(math.rndw() % 640, math.rndw() % 480, math.rndw() % 640, math.rndw() % 480, 1) + monogfx.line(math.rndw() % 640, math.rndw() % 480, math.rndw() % 640, math.rndw() % 480, 1) sys.wait(1*60) } diff --git a/examples/cx16/testmonogfx.p8 b/examples/cx16/testmonogfx.p8 new file mode 100644 index 000000000..e48ff0ba5 --- /dev/null +++ b/examples/cx16/testmonogfx.p8 @@ -0,0 +1,208 @@ +%import monogfx +%import textio +%import math + +%option no_sysinit +%zeropage basicsafe + + +main { + + sub start() { + monogfx.lores() + demofill() + sys.wait(2*60) + monogfx.hires() + demo1() + sys.wait(2*60) + demo2() + + monogfx.textmode() + txt.print("done!\n") + } + + sub demofill() { + monogfx.circle(160, 120, 110, 1) + monogfx.rect(180, 5, 25, 190, 1) + monogfx.line(100, 150, 240, 10, 1) + monogfx.line(101, 150, 241, 10, 1) + monogfx.stipple(true) + sys.wait(60) + monogfx.fill(100,100,2) + } + + sub demo1() { + uword yy = 10 + uword xx + uword cnt + + monogfx.stipple(true) + monogfx.disc(320,240,200,1) + for xx in 0 to 639 { + monogfx.vertical_line(xx, 0, 480, 1) + } + for xx in 0 to 639 { + monogfx.vertical_line(xx, 0, 480, 0) + } + + xx=monogfx.width/2 + yy=10 + monogfx.stipple(false) + linesy() + linesx() + monogfx.stipple(true) + linesy() + linesx() + + + + sub linesx() { + repeat 8 { + monogfx.horizontal_line(10,yy,300,3) + yy++ + } + yy+=4 + + repeat 8 { + monogfx.line(10,yy,309,yy,4) + yy++ + } + yy+=4 + + repeat 8 { + for cnt in 10 to 309 { + monogfx.plot(cnt, yy, 1) + } + yy+=1 + } + yy += 4 + + repeat 8 { + monogfx.horizontal_line(10,yy,100,3) + yy++ + } + yy+=4 + + repeat 8 { + monogfx.line(10,yy,109,yy,4) + yy++ + } + yy+=4 + + repeat 8 { + for cnt in 10 to 109 { + monogfx.plot(cnt, yy, 1) + } + yy++ + } + yy+=4 + } + + sub linesy() { + repeat 8 { + monogfx.vertical_line(xx,10,300,3) + xx++ + } + xx+=4 + + repeat 8 { + monogfx.line(xx,10, xx, 309, 4) + xx++ + } + xx+=4 + + repeat 8 { + for cnt in 10 to 309 { + monogfx.plot(xx, cnt, 1) + } + xx+=1 + } + xx += 4 + + repeat 8 { + monogfx.vertical_line(xx,10,100,3) + xx++ + } + xx+=4 + + repeat 8 { + monogfx.line(xx,10,xx,109,4) + xx++ + } + xx+=4 + + repeat 8 { + for cnt in 10 to 109 { + monogfx.plot(xx, cnt, 1) + } + xx++ + } + xx+=4 + } + } + + sub demo2 () { + monogfx.text_charset(3) + monogfx.lores() + draw() + sys.wait(200) + monogfx.hires() + draw() + sys.wait(200) + } + + sub draw() { + + monogfx.rect(10,10, 1, 1, 4) + monogfx.rect(20,10, 2, 1, 4) + monogfx.rect(30,10, 3, 1, 4) + monogfx.rect(40,10, 1, 2, 4) + monogfx.rect(50,10, 1, 3, 4) + monogfx.rect(60,10, 2, 2, 4) + monogfx.rect(70,10, 3, 3, 4) + monogfx.rect(80,10, 4, 4, 4) + monogfx.rect(90,10, 5, 5, 4) + monogfx.rect(100,10, 8, 8, 4) + monogfx.rect(110,10, 20, 5, 4) + monogfx.rect(80, 80, 200, 140, 4) + + monogfx.fillrect(10,40, 1, 1, 5) + monogfx.fillrect(20,40, 2, 1, 5) + monogfx.fillrect(30,40, 3, 1, 5) + monogfx.fillrect(40,40, 1, 2, 5) + monogfx.fillrect(50,40, 1, 3, 5) + monogfx.fillrect(60,40, 2, 2, 5) + monogfx.fillrect(70,40, 3, 3, 5) + monogfx.fillrect(80,40, 4, 4, 5) + monogfx.fillrect(90,40, 5, 5, 5) + monogfx.fillrect(100,40, 8, 8, 5) + monogfx.fillrect(110,40, 20, 5, 5) + monogfx.fillrect(82, 82, 200-4, 140-4, 5) + + ubyte i + for i in 0 to 254 step 4 { + uword x1 = ((monogfx.width-256)/2 as uword) + math.sin8u(i) + uword y1 = (monogfx.height-128)/2 + math.cos8u(i)/2 + uword x2 = ((monogfx.width-64)/2 as uword) + math.sin8u(i)/4 + uword y2 = (monogfx.height-64)/2 + math.cos8u(i)/4 + monogfx.line(x1, y1, x2, y2, i+1) + } + + sys.wait(60) + monogfx.clear_screen() + + ubyte radius + + for radius in 110 downto 8 step -4 { + monogfx.circle(monogfx.width/2, (monogfx.height/2 as ubyte), radius, radius) + } + + monogfx.disc(monogfx.width/2, monogfx.height/2, 80, 2) + + ubyte tp + for tp in 0 to 15 { + monogfx.text(19+tp,20+tp*11, 7, sc:"ScreenCODE text! 1234![]<>#$%&*()") + } + + } +} diff --git a/examples/test.p8 b/examples/test.p8 index 916d1e8ce..b39d51758 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,20 +1,80 @@ %import textio +;%import math +;%import verafx %zeropage basicsafe +%option no_sysinit main { sub start() { - alignblock.flags[0] = 222 - cx16.r0++ - cx16.r1++ - txt.print_uwhex(alignblock.flags, true) - txt.spc() - txt.print_ub(alignblock.flags[0]) + word w1 = -123 + word w2 = 222 + ubyte b2 = 222 + byte sb2 = 111 + txt.print_w(w1*w2) txt.nl() + txt.print_w(w1*222) + txt.nl() + w1 = -123 + w1 *= 222 + txt.print_w(w1) + txt.nl() + w1 = -123 + w1 *= w2 + txt.print_w(w1) + txt.nl() + w1 = -123 + w1 *= (w2-1) + txt.print_w(w1) + txt.nl() + w1 = -123 + w1 *= b2 + txt.print_w(w1) + txt.nl() + w1 = -123 + w1 *= sb2 + txt.print_w(w1) + txt.nl() + +; txt.print_uw(math.mul16_last_upper()) +; txt.nl() +; uword value1=5678 +; uword value2=9999 +; uword result = value1*value2 +; uword upper16 = math.mul16_last_upper() +; txt.print_uw(result) +; txt.spc() +; txt.print_uw(upper16) +; txt.nl() + + +; const word MULTIPLIER = 431 +; +; ; verify results: +; for value in -50 to 50 { +; if value*MULTIPLIER != verafx.muls(value, MULTIPLIER) { +; txt.print("verafx muls error\n") +; sys.exit(1) +; } +; } +; +; +; word value +; txt.print("verafx muls...") +; cbm.SETTIM(0,0,0) +; for value in -50 to 50 { +; repeat 250 void verafx.muls(value, MULTIPLIER) +; } +; txt.print_uw(cbm.RDTIM16()) +; txt.nl() +; +; txt.print("6502 muls...") +; cbm.SETTIM(0,0,0) +; for value in -50 to 50 { +; repeat 250 cx16.r0s = value*MULTIPLIER +; } +; txt.print_uw(cbm.RDTIM16()) +; txt.nl() + } } -alignblock { - %option align_page - ubyte[10] flags -} -