mirror of
https://github.com/irmen/prog8.git
synced 2025-11-23 14:17:51 +00:00
added doublebuffering to monogfx (in both lores and hires mode)
This commit is contained in:
@@ -22,18 +22,23 @@ monogfx {
|
|||||||
const ubyte MODE_STIPPLE = %00000001
|
const ubyte MODE_STIPPLE = %00000001
|
||||||
const ubyte MODE_INVERT = %00000010
|
const ubyte MODE_INVERT = %00000010
|
||||||
|
|
||||||
|
uword buffer_visible, buffer_back
|
||||||
|
|
||||||
|
|
||||||
sub lores() {
|
sub lores() {
|
||||||
; enable 320*240 bitmap mode
|
; enable 320*240 bitmap mode
|
||||||
|
buffer_visible = buffer_back = $0000
|
||||||
cx16.VERA_CTRL=0
|
cx16.VERA_CTRL=0
|
||||||
cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11001111) | %00100000 ; enable only layer 1
|
cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11001111) | %00100000 ; enable only layer 1
|
||||||
cx16.VERA_DC_HSCALE = 64
|
cx16.VERA_DC_HSCALE = 64
|
||||||
cx16.VERA_DC_VSCALE = 64
|
cx16.VERA_DC_VSCALE = 64
|
||||||
cx16.VERA_L1_CONFIG = %00000100
|
cx16.VERA_L1_CONFIG = %00000100
|
||||||
cx16.VERA_L1_MAPBASE = 0
|
cx16.VERA_L1_MAPBASE = 0
|
||||||
cx16.VERA_L1_TILEBASE = 0
|
cx16.VERA_L1_TILEBASE = 0 ; lores
|
||||||
width = 320
|
width = 320
|
||||||
height = 240
|
height = 240
|
||||||
lores_mode = true
|
lores_mode = true
|
||||||
|
buffer_visible = buffer_back = $0000
|
||||||
mode = MODE_NORMAL
|
mode = MODE_NORMAL
|
||||||
clear_screen(false)
|
clear_screen(false)
|
||||||
}
|
}
|
||||||
@@ -46,14 +51,40 @@ monogfx {
|
|||||||
cx16.VERA_DC_VSCALE = 128
|
cx16.VERA_DC_VSCALE = 128
|
||||||
cx16.VERA_L1_CONFIG = %00000100
|
cx16.VERA_L1_CONFIG = %00000100
|
||||||
cx16.VERA_L1_MAPBASE = 0
|
cx16.VERA_L1_MAPBASE = 0
|
||||||
cx16.VERA_L1_TILEBASE = %00000001
|
cx16.VERA_L1_TILEBASE = %00000001 ; hires
|
||||||
width = 640
|
width = 640
|
||||||
height = 480
|
height = 480
|
||||||
lores_mode = false
|
lores_mode = false
|
||||||
|
buffer_visible = buffer_back = $0000
|
||||||
mode = MODE_NORMAL
|
mode = MODE_NORMAL
|
||||||
clear_screen(false)
|
clear_screen(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub enable_doublebuffer() {
|
||||||
|
; enable double buffering mode
|
||||||
|
if lores_mode {
|
||||||
|
buffer_visible = $0000
|
||||||
|
buffer_back = $2800
|
||||||
|
} else {
|
||||||
|
buffer_visible = $0000
|
||||||
|
buffer_back = $9800
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub swap_buffers(bool wait_for_vsync) {
|
||||||
|
; flip the buffers: make the back buffer visible and the other one now the backbuffer.
|
||||||
|
; to avoid any screen tearing it is advised to call this during the vertical blank (pass true)
|
||||||
|
if wait_for_vsync
|
||||||
|
sys.waitvsync()
|
||||||
|
cx16.r0 = buffer_back
|
||||||
|
buffer_back = buffer_visible
|
||||||
|
buffer_visible = cx16.r0
|
||||||
|
cx16.VERA_CTRL = 0
|
||||||
|
cx16.r0 &= %1111110000000000
|
||||||
|
cx16.VERA_L1_TILEBASE = cx16.VERA_L1_TILEBASE & 1 | (cx16.r0H >>1 )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub textmode() {
|
sub textmode() {
|
||||||
; back to normal text mode
|
; back to normal text mode
|
||||||
cx16.r15L = cx16.VERA_DC_VIDEO & %00000111 ; retain chroma + output mode
|
cx16.r15L = cx16.VERA_DC_VIDEO & %00000111 ; retain chroma + output mode
|
||||||
@@ -559,6 +590,7 @@ drawmode: ora cx16.r15L
|
|||||||
sub disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) {
|
sub disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) {
|
||||||
; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen.
|
; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen.
|
||||||
; Midpoint algorithm, filled
|
; Midpoint algorithm, filled
|
||||||
|
; Note: has problems with INVERT draw mode because of horizontal span overdrawing. Horizontal lines may occur.
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
return
|
||||||
ubyte @zp yy = 0
|
ubyte @zp yy = 0
|
||||||
@@ -597,6 +629,7 @@ drawmode: ora cx16.r15L
|
|||||||
sub safe_disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) {
|
sub safe_disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, bool draw) {
|
||||||
; Does bounds checking and clipping.
|
; Does bounds checking and clipping.
|
||||||
; Midpoint algorithm, filled
|
; Midpoint algorithm, filled
|
||||||
|
; Note: has problems with INVERT draw mode because of horizontal span overdrawing. Horizontal lines may occur.
|
||||||
if radius==0
|
if radius==0
|
||||||
return
|
return
|
||||||
ubyte @zp yy = 0
|
ubyte @zp yy = 0
|
||||||
@@ -696,7 +729,7 @@ invert:
|
|||||||
adc p8v_times40_lsb,y
|
adc p8v_times40_lsb,y
|
||||||
sta cx16.VERA_ADDR_L
|
sta cx16.VERA_ADDR_L
|
||||||
lda p8v_times40_msb,y
|
lda p8v_times40_msb,y
|
||||||
adc #0
|
adc p8v_buffer_back+1
|
||||||
sta cx16.VERA_ADDR_M
|
sta cx16.VERA_ADDR_M
|
||||||
|
|
||||||
lda p8v_xx
|
lda p8v_xx
|
||||||
@@ -708,7 +741,6 @@ invert:
|
|||||||
; width=640 (hires)
|
; width=640 (hires)
|
||||||
%asm {{
|
%asm {{
|
||||||
stz cx16.VERA_CTRL
|
stz cx16.VERA_CTRL
|
||||||
stz cx16.VERA_ADDR_H
|
|
||||||
lda p8v_xx
|
lda p8v_xx
|
||||||
and #7
|
and #7
|
||||||
pha ; xbits
|
pha ; xbits
|
||||||
@@ -723,10 +755,15 @@ invert:
|
|||||||
;xx /= 8
|
;xx /= 8
|
||||||
xx += yy*(640/8)
|
xx += yy*(640/8)
|
||||||
%asm {{
|
%asm {{
|
||||||
lda p8v_xx+1
|
|
||||||
sta cx16.VERA_ADDR_M
|
|
||||||
lda p8v_xx
|
lda p8v_xx
|
||||||
sta cx16.VERA_ADDR_L
|
sta cx16.VERA_ADDR_L
|
||||||
|
lda p8v_xx+1
|
||||||
|
clc
|
||||||
|
adc p8v_buffer_back+1
|
||||||
|
sta cx16.VERA_ADDR_M
|
||||||
|
lda #0
|
||||||
|
rol a ; hi bit carry also needed when double-buffering
|
||||||
|
sta cx16.VERA_ADDR_H
|
||||||
plx ; xbits
|
plx ; xbits
|
||||||
lda p8v_maskbits,x
|
lda p8v_maskbits,x
|
||||||
}}
|
}}
|
||||||
@@ -768,11 +805,15 @@ invert:
|
|||||||
|
|
||||||
%asm {{
|
%asm {{
|
||||||
stz cx16.VERA_CTRL
|
stz cx16.VERA_CTRL
|
||||||
stz cx16.VERA_ADDR_H
|
|
||||||
lda p8v_xx+1
|
|
||||||
sta cx16.VERA_ADDR_M
|
|
||||||
lda p8v_xx
|
lda p8v_xx
|
||||||
sta cx16.VERA_ADDR_L
|
sta cx16.VERA_ADDR_L
|
||||||
|
lda p8v_xx+1
|
||||||
|
clc
|
||||||
|
adc p8v_buffer_back+1
|
||||||
|
sta cx16.VERA_ADDR_M
|
||||||
|
lda #0
|
||||||
|
rol a ; hi bit carry also needed when double-buffering
|
||||||
|
sta cx16.VERA_ADDR_H
|
||||||
ply ; xbits
|
ply ; xbits
|
||||||
lda p8s_plot.p8v_maskbits,y
|
lda p8s_plot.p8v_maskbits,y
|
||||||
and cx16.VERA_DATA0
|
and cx16.VERA_DATA0
|
||||||
@@ -855,8 +896,8 @@ skip:
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub fill_scanline_right() {
|
sub fill_scanline_right() {
|
||||||
; TODO maybe this could use vera auto increment, but that requires some clever masking calculations
|
; TODO maybe this could use vera auto increment, but that requires some clever masking calculations
|
||||||
cx16.r9s = xx
|
cx16.r9s = xx
|
||||||
while xx <= width-1 {
|
while xx <= width-1 {
|
||||||
if pgetset()
|
if pgetset()
|
||||||
break
|
break
|
||||||
@@ -891,11 +932,15 @@ skip:
|
|||||||
|
|
||||||
%asm {{
|
%asm {{
|
||||||
stz cx16.VERA_CTRL
|
stz cx16.VERA_CTRL
|
||||||
stz cx16.VERA_ADDR_H
|
|
||||||
lda p8v_xpos+1
|
|
||||||
sta cx16.VERA_ADDR_M
|
|
||||||
lda p8v_xpos
|
lda p8v_xpos
|
||||||
sta cx16.VERA_ADDR_L
|
sta cx16.VERA_ADDR_L
|
||||||
|
lda p8v_xpos+1
|
||||||
|
clc
|
||||||
|
adc p8v_buffer_back+1
|
||||||
|
sta cx16.VERA_ADDR_M
|
||||||
|
lda #0
|
||||||
|
rol a ; hi bit carry also needed when double-buffering
|
||||||
|
sta cx16.VERA_ADDR_H
|
||||||
ply ; xbits
|
ply ; xbits
|
||||||
lda p8s_plot.p8v_maskbits,y
|
lda p8s_plot.p8v_maskbits,y
|
||||||
and cx16.VERA_DATA0
|
and cx16.VERA_DATA0
|
||||||
@@ -942,12 +987,12 @@ _doplot beq +
|
|||||||
ror a
|
ror a
|
||||||
lsr a
|
lsr a
|
||||||
lsr a
|
lsr a
|
||||||
clc
|
|
||||||
ldy p8v_yy
|
ldy p8v_yy
|
||||||
|
clc
|
||||||
adc p8v_times40_lsb,y
|
adc p8v_times40_lsb,y
|
||||||
sta cx16.VERA_ADDR_L
|
sta cx16.VERA_ADDR_L
|
||||||
lda p8v_times40_msb,y
|
lda p8v_times40_msb,y
|
||||||
adc #0
|
adc p8v_buffer_back+1
|
||||||
sta cx16.VERA_ADDR_M
|
sta cx16.VERA_ADDR_M
|
||||||
lda #%00010000 ; autoincr
|
lda #%00010000 ; autoincr
|
||||||
sta cx16.VERA_ADDR_H
|
sta cx16.VERA_ADDR_H
|
||||||
@@ -975,8 +1020,11 @@ _doplot beq +
|
|||||||
lda cx16.r0L
|
lda cx16.r0L
|
||||||
sta cx16.VERA_ADDR_L
|
sta cx16.VERA_ADDR_L
|
||||||
lda cx16.r0H
|
lda cx16.r0H
|
||||||
|
clc
|
||||||
|
adc p8v_buffer_back+1
|
||||||
sta cx16.VERA_ADDR_M
|
sta cx16.VERA_ADDR_M
|
||||||
lda #%00010000 ; autoincr
|
lda #%00001000 ; autoincr (1 bit shifted)
|
||||||
|
rol a ; hi bit carry also needed when double-buffering
|
||||||
sta cx16.VERA_ADDR_H
|
sta cx16.VERA_ADDR_H
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@@ -1146,15 +1194,11 @@ cdraw_mod2 ora cx16.VERA_DATA1
|
|||||||
cmp #0
|
cmp #0
|
||||||
beq +
|
beq +
|
||||||
lda #255
|
lda #255
|
||||||
+ ldy #80
|
+ ldy #40
|
||||||
- sta cx16.VERA_DATA0
|
-
|
||||||
sta cx16.VERA_DATA0
|
.rept 16
|
||||||
sta cx16.VERA_DATA0
|
|
||||||
sta cx16.VERA_DATA0
|
|
||||||
sta cx16.VERA_DATA0
|
|
||||||
sta cx16.VERA_DATA0
|
|
||||||
sta cx16.VERA_DATA0
|
|
||||||
sta cx16.VERA_DATA0
|
sta cx16.VERA_DATA0
|
||||||
|
.endrept
|
||||||
dey
|
dey
|
||||||
bne -
|
bne -
|
||||||
rts
|
rts
|
||||||
|
|||||||
@@ -816,6 +816,7 @@ Full-screen lores or hires monochrome bitmap graphics routines, available on the
|
|||||||
- two resolutions: lores 320*240 or hires 640*480 bitmap mode
|
- two resolutions: lores 320*240 or hires 640*480 bitmap mode
|
||||||
- optimized routines for monochrome (2-color) graphics
|
- optimized routines for monochrome (2-color) graphics
|
||||||
- clearing screen, switching screen mode, also back to text mode
|
- clearing screen, switching screen mode, also back to text mode
|
||||||
|
- doublebuffering option to avoid flicker
|
||||||
- drawing and reading individual pixels
|
- drawing and reading individual pixels
|
||||||
- drawing lines, rectangles, filled rectangles, circles, discs
|
- drawing lines, rectangles, filled rectangles, circles, discs
|
||||||
- flood fill
|
- flood fill
|
||||||
@@ -823,7 +824,7 @@ Full-screen lores or hires monochrome bitmap graphics routines, available on the
|
|||||||
- can draw using a stipple pattern (alternate black/white pixels) and in invert mode (toggle pixels)
|
- can draw using a stipple pattern (alternate black/white pixels) and in invert mode (toggle pixels)
|
||||||
|
|
||||||
Read the `monogfx source code <https://github.com/irmen/prog8/tree/master/compiler/res/prog8lib/cx16/monogfx.p8>`_
|
Read the `monogfx source code <https://github.com/irmen/prog8/tree/master/compiler/res/prog8lib/cx16/monogfx.p8>`_
|
||||||
to see what's in there.
|
and the `testmonogfx` example program, to see what's in there.
|
||||||
|
|
||||||
|
|
||||||
palette (cx16 only)
|
palette (cx16 only)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
Bug: monogfx circle, plot and line drawing with INVERT mode is broken (garbage pixels)
|
||||||
|
|
||||||
|
|
||||||
STRUCTS: are being developed in their own separate branch for now, called "structs".
|
STRUCTS: are being developed in their own separate branch for now, called "structs".
|
||||||
Idea is to make it feature complete in the IR/Virtual target, then merge it to master?, and then start building the 6502 code generation for it.
|
Idea is to make it feature complete in the IR/Virtual target, then merge it to master?, and then start building the 6502 code generation for it.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
%import monogfx
|
%import monogfx
|
||||||
%import textio
|
|
||||||
%import math
|
%import math
|
||||||
|
%import conv
|
||||||
|
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
@@ -18,8 +18,7 @@ main {
|
|||||||
sys.wait(2*60)
|
sys.wait(2*60)
|
||||||
demo2()
|
demo2()
|
||||||
|
|
||||||
monogfx.textmode()
|
doublebuffer.demo()
|
||||||
txt.print("done!\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub demofill() {
|
sub demofill() {
|
||||||
@@ -214,3 +213,40 @@ main {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
doublebuffer {
|
||||||
|
sub demo() {
|
||||||
|
monogfx.lores()
|
||||||
|
monogfx.text_charset(1)
|
||||||
|
monogfx.enable_doublebuffer()
|
||||||
|
uword cx = 100
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
monogfx.clear_screen(false)
|
||||||
|
monogfx.text(50, 10, true, iso:"Double Buffered")
|
||||||
|
monogfx.circle(160, 120, 100, true)
|
||||||
|
monogfx.disc(160, 120, 40, true)
|
||||||
|
|
||||||
|
monogfx.rect(40, 40, 240, 180, true)
|
||||||
|
monogfx.drawmode(monogfx.MODE_STIPPLE)
|
||||||
|
monogfx.fill(50, 50, true, 1)
|
||||||
|
|
||||||
|
monogfx.drawmode(monogfx.MODE_NORMAL)
|
||||||
|
monogfx.fill(250, 50, true, 1)
|
||||||
|
monogfx.fillrect( 10, 50, 20, 100, true)
|
||||||
|
monogfx.line(10, 10, 300, 200, true)
|
||||||
|
|
||||||
|
repeat 200 {
|
||||||
|
monogfx.plot($00e0 + math.randrange(64), 20 + math.randrange(20), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
monogfx.circle(cx, 219, 20, true)
|
||||||
|
monogfx.text(cx+20, 225, true, conv.str_uw(cx))
|
||||||
|
cx++
|
||||||
|
monogfx.swap_buffers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,58 +1,21 @@
|
|||||||
%import textio
|
%import math
|
||||||
%zeropage basicsafe
|
%import monogfx
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
word w1, w2, w3, w4
|
monogfx.hires()
|
||||||
uword uw1, uw2, uw3
|
monogfx.fillrect(100, 100, 200, 100, true)
|
||||||
|
|
||||||
w1 = -111
|
sys.wait(60)
|
||||||
w2 = 222
|
|
||||||
w3 = -333
|
|
||||||
w4 = -20
|
|
||||||
|
|
||||||
uw1 = 111
|
monogfx.drawmode(monogfx.MODE_INVERT)
|
||||||
uw2 = 222
|
monogfx.circle(150, 120, 80, true) ; TODO INVERT is BROKEN
|
||||||
uw3 = 333
|
monogfx.line(10, 20, 250, 160, true) ; TODO INVERT is BROKEN
|
||||||
|
|
||||||
txt.print_w(w2*w3)
|
repeat 500 {
|
||||||
txt.spc()
|
monogfx.plot( math.rnd(), math.rnd(), true) ; TODO INVERT is BROKEN
|
||||||
w1 = w2 * w3
|
}
|
||||||
txt.print_w(w1)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_w(w3*w4)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print_uw(uw2*uw3)
|
repeat {}
|
||||||
txt.spc()
|
|
||||||
uw1 = uw2 * uw3
|
|
||||||
txt.print_uw(uw1)
|
|
||||||
txt.nl()
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
|
|
||||||
w1 = -111
|
|
||||||
w2 = 22222
|
|
||||||
w3 = -333
|
|
||||||
w4 = -17
|
|
||||||
|
|
||||||
uw1 = 111
|
|
||||||
uw2 = 22222
|
|
||||||
uw3 = 333
|
|
||||||
|
|
||||||
txt.print_w(w2/w3)
|
|
||||||
txt.spc()
|
|
||||||
w1 = w2 / w3
|
|
||||||
txt.print_w(w1)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_w(w3/w4)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print_uw(uw2/uw3)
|
|
||||||
txt.spc()
|
|
||||||
uw1 = uw2 / uw3
|
|
||||||
txt.print_uw(uw1)
|
|
||||||
txt.nl()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user