1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-25 17:29:50 +00:00

Final touches to the first full version of the vector font output.

git-svn-id: svn://svn.cc65.org/cc65/trunk@4464 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2009-11-12 18:00:17 +00:00
parent 5dc80c2615
commit d1e4687540
6 changed files with 312 additions and 140 deletions

View File

@ -1,12 +1,16 @@
;
; Ullrich von Bassewitz, 2009-11-05
;
; Helper function for functions using sine/cosine: Multiply two values, one
; being an 8.8 fixed point one, and return the rounded and scaled result.
; Helper function for graphics functions: Multiply two values, one being
; an 8.8 fixed point one, and return the rounded and scaled result.
;
; The module has two entry points: One is C callable and expects the
; parameters in ax and the stack, the second is assembler callable and
; expects the parameters in ax and ptr1
;
.export _tgi_imulround
.export _tgi_imulround, tgi_imulround
.import popax, imul16x16r32
.include "zeropage.inc"
@ -16,7 +20,9 @@
;
.code
.proc _tgi_imulround
; C callable entry point
_tgi_imulround:
; Get arguments
@ -24,6 +30,9 @@
stx ptr1+1 ; Save lhs
jsr popax ; Get rhs
; ASM callable entry point
tgi_imulround:
; Multiplicate
jsr imul16x16r32
@ -51,4 +60,4 @@
tya
rts
.endproc

View File

@ -12,7 +12,7 @@
.bss
; Clipping coordinates.
; Clipping coordinates. They must be in this order!
tgi_clip_x1: .res 2
tgi_clip_y1: .res 2
tgi_clip_x2: .res 2
@ -42,7 +42,7 @@ tgi_clip_y2: .res 2
;
.code
.proc tgi_outcode
.proc tgi_outcode
lda #TGI_CLIP_NONE
sta tmp1

View File

@ -9,6 +9,7 @@
.include "tgi-vectorfont.inc"
.include "zeropage.inc"
.import _toascii
.import popax, negax
@ -16,6 +17,8 @@
; Data
text := regbank
font := regbank ; Same as text
widths := regbank+2
;----------------------------------------------------------------------------
;
@ -40,6 +43,10 @@ text := regbank
tax
pla ; Restore s
jsr _tgi_textwidth ; Get width of text string
; Move the graphics cursor by the amount in a/x
MoveCursor:
ldy _tgi_textdir ; Horizontal or vertical text?
beq @L1 ; Jump if horizontal
@ -56,9 +63,10 @@ text := regbank
txa
adc _tgi_curx+1,y
sta _tgi_curx+1,y
rts
Done: rts
; Handle vector font output
; Handle vector font output. First, check if we really have a registered
; vector font. Bail out if this is not the case.
VectorFont:
tay
@ -66,20 +74,58 @@ VectorFont:
ora _tgi_vectorfont+1
beq Done ; Bail out if not
lda text ; Save zero page variable on stack
; Check if the font in the given size is partially out of the screen. We
; do this in vertical direction here, and in horizontal direction before
; outputting a character.
; (todo)
; Save zero page variable on stack and save
lda text
pha
lda text+1
pha
lda widths
pha
lda widths+1
pha
sty text
stx text+1 ; Store pointer to string
lda _tgi_vectorfont
clc
adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
sta widths
lda _tgi_vectorfont+1
adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
sta widths+1
; Output the text string
@L1: ldy #0
lda (text),y ; Get next character from string
beq EndOfText
jsr _toascii ; Convert to ascii
pha ; Save char in A
jsr _tgi_vectorchar ; Output it
pla
; Move the graphics cursor by the width of the char
tay
lda (widths),y ; Get width of this char
sta ptr1
lda #0
sta ptr1+1
lda _tgi_textscalew
ldx _tgi_textscalew+1 ; Get scale factor
jsr tgi_imulround ; Multiplcate and round
jsr MoveCursor ; Move the graphics cursor
; Next char in string
inc text
bne @L1
inc text+1
@ -88,11 +134,15 @@ VectorFont:
; Done. Restore registers and return
EndOfText:
pla
sta widths+1
pla
sta widths
pla
sta text+1
pla
sta text
Done: rts
rts
.endproc

View File

@ -4,20 +4,51 @@
.include "tgi-kernel.inc"
.include "tgi-vectorfont.inc"
.include "zeropage.inc"
;-----------------------------------------------------------------------------
; unsigned __fastcall__ tgi_textheight (const char* s);
; /* Calculate the width of the text in pixels according to the current text
; /* Calculate the height of the text in pixels according to the current text
; * style.
; */
;
.proc _tgi_textheight
ldy _tgi_font
bne @L2 ; Jump if vector font
; Return the height for the bitmap font
lda _tgi_charheight
ldx #0
rts
@L1: rts
; Return the height for the vector font
@L2: lda _tgi_vectorfont
tax
ora _tgi_vectorfont+1
beq @L1 ; Return zero if no font
stx ptr1
lda _tgi_vectorfont+1
sta ptr1+1
ldy #TGI_VECTORFONT::TOP
lda (ptr1),y
ldy #TGI_VECTORFONT::BOTTOM
clc
adc (ptr1),y ; Total font height is top + bottom
sta ptr1
lda #0
sta ptr1+1 ; Save base height in ptr1
lda _tgi_textscaleh
ldx _tgi_textscaleh+1 ; Get scale factor ...
jmp tgi_imulround ; ... and return scaled result
.endproc

View File

@ -4,8 +4,20 @@
.include "tgi-kernel.inc"
.include "tgi-vectorfont.inc"
.include "zeropage.inc"
.import _strlen, _toascii
.import umul16x16r32
;-----------------------------------------------------------------------------
; Aliases for zero page locations
Width := ptr1
WTab := ptr2
Text := ptr3
.import _strlen, pushax, tosumula0
;-----------------------------------------------------------------------------
; unsigned __fastcall__ tgi_textwidth (const char* s);
@ -16,12 +28,75 @@
; Result is strlen (s) * tgi_textmagw * tgi_fontsizex
;
.code
.proc _tgi_textwidth
ldy _tgi_font
bne @L1 ; Jump if vector font
; Return the width of the string for the bitmap font
jsr _strlen
jsr pushax
sta ptr1
stx ptr1+1
lda _tgi_charwidth
jmp tosumula0
ldx #0
jmp umul16x16r32
; Return the width of the string for the vector font. To save some code, we
; will add up all the character widths and then multiply by the scale factor.
; Since the output routine will scale each single character, the result may
; be slightly different.
@L1: sta Text
stx Text+1 ; Save pointer to string
lda _tgi_vectorfont+1
tax
ora _tgi_vectorfont
beq @L9 ; Return zero if no font
lda _tgi_vectorfont
clc
adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
sta WTab
txa
adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
sta WTab+1
ldy #0
sty Width
sty Width+1 ; Zero the total width
; Sum up the widths of the single characters
@L2: ldy #0
lda (Text),y ; Get next char
beq @L4 ; Bail out if end of text reached
jsr _toascii ; Convert to ascii
tay
lda (WTab),y ; Get width of this char
clc
adc Width
sta Width
bcc @L3
inc Width+1
@L3: inc Text
bne @L2
inc Text+1
bne @L2
; We have the total width now, scale and return it
@L4: lda _tgi_textscalew
ldx _tgi_textscalew+1
jmp tgi_imulround
; Exit point if no font installed
@L9: rts
.endproc

View File

@ -7,7 +7,7 @@
; */
;
.import _toascii, imul16x16r32, umul16x16r32, negax, negeax
.import imul16x16r32, umul16x16r32, negax, negeax
.include "tgi-kernel.inc"
.include "tgi-vectorfont.inc"
@ -26,13 +26,10 @@ X1: .res 2
Y1: .res 2
X2: .res 2
Y2: .res 2
BaseX: .res 2
BaseY: .res 2
Char: .res 1
;----------------------------------------------------------------------------
; Get the next operation from the Ops pointer, remove the flag bit and sign
; extend the 8 bit value. On return, the flags are set for the value in A.
; extend the 8 bit value to 16 bits.
.code
.proc GetOp
@ -45,78 +42,88 @@ Char: .res 1
bne :+
inc Ops+1
; Move bit 7 into Flag, then sign extend the value in A
; Move bit 7 into Flag, then sign extend the value in A and extend the sign
; into X.
: asl a ; Flag into carry
ror Flag
ldx #0
cmp #$80 ; Sign bit into carry
ror a ; Sign extend the value
bpl :+
dex ; Value is negative
; Done
rts
: rts
.endproc
;----------------------------------------------------------------------------
; Round a 16.8 fixed point value in eax
.code
.proc RoundFix
cmp #$80 ; frac(val) >= 0.5?
txa
ldx sreg
adc #$00
bcc @L1
inx
@L1: rts
.endproc
;----------------------------------------------------------------------------
; Get and process one coordinate value. The scale factor is passed in a/x
.code
.proc GetProcessedCoord
GetProcessedYCoord:
lda _tgi_textscaleh+0
ldx _tgi_textscaleh+1
GetProcessedCoord:
; Save scale factor as left operand for multiplication
sta ptr1
stx ptr1+1
; Load next operation value. This will set the flags for the value in A.
; Load next operation value.
jsr GetOp
; Since we know that the scale factor is always positive, we will remember
; the sign of the coordinate offset, make it positive, do an unsigned mul
; and negate the result if the vector was negative. This is faster than
; relying on the signed multiplication, which will do the same, but for
; both operands.
sta tmp1 ; Remember sign of vector offset
bpl :+
eor #$FF
clc
adc #$01 ; Negate
: ldx #$00 ; High byte is always zero
; Multiplicate with the scale factor.
jsr umul16x16r32 ; Multiplicate
jmp tgi_imulround ; Multiplicate, round and scale
; The result is a 16.8 fixed point value. Round it.
;----------------------------------------------------------------------------
; Add the base coordinate with offset in Y to the value in A/X
jsr RoundFix
.code
.proc AddBaseCoord
; Check the sign and negate if necessary
clc
adc _tgi_curx+0,y
pha
txa
adc _tgi_curx+1,y
tax
pla
rts
bit tmp1 ; Check sign
bpl :+
jmp negax ; Negate result if necessary
: rts
.endproc
;----------------------------------------------------------------------------
; Subtract the value in a/x from the base coordinate with offset in Y
; This is
;
; ax = _tgi_cur[xy] - ax
;
; which can be transformed to
;
; ax = _tgi_cur[xy] + (~ax + 1);
.code
.proc SubBaseCoord
eor #$FF
sec ; + 1
adc _tgi_curx+0,y
pha
txa
eor #$FF
adc _tgi_curx+1,y
tax
pla
rts
.endproc
@ -126,9 +133,8 @@ Char: .res 1
.code
.proc _tgi_vectorchar
; Convert the character to ASCII, multiplicate by two and save into Y
; Multiplicate the char value by two and save into Y
jsr _toascii
asl a
tay
@ -142,59 +148,6 @@ Char: .res 1
lda Flag
pha
; Get the width of the char in question
lda _tgi_vectorfont
clc
adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
sta Ops
lda _tgi_vectorfont+1
adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
sta Ops+1
lda (Ops),y
; Save the character
sty Char
; Calculate the width of the character by multiplying with the scale
; factor for the width
sta ptr1
lda #0
sta ptr1+1
lda _tgi_textscalew
ldx _tgi_textscalew+1
jsr umul16x16r32
jsr RoundFix
; Store the current value of the graphics cursor into BaseX/BaseY, then
; move it to the next character position
pha
ldy #3
: lda _tgi_curx,y
sta BaseX,y
dey
bpl :-
pla
ldy _tgi_textdir
beq :+ ; Jump if horizontal text
jsr negax
ldy #2 ; Offset of tgi_cury
; Advance graphics cursor
: clc
adc _tgi_curx,y
sta _tgi_curx,y
txa
adc _tgi_curx+1,y
sta _tgi_curx+1,y
; Calculate a pointer to the vector ops for the given char (now in Y). We
; definitely expect a font here, that has to be checked by the caller.
@ -206,7 +159,6 @@ Char: .res 1
adc #>(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
sta Ops+1
ldy Char
iny
lda (Ops),y
tax
@ -221,38 +173,84 @@ Loop: lda _tgi_textscalew+0
ldx _tgi_textscalew+1
jsr GetProcessedCoord ; Get X vector
; X2 = BaseX + XMag * XDelta.
; Depending on the text direction, the X vector is either applied to X as
;
; X2 = _tgi_curx + XMag * XDelta
;
; or applied to Y as
;
; Y2 = _tgi_cury - XMag * XDelta
;
; which can be transformed to
;
; Y2 = _tgi_cury + (~(XMag * XDelta) + 1);
;
;
; For the Y component we have
;
; Y2 = _tgi_cury - YMag * YDelta
;
; which can be transformed to
;
; Y2 = _tgi_cury + (~(YMag * YDelta) + 1);
;
; or applied to X as
;
; X2 = _tgi_curx - YMag * YDelta
;
; which can be transformed to
;
; X2 = _tgi_curx + (~(YMag * YDelta) + 1);
;
clc
adc BaseX+0
sta X2+0
txa
adc BaseX+1
sta X2+1
ldy _tgi_textdir ; Horizontal or vertical text?
bne @Vertical ; Jump if vertical
; Process the Y value
; Process horizontal text
lda _tgi_textscaleh+0
ldx _tgi_textscaleh+1
jsr GetProcessedCoord
ldy #0
jsr AddBaseCoord
sta X2
stx X2+1
; Y2 = BaseY - YMag * YDelta;
; Y2 = BaseY + (~(YMag * YDelta) + 1);
; Get Y vector
eor #$FF
sec ; + 1
adc BaseY+0
sta Y2+0
txa
eor #$FF
adc BaseY+1
sta Y2+1
jsr GetProcessedYCoord
; Apply to Y
ldy #2
jsr SubBaseCoord
sta Y2
stx Y2+1
jmp @DrawMove
; Process vertical text
@Vertical:
ldy #2
jsr SubBaseCoord
sta Y2
stx Y2+1
; Get Y vector
jsr GetProcessedYCoord
; Apply to X
ldy #0
jsr SubBaseCoord
sta X2
stx X2+1
; Draw, then move - or just move
@DrawMove:
bit Flag
bpl @Move ; Jump if move only
.if 0
ldy #7 ; Copy start coords into zp
: lda X1,y
sta ptr1,y
@ -260,6 +258,15 @@ Loop: lda _tgi_textscalew+0
bpl :-
jsr tgi_line ; Call the driver
.else
ldy #7 ; Copy start coords
: lda X1,y
sta tgi_clip_x1,y
dey
bpl :-
jsr tgi_clippedline ; Call line clipper
.endif
; Move the start position
@ -276,7 +283,7 @@ Loop: lda _tgi_textscalew+0
; Done. Restore zp and return.
Done: pla
pla
sta Flag
pla
sta Ops+1