]> git.sur5r.net Git - cc65/blob - libsrc/tgi/tgi_vectorchar.s
Working on stroked font output.
[cc65] / libsrc / tgi / tgi_vectorchar.s
1 ;
2 ; Ullrich von Bassewitz, 2009-11-02
3 ;
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.
7 ;  */
8 ;
9
10         .import         _toascii, imul16x16r32, umul16x16r32, negax, negeax
11
12         .include        "tgi-kernel.inc"
13         .include        "tgi-vectorfont.inc"
14         .include        "zeropage.inc"
15
16         .macpack        longbranch
17
18 ;----------------------------------------------------------------------------
19 ; Data
20
21 Ops     = regbank
22 Flag    = regbank+2
23
24 .bss
25 X1:     .res    2
26 Y1:     .res    2
27 X2:     .res    2
28 Y2:     .res    2
29 BaseX:  .res    2
30 BaseY:  .res    2
31 Char:   .res    1
32
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.
36
37 .code
38 .proc   GetOp
39
40 ; Load delta value
41
42         ldy     #0
43         lda     (Ops),y
44         inc     Ops
45         bne     :+
46         inc     Ops+1
47
48 ; Move bit 7 into Flag, then sign extend the value in A
49
50 :       asl     a                       ; Flag into carry
51         ror     Flag
52         cmp     #$80                    ; Sign bit into carry
53         ror     a                       ; Sign extend the value
54
55 ; Done
56
57         rts
58
59 .endproc
60
61
62 ;----------------------------------------------------------------------------
63 ; Round a 16.8 fixed point value in eax
64
65 .code
66 .proc   RoundFix
67
68         cmp     #$80                    ; frac(val) >= 0.5?
69         txa
70         ldx     sreg
71         adc     #$00
72         bcc     @L1
73         inx
74 @L1:    rts
75
76 .endproc
77
78 ;----------------------------------------------------------------------------
79 ; Get and process one coordinate value. The scale factor is passed in a/x
80
81 .code
82 .proc   GetProcessedCoord
83
84 ; Save scale factor as left operand for multiplication
85
86         sta     ptr1
87         stx     ptr1+1
88
89 ; Load next operation value. This will set the flags for the value in A.
90
91         jsr     GetOp
92
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
97 ; both operands.
98
99         sta     tmp1                    ; Remember sign of vector offset
100         bpl     :+
101         eor     #$FF
102         clc
103         adc     #$01                    ; Negate
104 :       ldx     #$00                    ; High byte is always zero
105
106 ; Multiplicate with the scale factor.
107
108         jsr     umul16x16r32            ; Multiplicate
109
110 ; The result is a 16.8 fixed point value. Round it.
111
112         jsr     RoundFix
113
114 ; Check the sign and negate if necessary
115
116         bit     tmp1                    ; Check sign
117         bpl     :+
118         jmp     negax                   ; Negate result if necessary
119 :       rts
120
121 .endproc
122
123 ;----------------------------------------------------------------------------
124 ;
125
126 .code
127 .proc   _tgi_vectorchar
128
129 ; Convert the character to ASCII, multiplicate by two and save into Y
130
131         jsr     _toascii
132         asl     a
133         tay
134
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.
137
138         lda     Ops
139         pha
140         lda     Ops+1
141         pha
142         lda     Flag
143         pha
144
145 ; Get the width of the char in question
146
147         lda     _tgi_vectorfont
148         clc
149         adc     #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
150         sta     Ops
151         lda     _tgi_vectorfont+1
152         adc     #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR)
153         sta     Ops+1
154         lda     (Ops),y
155
156 ; Save the character
157
158         sty     Char
159
160 ; Calculate the width of the character by multiplying with the scale
161 ; factor for the width
162
163         sta     ptr1
164         lda     #0
165         sta     ptr1+1
166
167         lda     _tgi_textscalew
168         ldx     _tgi_textscalew+1
169         jsr     umul16x16r32
170         jsr     RoundFix
171
172 ; Store the current value of the graphics cursor into BaseX/BaseY, then
173 ; move it to the next character position
174
175         pha
176         ldy     #3
177 :       lda     _tgi_curx,y
178         sta     BaseX,y
179         dey
180         bpl     :-
181         pla
182
183         ldy     _tgi_textdir
184         beq     :+                      ; Jump if horizontal text
185
186         jsr     negax
187         ldy     #2                      ; Offset of tgi_cury
188
189 ; Advance graphics cursor
190
191 :       clc
192         adc     _tgi_curx,y
193         sta     _tgi_curx,y
194         txa
195         adc     _tgi_curx+1,y
196         sta     _tgi_curx+1,y
197
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.
200
201         lda     _tgi_vectorfont
202         clc
203         adc     #<(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
204         sta     Ops
205         lda     _tgi_vectorfont+1
206         adc     #>(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
207         sta     Ops+1
208
209         ldy     Char
210         iny
211         lda     (Ops),y
212         tax
213         dey
214         lda     (Ops),y
215         sta     Ops
216         stx     Ops+1
217
218 ; Main loop executing vector operations
219
220 Loop:   lda     _tgi_textscalew+0
221         ldx     _tgi_textscalew+1
222         jsr     GetProcessedCoord       ; Get X vector
223
224 ; X2 = BaseX + XMag * XDelta.
225
226         clc
227         adc     BaseX+0
228         sta     X2+0
229         txa
230         adc     BaseX+1
231         sta     X2+1
232
233 ; Process the Y value
234
235         lda     _tgi_textscaleh+0
236         ldx     _tgi_textscaleh+1
237         jsr     GetProcessedCoord
238
239 ; Y2 = BaseY - YMag * YDelta;
240 ; Y2 = BaseY + (~(YMag * YDelta) + 1);
241
242         eor     #$FF
243         sec                             ; + 1
244         adc     BaseY+0
245         sta     Y2+0
246         txa
247         eor     #$FF
248         adc     BaseY+1
249         sta     Y2+1
250
251 ; Draw, then move - or just move
252
253         bit     Flag
254         bpl     @Move                   ; Jump if move only
255
256         ldy     #7                      ; Copy start coords into zp
257 :       lda     X1,y
258         sta     ptr1,y
259         dey
260         bpl     :-
261
262         jsr     tgi_line                ; Call the driver
263
264 ; Move the start position
265
266 @Move:  ldy     #3
267 :       lda     X2,y
268         sta     X1,y
269         dey
270         bpl     :-
271
272 ; Loop if not done
273
274         bit     Flag
275         bvc     Loop
276
277 ; Done. Restore zp and return.
278
279 Done:   pla
280         sta     Flag
281         pla
282         sta     Ops+1
283         pla
284         sta     Ops
285         rts
286
287 .endproc
288