mirror of
https://github.com/irmen/prog8.git
synced 2025-01-03 06:29:54 +00:00
gfx_lores.set_screen_mode() is now gfx_lores.graphics_mode()
adding all missing routines from gfx2 to gfx_lores
This commit is contained in:
parent
66b06d6c40
commit
73609636c5
@ -703,7 +703,7 @@ io_error:
|
|||||||
; CommanderX16 extensions over the basic C64/C128 diskio routines:
|
; CommanderX16 extensions over the basic C64/C128 diskio routines:
|
||||||
|
|
||||||
; For use directly after a load or load_raw call (don't mess with the ram bank yet):
|
; For use directly after a load or load_raw call (don't mess with the ram bank yet):
|
||||||
; Calculates the number of bytes loaded (files > 64Kb ar truncated to 16 bits)
|
; Calculates the number of bytes loaded (files > 64Kb are truncated to 16 bits)
|
||||||
sub load_size(ubyte startbank, uword startaddress, uword endaddress) -> uword {
|
sub load_size(ubyte startbank, uword startaddress, uword endaddress) -> uword {
|
||||||
return $2000 * (cx16.getrambank() - startbank) + endaddress - startaddress
|
return $2000 * (cx16.getrambank() - startbank) + endaddress - startaddress
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,18 @@
|
|||||||
; bitmap image needs to start at VRAM addres $00000.
|
; bitmap image needs to start at VRAM addres $00000.
|
||||||
; This is compatible with the CX16's screen mode 128. (void cx16.set_screen_mode(128))
|
; This is compatible with the CX16's screen mode 128. (void cx16.set_screen_mode(128))
|
||||||
|
|
||||||
|
|
||||||
|
%import syslib
|
||||||
%import verafx
|
%import verafx
|
||||||
|
|
||||||
|
|
||||||
gfx_lores {
|
gfx_lores {
|
||||||
|
|
||||||
%option ignore_unused
|
%option ignore_unused
|
||||||
|
|
||||||
sub set_screen_mode() {
|
const uword WIDTH = 320
|
||||||
|
const ubyte HEIGHT = 240
|
||||||
|
|
||||||
|
sub graphics_mode() {
|
||||||
|
; enable 320x240 256c bitmap graphics mode
|
||||||
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
|
||||||
@ -20,6 +24,13 @@ gfx_lores {
|
|||||||
clear_screen(0)
|
clear_screen(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) {
|
sub clear_screen(ubyte color) {
|
||||||
if verafx.available() {
|
if verafx.available() {
|
||||||
; use verafx cache writes to quicly clear the screen
|
; use verafx cache writes to quicly clear the screen
|
||||||
@ -56,10 +67,10 @@ gfx_lores {
|
|||||||
cx16.VERA_CTRL=0
|
cx16.VERA_CTRL=0
|
||||||
cx16.VERA_ADDR=0
|
cx16.VERA_ADDR=0
|
||||||
cx16.VERA_ADDR_H = 1<<4 ; 1 pixel auto increment
|
cx16.VERA_ADDR_H = 1<<4 ; 1 pixel auto increment
|
||||||
repeat 240 {
|
repeat HEIGHT {
|
||||||
%asm {{
|
%asm {{
|
||||||
lda p8v_color
|
lda p8v_color
|
||||||
ldy #320/8
|
ldy #p8c_WIDTH/8
|
||||||
- .rept 8
|
- .rept 8
|
||||||
sta cx16.VERA_DATA0
|
sta cx16.VERA_DATA0
|
||||||
.endrept
|
.endrept
|
||||||
@ -71,24 +82,145 @@ gfx_lores {
|
|||||||
cx16.VERA_ADDR_H = 0
|
cx16.VERA_ADDR_H = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
asmsub plot(uword x @AX, ubyte y @Y, ubyte color @R0) {
|
sub rect(uword xx, ubyte yy, uword rwidth, ubyte rheight, ubyte color) {
|
||||||
; x in r0, y in r1, color.
|
if rwidth==0 or rheight==0
|
||||||
|
return
|
||||||
|
horizontal_line(xx, yy, rwidth, color)
|
||||||
|
if rheight==1
|
||||||
|
return
|
||||||
|
horizontal_line(xx, yy+rheight-1, rwidth, color)
|
||||||
|
vertical_line(xx, yy+1, rheight-2, color)
|
||||||
|
if rwidth==1
|
||||||
|
return
|
||||||
|
vertical_line(xx+rwidth-1, yy+1, rheight-2, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub safe_rect(uword xx, ubyte yy, uword rwidth, ubyte rheight, ubyte color) {
|
||||||
|
; does bounds checking and clipping
|
||||||
|
safe_horizontal_line(xx, yy, rwidth, color)
|
||||||
|
if rheight==1
|
||||||
|
return
|
||||||
|
uword bottomyy = yy as uword + rheight -1
|
||||||
|
if bottomyy<HEIGHT
|
||||||
|
safe_horizontal_line(xx, lsb(bottomyy), rwidth, color)
|
||||||
|
safe_vertical_line(xx, yy+1, rheight-2, color)
|
||||||
|
if rwidth==1
|
||||||
|
return
|
||||||
|
safe_vertical_line(xx+rwidth-1, yy+1, rheight-2, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub fillrect(uword xx, ubyte yy, uword rwidth, ubyte rheight, ubyte color) {
|
||||||
|
; Draw a filled rectangle of the given size and color.
|
||||||
|
; To fill the whole screen, use clear_screen(color) instead - it is much faster.
|
||||||
|
if rwidth==0
|
||||||
|
return
|
||||||
|
repeat rheight {
|
||||||
|
horizontal_line(xx, yy, rwidth, color)
|
||||||
|
yy++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub safe_fillrect(uword xx, ubyte yy, uword rwidth, ubyte rheight, ubyte color) {
|
||||||
|
; 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>=HEIGHT
|
||||||
|
return
|
||||||
|
if msb(xx)&$80!=0 {
|
||||||
|
rwidth += xx
|
||||||
|
xx = 0
|
||||||
|
}
|
||||||
|
if xx>=WIDTH
|
||||||
|
return
|
||||||
|
if xx+rwidth>WIDTH
|
||||||
|
rwidth = WIDTH-xx
|
||||||
|
if rwidth>WIDTH
|
||||||
|
return
|
||||||
|
|
||||||
|
if yy as uword + rheight > HEIGHT
|
||||||
|
rheight = HEIGHT-yy
|
||||||
|
if rheight>HEIGHT
|
||||||
|
return
|
||||||
|
|
||||||
|
repeat rheight {
|
||||||
|
horizontal_line(xx, yy, rwidth, color)
|
||||||
|
yy++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub horizontal_line(uword xx, ubyte yy, uword length, ubyte color) {
|
||||||
|
if length==0
|
||||||
|
return
|
||||||
|
plot(xx, yy, color) ; set starting position by reusing plot routine
|
||||||
|
; set vera auto-increment to 1 pixel
|
||||||
|
cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & %00000111 | (1<<4)
|
||||||
|
|
||||||
%asm {{
|
%asm {{
|
||||||
clc
|
lda p8v_color
|
||||||
adc times320_lo,y
|
ldx p8v_length+1
|
||||||
sta cx16.VERA_ADDR_L
|
beq +
|
||||||
txa
|
ldy #0
|
||||||
adc times320_mid,y
|
- sta cx16.VERA_DATA0
|
||||||
sta cx16.VERA_ADDR_M
|
iny
|
||||||
lda #0
|
bne -
|
||||||
adc times320_hi,y
|
dex
|
||||||
sta cx16.VERA_ADDR_H
|
bne -
|
||||||
lda cx16.r0L
|
+ ldy p8v_length ; remaining
|
||||||
sta cx16.VERA_DATA0
|
beq +
|
||||||
rts
|
- sta cx16.VERA_DATA0
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
+
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub safe_horizontal_line(uword xx, ubyte yy, uword length, ubyte color) {
|
||||||
|
; does bounds checking and clipping
|
||||||
|
if yy>=HEIGHT
|
||||||
|
return
|
||||||
|
if msb(xx)&$80!=0 {
|
||||||
|
length += xx
|
||||||
|
xx = 0
|
||||||
|
}
|
||||||
|
if xx>=WIDTH
|
||||||
|
return
|
||||||
|
if xx+length>WIDTH
|
||||||
|
length = WIDTH-xx
|
||||||
|
if length>WIDTH
|
||||||
|
return
|
||||||
|
|
||||||
|
horizontal_line(xx, yy, length, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vertical_line(uword xx, ubyte yy, ubyte lheight, ubyte color) {
|
||||||
|
if lheight==0
|
||||||
|
return
|
||||||
|
plot(xx, yy, color) ; set starting position by reusing plot routine
|
||||||
|
; set vera auto-increment to 320 pixel increment (=next line)
|
||||||
|
cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & %00000111 | (14<<4)
|
||||||
|
%asm {{
|
||||||
|
ldy p8v_lheight
|
||||||
|
lda p8v_color
|
||||||
|
- sta cx16.VERA_DATA0
|
||||||
|
dey
|
||||||
|
bne -
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub safe_vertical_line(uword xx, ubyte yy, ubyte lheight, ubyte color) {
|
||||||
|
; does bounds checking and clipping
|
||||||
|
if yy>=HEIGHT
|
||||||
|
return
|
||||||
|
if msb(xx)&$80!=0 or xx>=WIDTH
|
||||||
|
return
|
||||||
|
if yy as uword + lheight > HEIGHT
|
||||||
|
lheight = HEIGHT-yy
|
||||||
|
if lheight>HEIGHT
|
||||||
|
return
|
||||||
|
|
||||||
|
vertical_line(xx, yy, lheight, color)
|
||||||
|
}
|
||||||
|
|
||||||
sub line(uword x1, ubyte y1, uword x2, ubyte y2, ubyte color) {
|
sub line(uword x1, ubyte y1, uword x2, ubyte y2, ubyte color) {
|
||||||
; Bresenham algorithm.
|
; Bresenham algorithm.
|
||||||
; This code special-cases various quadrant loops to allow simple ++ and -- operations.
|
; This code special-cases various quadrant loops to allow simple ++ and -- operations.
|
||||||
@ -214,48 +346,491 @@ gfx_lores {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub horizontal_line(uword xx, ubyte yy, uword length, ubyte color) {
|
sub circle(uword @zp xcenter, ubyte @zp ycenter, ubyte radius, ubyte color) {
|
||||||
if length==0
|
; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen.
|
||||||
|
; Midpoint algorithm.
|
||||||
|
if radius==0
|
||||||
return
|
return
|
||||||
plot(xx, yy, color) ; set starting position by reusing plot routine
|
|
||||||
; set vera auto-increment to 1 pixel
|
|
||||||
cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & %00000111 | (1<<4)
|
|
||||||
|
|
||||||
|
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
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter + xx
|
||||||
|
cx16.r15 = ycenter - yy
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter + yy
|
||||||
|
cx16.r15 = ycenter + xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - yy
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter + yy
|
||||||
|
cx16.r15 = ycenter - xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - yy
|
||||||
|
plotq()
|
||||||
|
|
||||||
|
yy++
|
||||||
|
if decisionOver2>=0 {
|
||||||
|
xx--
|
||||||
|
decisionOver2 -= xx*$0002
|
||||||
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plotq() {
|
||||||
|
; cx16.r14 = x, cx16.r15 = y, color=color.
|
||||||
|
plot(cx16.r14, cx16.r15L, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub safe_circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, ubyte color) {
|
||||||
|
; This version does bounds checks and clipping, but is a lot slower.
|
||||||
|
; 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
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter + xx
|
||||||
|
cx16.r15 = ycenter - yy
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter + yy
|
||||||
|
cx16.r15 = ycenter + xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - yy
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter + yy
|
||||||
|
cx16.r15 = ycenter - xx
|
||||||
|
plotq()
|
||||||
|
cx16.r14 = xcenter - yy
|
||||||
|
plotq()
|
||||||
|
|
||||||
|
yy++
|
||||||
|
if decisionOver2>=0 {
|
||||||
|
xx--
|
||||||
|
decisionOver2 -= xx*$0002
|
||||||
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
|
}
|
||||||
|
|
||||||
|
sub plotq() {
|
||||||
|
; cx16.r14 = x, cx16.r15 = y, color=color.
|
||||||
|
if cx16.r15 < HEIGHT
|
||||||
|
safe_plot(cx16.r14, cx16.r15L, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub disc(uword @zp xcenter, ubyte @zp ycenter, ubyte @zp radius, ubyte color) {
|
||||||
|
; Warning: NO BOUNDS CHECKS. Make sure circle fits in the screen.
|
||||||
|
; Midpoint algorithm, filled
|
||||||
|
if radius==0
|
||||||
|
return
|
||||||
|
ubyte @zp yy = 0
|
||||||
|
word @zp decisionOver2 = (1 as word)-radius
|
||||||
|
ubyte last_y3 = ycenter+radius
|
||||||
|
ubyte last_y4 = ycenter-radius
|
||||||
|
ubyte new_y3, new_y4
|
||||||
|
|
||||||
|
while radius>=yy {
|
||||||
|
horizontal_line(xcenter-radius, ycenter+yy, radius*$0002+1, color)
|
||||||
|
horizontal_line(xcenter-radius, ycenter-yy, radius*$0002+1, color)
|
||||||
|
|
||||||
|
new_y3 = ycenter+radius
|
||||||
|
if new_y3 != last_y3 {
|
||||||
|
horizontal_line(xcenter-yy, last_y3, yy*$0002+1, color)
|
||||||
|
last_y3 = new_y3
|
||||||
|
}
|
||||||
|
new_y4 = ycenter-radius
|
||||||
|
if new_y4 != last_y4 {
|
||||||
|
horizontal_line(xcenter-yy, last_y4, yy*$0002+1, color)
|
||||||
|
last_y4 = new_y4
|
||||||
|
}
|
||||||
|
|
||||||
|
yy++
|
||||||
|
if decisionOver2>=0 {
|
||||||
|
radius--
|
||||||
|
decisionOver2 -= radius*$0002
|
||||||
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
|
}
|
||||||
|
|
||||||
|
; draw the final two spans
|
||||||
|
yy--
|
||||||
|
horizontal_line(xcenter-yy, last_y3, yy*$0002+1, color)
|
||||||
|
horizontal_line(xcenter-yy, last_y4, yy*$0002+1, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub safe_disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, ubyte color) {
|
||||||
|
; This version does bounds checks and clipping, but is a lot slower.
|
||||||
|
; Midpoint algorithm, filled
|
||||||
|
if radius==0
|
||||||
|
return
|
||||||
|
ubyte @zp yy = 0
|
||||||
|
word @zp decisionOver2 = (1 as word)-radius
|
||||||
|
uword last_y3 = ycenter+radius
|
||||||
|
uword last_y4 = ycenter-radius
|
||||||
|
uword new_y3, new_y4
|
||||||
|
|
||||||
|
while radius>=yy {
|
||||||
|
uword liney = ycenter+yy
|
||||||
|
if msb(liney)==0
|
||||||
|
safe_horizontal_line(xcenter-radius, lsb(ycenter+yy), radius*$0002+1, color)
|
||||||
|
liney = ycenter-yy
|
||||||
|
if msb(liney)==0
|
||||||
|
safe_horizontal_line(xcenter-radius, lsb(ycenter-yy), radius*$0002+1, color)
|
||||||
|
new_y3 = ycenter+radius
|
||||||
|
if new_y3 != last_y3 {
|
||||||
|
if msb(last_y3)==0
|
||||||
|
safe_horizontal_line(xcenter-yy, lsb(last_y3), yy*$0002+1, color)
|
||||||
|
last_y3 = new_y3
|
||||||
|
}
|
||||||
|
new_y4 = ycenter-radius
|
||||||
|
if new_y4 != last_y4 {
|
||||||
|
if msb(last_y4)==0
|
||||||
|
safe_horizontal_line(xcenter-yy, lsb(last_y4), yy*$0002+1, color)
|
||||||
|
last_y4 = new_y4
|
||||||
|
}
|
||||||
|
yy++
|
||||||
|
if decisionOver2>=0 {
|
||||||
|
radius--
|
||||||
|
decisionOver2 -= radius*$0002
|
||||||
|
}
|
||||||
|
decisionOver2 += yy*$0002
|
||||||
|
decisionOver2++
|
||||||
|
}
|
||||||
|
; draw the final two spans
|
||||||
|
yy--
|
||||||
|
if msb(last_y3)==0
|
||||||
|
safe_horizontal_line(xcenter-yy, lsb(last_y3), yy*$0002+1, color)
|
||||||
|
if msb(last_y4)==0
|
||||||
|
safe_horizontal_line(xcenter-yy, lsb(last_y4), yy*$0002+1, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub plot(uword x @AX, ubyte y @Y, ubyte color @R0) {
|
||||||
|
; x in r0, y in r1, color.
|
||||||
%asm {{
|
%asm {{
|
||||||
lda p8v_color
|
clc
|
||||||
ldx p8v_length+1
|
adc times320_lo,y
|
||||||
|
sta cx16.VERA_ADDR_L
|
||||||
|
txa
|
||||||
|
adc times320_mid,y
|
||||||
|
sta cx16.VERA_ADDR_M
|
||||||
|
lda #0
|
||||||
|
adc times320_hi,y
|
||||||
|
sta cx16.VERA_ADDR_H
|
||||||
|
lda cx16.r0L
|
||||||
|
sta cx16.VERA_DATA0
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub safe_plot(uword xx, ubyte yy, ubyte color) {
|
||||||
|
; A plot that does bounds checks to see if the pixel is inside the screen.
|
||||||
|
if msb(xx)&$80!=0
|
||||||
|
return
|
||||||
|
if xx >= WIDTH or yy >= HEIGHT
|
||||||
|
return
|
||||||
|
plot(xx, yy, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub pget(uword x @AX, ubyte y @Y) -> ubyte @A {
|
||||||
|
; returns the color of the pixel
|
||||||
|
%asm {{
|
||||||
|
jsr p8s_position
|
||||||
|
lda cx16.VERA_DATA0
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub fill(uword x, ubyte y, ubyte new_color) {
|
||||||
|
; reuse a few virtual registers in ZP for variables
|
||||||
|
&ubyte fillm = &cx16.r7L
|
||||||
|
&ubyte seedm = &cx16.r8L
|
||||||
|
&ubyte cmask = &cx16.r8H
|
||||||
|
&ubyte vub = &cx16.r13L
|
||||||
|
&ubyte nvub = &cx16.r13H
|
||||||
|
ubyte[4] amask = [$c0,$30,$0c,$03] ; array of cmask bytes
|
||||||
|
|
||||||
|
; 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 = 100
|
||||||
|
word @zp xx = x as word
|
||||||
|
word @zp yy = y as word
|
||||||
|
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 = new_color
|
||||||
|
|
||||||
|
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 p8v_sxl
|
||||||
|
sta p8v_stack_xl_lsb,y
|
||||||
|
lda p8v_sxl+1
|
||||||
|
sta p8v_stack_xl_msb,y
|
||||||
|
lda p8v_sxr
|
||||||
|
sta p8v_stack_xr_lsb,y
|
||||||
|
lda p8v_sxr+1
|
||||||
|
sta p8v_stack_xr_msb,y
|
||||||
|
lda p8v_sy
|
||||||
|
sta p8v_stack_y_lsb,y
|
||||||
|
lda p8v_sy+1
|
||||||
|
sta p8v_stack_y_msb,y
|
||||||
|
ldy cx16.r12L
|
||||||
|
lda p8v_sdy
|
||||||
|
sta p8v_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 p8v_stack_xl_lsb,y
|
||||||
|
sta p8v_x1
|
||||||
|
lda p8v_stack_xl_msb,y
|
||||||
|
sta p8v_x1+1
|
||||||
|
lda p8v_stack_xr_lsb,y
|
||||||
|
sta p8v_x2
|
||||||
|
lda p8v_stack_xr_msb,y
|
||||||
|
sta p8v_x2+1
|
||||||
|
lda p8v_stack_y_lsb,y
|
||||||
|
sta p8v_yy
|
||||||
|
lda p8v_stack_y_msb,y
|
||||||
|
sta p8v_yy+1
|
||||||
|
ldy cx16.r12L
|
||||||
|
lda p8v_stack_dy,y
|
||||||
|
sta p8v_dy
|
||||||
|
}}
|
||||||
|
yy+=dy
|
||||||
|
}
|
||||||
|
cx16.r11L = pget(xx as uword, lsb(yy)) ; 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!=0 {
|
||||||
|
pop_stack()
|
||||||
|
xx = x1
|
||||||
|
if fill_scanline_left_8bpp() goto skip
|
||||||
|
left = xx + 1
|
||||||
|
if left < x1
|
||||||
|
push_stack(left, x1 - 1, yy, -dy)
|
||||||
|
xx = x1 + 1
|
||||||
|
|
||||||
|
do {
|
||||||
|
fill_scanline_right_8bpp()
|
||||||
|
push_stack(left, xx - 1, yy, dy)
|
||||||
|
if xx > x2 + 1
|
||||||
|
push_stack(x2 + 1, xx - 1, yy, -dy)
|
||||||
|
skip:
|
||||||
|
xx++
|
||||||
|
while xx <= x2 {
|
||||||
|
if pget(xx as uword, lsb(yy)) == cx16.r11L
|
||||||
|
break
|
||||||
|
xx++
|
||||||
|
}
|
||||||
|
left = xx
|
||||||
|
} until xx>x2
|
||||||
|
}
|
||||||
|
|
||||||
|
sub set_vera_address(bool decr) {
|
||||||
|
; set both data0 and data1 addresses
|
||||||
|
position(xx as uword, lsb(yy))
|
||||||
|
cx16.r0 = cx16.VERA_ADDR
|
||||||
|
cx16.r1L = cx16.VERA_ADDR_H & 1 | if decr %00011000 else %00010000
|
||||||
|
cx16.VERA_ADDR_H = cx16.r1L
|
||||||
|
cx16.VERA_CTRL = 1
|
||||||
|
cx16.VERA_ADDR = cx16.r0
|
||||||
|
cx16.VERA_ADDR_H = cx16.r1L
|
||||||
|
cx16.VERA_CTRL = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
sub fill_scanline_left_8bpp() -> bool {
|
||||||
|
set_vera_address(true)
|
||||||
|
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() {
|
||||||
|
set_vera_address(false)
|
||||||
|
while xx <= WIDTH-1 {
|
||||||
|
if cx16.VERA_DATA0 != cx16.r11L
|
||||||
|
break
|
||||||
|
cx16.VERA_DATA1 = cx16.r10L
|
||||||
|
xx++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 etc. etc.
|
||||||
|
cx16.screen_set_charset(charset, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ubyte charset_bank = $1
|
||||||
|
const uword charset_addr = $f000 ; in bank 1, so $1f000
|
||||||
|
|
||||||
|
sub text(uword @zp xx, uword yy, ubyte color, uword textptr) {
|
||||||
|
; -- Write some text at the given pixel position. The text string must be in an encoding approprite for the charset.
|
||||||
|
; 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
|
||||||
|
|
||||||
|
while @(textptr)!=0 {
|
||||||
|
chardataptr = charset_addr + (@(textptr) as uword)*8
|
||||||
|
cx16.vaddr(charset_bank, chardataptr, 1, 1)
|
||||||
|
repeat 8 {
|
||||||
|
position(xx,lsb(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
|
||||||
|
textptr++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub position(uword x @AX, ubyte y @Y) {
|
||||||
|
%asm {{
|
||||||
|
clc
|
||||||
|
adc times320_lo,y
|
||||||
|
sta cx16.VERA_ADDR_L
|
||||||
|
txa
|
||||||
|
adc times320_mid,y
|
||||||
|
sta cx16.VERA_ADDR_M
|
||||||
|
lda #%00010000 ; auto increment on
|
||||||
|
adc times320_hi,y
|
||||||
|
sta cx16.VERA_ADDR_H
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline asmsub next_pixel(ubyte color @A) {
|
||||||
|
; -- sets the next pixel byte to the graphics chip.
|
||||||
|
; for 8 bpp screens this will plot 1 pixel.
|
||||||
|
; for 2 bpp screens it will plot 4 pixels at once (color = bit pattern).
|
||||||
|
%asm {{
|
||||||
|
sta cx16.VERA_DATA0
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
asmsub next_pixels(uword pixels @AY, uword amount @R0) clobbers(A, X, Y) {
|
||||||
|
; -- sets the next bunch of pixels from a prepared array of bytes.
|
||||||
|
; for 8 bpp screens this will plot 1 pixel per byte.
|
||||||
|
; for 2 bpp screens it will plot 4 pixels at once (colors are the bit patterns per byte).
|
||||||
|
%asm {{
|
||||||
|
sta P8ZP_SCRATCH_W1
|
||||||
|
sty P8ZP_SCRATCH_W1+1
|
||||||
|
ldx cx16.r0+1
|
||||||
beq +
|
beq +
|
||||||
ldy #0
|
ldy #0
|
||||||
- sta cx16.VERA_DATA0
|
- lda (P8ZP_SCRATCH_W1),y
|
||||||
|
sta cx16.VERA_DATA0
|
||||||
iny
|
iny
|
||||||
bne -
|
bne -
|
||||||
|
inc P8ZP_SCRATCH_W1+1 ; next page of 256 pixels
|
||||||
dex
|
dex
|
||||||
bne -
|
bne -
|
||||||
+ ldy p8v_length ; remaining
|
|
||||||
|
+ ldx cx16.r0 ; remaining pixels
|
||||||
beq +
|
beq +
|
||||||
- sta cx16.VERA_DATA0
|
ldy #0
|
||||||
dey
|
- lda (P8ZP_SCRATCH_W1),y
|
||||||
|
sta cx16.VERA_DATA0
|
||||||
|
iny
|
||||||
|
dex
|
||||||
bne -
|
bne -
|
||||||
+
|
+ rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub vertical_line(uword xx, ubyte yy, ubyte lheight, ubyte color) {
|
asmsub set_8_pixels_from_bits(ubyte bits @R0, ubyte oncolor @A, ubyte offcolor @Y) clobbers(X) {
|
||||||
if lheight==0
|
; this is only useful in 256 color mode where one pixel equals one byte value.
|
||||||
return
|
|
||||||
plot(xx, yy, color) ; set starting position by reusing plot routine
|
|
||||||
; set vera auto-increment to 320 pixel increment (=next line)
|
|
||||||
cx16.VERA_ADDR_H = cx16.VERA_ADDR_H & %00000111 | (14<<4)
|
|
||||||
%asm {{
|
%asm {{
|
||||||
ldy p8v_lheight
|
ldx #8
|
||||||
lda p8v_color
|
- asl cx16.r0
|
||||||
- sta cx16.VERA_DATA0
|
bcc +
|
||||||
dey
|
sta cx16.VERA_DATA0
|
||||||
|
bra ++
|
||||||
|
+ sty cx16.VERA_DATA0
|
||||||
|
+ dex
|
||||||
bne -
|
bne -
|
||||||
|
rts
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
%asm {{
|
%asm {{
|
||||||
; multiplication by 320 lookup table
|
; multiplication by 320 lookup table
|
||||||
times320 := 320*range(240)
|
times320 := 320*range(240)
|
||||||
@ -265,4 +840,3 @@ times320_mid .byte >times320
|
|||||||
times320_hi .byte `times320
|
times320_hi .byte `times320
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
Allow %merge to overwrite existing subs if the signature is identical?
|
Transform gfx2 into gfx_hires
|
||||||
|
Add a eor mode to gfx_lores / gfx_hires
|
||||||
|
|
||||||
Improve register load order in subroutine call args assignments:
|
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
|
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
|
||||||
|
@ -25,7 +25,7 @@ main {
|
|||||||
uword[NUM_STARS] @split prev_x
|
uword[NUM_STARS] @split prev_x
|
||||||
ubyte[NUM_STARS] prev_y
|
ubyte[NUM_STARS] prev_y
|
||||||
|
|
||||||
gfx_lores.set_screen_mode()
|
gfx_lores.graphics_mode()
|
||||||
|
|
||||||
; init the star positions
|
; init the star positions
|
||||||
ubyte star
|
ubyte star
|
||||||
|
@ -1,26 +1,38 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import gfx2
|
||||||
|
%import gfx_lores
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
txt.print("sdfdsf")
|
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
txt {
|
|
||||||
; merges this block into the txt block coming from the textio library
|
|
||||||
%option merge
|
|
||||||
|
|
||||||
sub print(str text) {
|
|
||||||
repeat 4 chrout('@')
|
|
||||||
repeat {
|
repeat {
|
||||||
cx16.r0L = @(text)
|
|
||||||
if_z break
|
|
||||||
chrout(cx16.r0L)
|
|
||||||
text++
|
|
||||||
}
|
|
||||||
repeat 4 chrout('@')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user