gfx2.text() per-pixel positioning implemented for screen modes 1 and 5

This commit is contained in:
Irmen de Jong 2023-07-25 00:43:45 +02:00
parent 2f756f1e3a
commit 3b90be2d9e
2 changed files with 116 additions and 52 deletions

View File

@ -20,6 +20,7 @@
; mode 6 = bitmap 640 x 480 x 4c ; mode 6 = bitmap 640 x 480 x 4c
; higher color dephts in highres are not supported due to lack of VRAM ; higher color dephts in highres are not supported due to lack of VRAM
; TODO remove the phx/plx pairs in non-stack compiler version
gfx2 { gfx2 {
@ -986,48 +987,96 @@ skip:
sub text(uword @zp x, uword y, ubyte color, uword sctextptr) { sub text(uword @zp x, uword y, ubyte color, uword sctextptr) {
; -- Write some text at the given pixel position. The text string must be in screencode encoding (not petscii!). ; -- 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. ; You must also have called text_charset() first to select and prepare the character set to use.
; NOTE: in monochrome (1bpp) screen modes, x position is currently constrained to multiples of 8 ! TODO allow per-pixel horizontal positioning
; TODO draw whole horizontal spans using vera auto increment if possible, instead of per-character columns
uword chardataptr uword chardataptr
ubyte[8] @shared char_bitmap_bytes_left
ubyte[8] @shared char_bitmap_bytes_right
when active_mode { when active_mode {
1, 5 -> { 1, 5 -> {
; monochrome mode, either resolution ; monochrome mode, either resolution
cx16.r2 = 40 cx16.r3 = sctextptr
if active_mode==5 while @(cx16.r3) {
cx16.r2 = 80 chardataptr = charset_addr + @(cx16.r3) * $0008
while @(sctextptr) { ; copy the character bitmap into RAM
chardataptr = charset_addr + (@(sctextptr) as uword)*8 cx16.vaddr_autoincr(charset_bank, chardataptr, 0, 1)
cx16.vaddr(charset_bank, chardataptr, 1, 1)
position(x,y)
%asm {{ %asm {{
lda cx16.VERA_ADDR_H ; pre-shift the bits
and #%111 ; don't auto-increment, we have to do that manually because of the ora phx ; TODO remove in non-stack version
sta cx16.VERA_ADDR_H lda text.x
lda color and #7
sta P8ZP_SCRATCH_B1 sta P8ZP_SCRATCH_B1
ldy #8 ldy #0
- lda P8ZP_SCRATCH_B1 - lda cx16.VERA_DATA0
bne + ; white color, plot normally stz P8ZP_SCRATCH_REG
lda cx16.VERA_DATA1 ldx P8ZP_SCRATCH_B1
eor #255 ; black color, keep only the other pixels cpx #0
and cx16.VERA_DATA0 beq +
bra ++ - lsr a
+ lda cx16.VERA_DATA0 ror P8ZP_SCRATCH_REG
ora cx16.VERA_DATA1 dex
+ sta cx16.VERA_DATA0
lda cx16.VERA_ADDR_L
clc
adc cx16.r2
sta cx16.VERA_ADDR_L
bcc +
inc cx16.VERA_ADDR_M
+ inc x
bne +
inc x+1
+ dey
bne - bne -
+ sta char_bitmap_bytes_left,y
lda P8ZP_SCRATCH_REG
sta char_bitmap_bytes_right,y
iny
cpy #8
bne --
plx ; TODO remove in non-stack version
}} }}
sctextptr++ ; left part of shifted char
position2(x, y, true)
set_autoincrs_mode1_or_5()
if color {
%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(x) & 7 {
position2(x+8, y, true)
set_autoincrs_mode1_or_5()
if color {
%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++
x += 8
} }
} }
4 -> { 4 -> {
@ -1039,7 +1088,7 @@ skip:
position(x,y) position(x,y)
y++ y++
%asm {{ %asm {{
phx phx ; TODO remove in non-stack version
ldx color ldx color
lda cx16.VERA_DATA1 lda cx16.VERA_DATA1
sta P8ZP_SCRATCH_B1 sta P8ZP_SCRATCH_B1
@ -1051,7 +1100,7 @@ skip:
+ lda cx16.VERA_DATA0 ; don't write a pixel, but do advance to the next address + lda cx16.VERA_DATA0 ; don't write a pixel, but do advance to the next address
+ dey + dey
bne - bne -
plx plx ; TODO remove in non-stack version
}} }}
} }
x+=8 x+=8
@ -1068,7 +1117,7 @@ skip:
chardataptr = charset_addr + (@(sctextptr) as uword)*8 chardataptr = charset_addr + (@(sctextptr) as uword)*8
cx16.vaddr(charset_bank, chardataptr, 1, true) ; for reading the chardata from Vera data channel 1 cx16.vaddr(charset_bank, chardataptr, 1, true) ; for reading the chardata from Vera data channel 1
repeat 8 { repeat 8 {
; TODO rewrite this inner loop partly in assembly: ; TODO rewrite this in assembly, don't call plot for every pixel
; requires expanding the charbits to 2-bits per pixel (based on color) ; requires expanding the charbits to 2-bits per pixel (based on color)
; also it's way more efficient to draw whole horizontal spans instead of per-character ; also it's way more efficient to draw whole horizontal spans instead of per-character
cx16.r9L = cx16.VERA_DATA1 ; get the next 8 horizontal character bits cx16.r9L = cx16.VERA_DATA1 ; get the next 8 horizontal character bits
@ -1087,6 +1136,21 @@ skip:
} }
} }
} }
sub set_autoincrs_mode1_or_5() {
; set autoincrements to go to next pixel row (40 or 80 increment)
if active_mode==1 {
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) { asmsub cs_innerloop640() clobbers(Y) {

View File

@ -1,20 +1,20 @@
%import gfx2
main
{
sub start()
{
cx16.set_screen_mode(128)
cx16.vaddr_autoincr(0,320*100+100,1,2) main {
repeat 16 { sub start() {
cx16.VERA_DATA1 = 0 gfx2.screen_mode(1) ; 1 and 5 are lo-res and hi-res monochrome
}
cx16.vaddr_autodecr(0,320*110+100,1,1) uword xx
repeat 16 { gfx2.rect(10, 10, 180, 140, 3)
cx16.VERA_DATA1 = 0 gfx2.rect(12, 12, 180, 140, 3)
for xx in 5 to 100 {
gfx2.text(xx, xx, 1, sc:"hello world! should be pixel-aligned.")
sys.waitvsync()
sys.waitvsync()
gfx2.text(xx, xx, 0, sc:"hello world! should be pixel-aligned.")
} }
repeat { repeat { }
} }
}
} }