2 ; Ullrich von Bassewitz, 2009-11-02
4 ; void __fastcall__ tgi_vectorchar (const unsigned char* Ops);
5 ; /* Draw one character of the vector font at the current graphics cursor
6 ; * position using the current font magnification.
10 .import _toascii, imul16x16r32, umul16x16r32, negax, negeax
12 .include "tgi-kernel.inc"
13 .include "tgi-vectorfont.inc"
14 .include "zeropage.inc"
18 ;----------------------------------------------------------------------------
33 ;----------------------------------------------------------------------------
34 ; Get the next operation from the Ops pointer, remove the flag bit and sign
35 ; extend the 8 bit value. On return, the flags are set for the value in A.
48 ; Move bit 7 into Flag, then sign extend the value in A
50 : asl a ; Flag into carry
52 cmp #$80 ; Sign bit into carry
53 ror a ; Sign extend the value
62 ;----------------------------------------------------------------------------
63 ; Round a 16.8 fixed point value in eax
68 cmp #$80 ; frac(val) >= 0.5?
78 ;----------------------------------------------------------------------------
79 ; Get and process one coordinate value. The scale factor is passed in a/x
82 .proc GetProcessedCoord
84 ; Save scale factor as left operand for multiplication
89 ; Load next operation value. This will set the flags for the value in A.
93 ; Since we know that the scale factor is always positive, we will remember
94 ; the sign of the coordinate offset, make it positive, do an unsigned mul
95 ; and negate the result if the vector was negative. This is faster than
96 ; relying on the signed multiplication, which will do the same, but for
99 sta tmp1 ; Remember sign of vector offset
104 : ldx #$00 ; High byte is always zero
106 ; Multiplicate with the scale factor.
108 jsr umul16x16r32 ; Multiplicate
110 ; The result is a 16.8 fixed point value. Round it.
114 ; Check the sign and negate if necessary
116 bit tmp1 ; Check sign
118 jmp negax ; Negate result if necessary
123 ;----------------------------------------------------------------------------
127 .proc _tgi_vectorchar
129 ; Convert the character to ASCII, multiplicate by two and save into Y
135 ; Since we will call tgi_lineto, which uses the zero page, and we do also
136 ; need the zero page, make room in the register bank.
145 ; Get the width of the char in question
149 adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
151 lda _tgi_vectorfont+1
152 adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
160 ; Calculate the width of the character by multiplying with the scale
161 ; factor for the width
168 ldx _tgi_textscalew+1
172 ; Store the current value of the graphics cursor into BaseX/BaseY, then
173 ; move it to the next character position
184 beq :+ ; Jump if horizontal text
187 ldy #2 ; Offset of tgi_cury
189 ; Advance graphics cursor
198 ; Calculate a pointer to the vector ops for the given char (now in Y). We
199 ; definitely expect a font here, that has to be checked by the caller.
203 adc #<(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
205 lda _tgi_vectorfont+1
206 adc #>(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
218 ; Main loop executing vector operations
220 Loop: lda _tgi_textscalew+0
221 ldx _tgi_textscalew+1
222 jsr GetProcessedCoord ; Get X vector
224 ; X2 = BaseX + XMag * XDelta.
233 ; Process the Y value
235 lda _tgi_textscaleh+0
236 ldx _tgi_textscaleh+1
237 jsr GetProcessedCoord
239 ; Y2 = BaseY - YMag * YDelta;
240 ; Y2 = BaseY + (~(YMag * YDelta) + 1);
251 ; Draw, then move - or just move
254 bpl @Move ; Jump if move only
256 ldy #7 ; Copy start coords into zp
262 jsr tgi_line ; Call the driver
264 ; Move the start position
277 ; Done. Restore zp and return.