]> git.sur5r.net Git - cc65/blob - libsrc/tgi/tgi_vectorchar.s
fixed optimization bug where array index is 16-bit, e.g. arr16[i & 0x7f7f]
[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         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
30 ;----------------------------------------------------------------------------
31 ; Get the next operation from the Ops pointer, remove the flag bit and sign
32 ; extend the 8 bit value to 16 bits.
33
34 .code
35 .proc   GetOp
36
37 ; Load delta value
38
39         ldy     #0
40         lda     (Ops),y
41         inc     Ops
42         bne     :+
43         inc     Ops+1
44
45 ; Move bit 7 into Flag, then sign extend the value in A and extend the sign
46 ; into X.
47
48 :       asl     a                       ; Flag into carry
49         ror     Flag
50         ldx     #0
51         cmp     #$80                    ; Sign bit into carry
52         ror     a                       ; Sign extend the value
53         bpl     :+
54         dex                             ; Value is negative
55
56 ; Done
57
58 :       rts
59
60 .endproc
61
62
63 ;----------------------------------------------------------------------------
64 ; Get and process one coordinate value. The scale factor is passed in a/x
65
66 .code
67 GetProcessedYCoord:
68         lda     _tgi_textscaleh+0
69         ldx     _tgi_textscaleh+1
70
71 GetProcessedCoord:
72
73 ; Save scale factor as left operand for multiplication
74
75         sta     ptr1
76         stx     ptr1+1
77
78 ; Load next operation value.
79
80         jsr     GetOp
81
82 ; Multiplicate with the scale factor.
83
84         jmp     tgi_imulround           ; Multiplicate, round and scale
85
86 ;----------------------------------------------------------------------------
87 ; Add the base coordinate with offset in Y to the value in A/X
88
89 .code
90 .proc   AddBaseCoord
91
92         clc
93         adc     _tgi_curx+0,y
94         pha
95         txa
96         adc     _tgi_curx+1,y
97         tax
98         pla
99         rts
100
101 .endproc
102
103 ;----------------------------------------------------------------------------
104 ; Subtract the value in a/x from the base coordinate with offset in Y
105 ; This is
106 ;
107 ;   ax = _tgi_cur[xy] - ax
108 ;
109 ; which can be transformed to
110 ;
111 ;   ax = _tgi_cur[xy] + (~ax + 1);
112
113
114 .code
115 .proc   SubBaseCoord
116
117         eor     #$FF
118         sec                             ; + 1
119         adc     _tgi_curx+0,y
120         pha
121         txa
122         eor     #$FF
123         adc     _tgi_curx+1,y
124         tax
125         pla
126         rts
127
128 .endproc
129
130 ;----------------------------------------------------------------------------
131 ;
132
133 .code
134 .proc   _tgi_vectorchar
135
136 ; Multiplicate the char value by two and save into Y
137
138         asl     a
139         tay
140
141 ; Since we will call tgi_lineto, which uses the zero page, and we do also
142 ; need the zero page, make room in the register bank.
143
144         lda     Ops
145         pha
146         lda     Ops+1
147         pha
148         lda     Flag
149         pha
150
151 ; Calculate a pointer to the vector ops for the given char (now in Y). We
152 ; definitely expect a font here, that has to be checked by the caller.
153
154         lda     _tgi_vectorfont
155         clc
156         adc     #<(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
157         sta     Ops
158         lda     _tgi_vectorfont+1
159         adc     #>(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR)
160         sta     Ops+1
161
162         iny
163         lda     (Ops),y
164         tax
165         dey
166         lda     (Ops),y
167         sta     Ops
168         stx     Ops+1
169
170 ; Main loop executing vector operations
171
172 Loop:   lda     _tgi_textscalew+0
173         ldx     _tgi_textscalew+1
174         jsr     GetProcessedCoord       ; Get X vector
175
176 ; Depending on the text direction, the X vector is either applied to X as
177 ;
178 ;   X2 = _tgi_curx + XMag * XDelta
179 ;
180 ; or applied to Y as
181 ;
182 ;   Y2 = _tgi_cury - XMag * XDelta
183 ;
184 ; which can be transformed to
185 ;
186 ;   Y2 = _tgi_cury + (~(XMag * XDelta) + 1);
187 ;
188 ;
189 ; For the Y component we have
190 ;
191 ;   Y2 = _tgi_cury - YMag * YDelta
192 ;
193 ; which can be transformed to
194 ;
195 ;   Y2 = _tgi_cury + (~(YMag * YDelta) + 1);
196 ;
197 ; or applied to X as
198 ;
199 ;   X2 = _tgi_curx - YMag * YDelta
200 ;
201 ; which can be transformed to
202 ;
203 ;   X2 = _tgi_curx + (~(YMag * YDelta) + 1);
204 ;
205
206         ldy     _tgi_textdir    ; Horizontal or vertical text?
207         bne     @Vertical       ; Jump if vertical
208
209 ; Process horizontal text
210
211         ldy     #0
212         jsr     AddBaseCoord
213         sta     X2
214         stx     X2+1
215
216 ; Get Y vector
217
218         jsr     GetProcessedYCoord
219
220 ; Apply to Y
221
222         ldy     #2
223         jsr     SubBaseCoord
224         sta     Y2
225         stx     Y2+1
226         jmp     @DrawMove
227
228 ; Process vertical text
229
230 @Vertical:
231         ldy     #2
232         jsr     SubBaseCoord
233         sta     Y2
234         stx     Y2+1
235
236 ; Get Y vector
237
238         jsr     GetProcessedYCoord
239
240 ; Apply to X
241
242         ldy     #0
243         jsr     SubBaseCoord
244         sta     X2
245         stx     X2+1
246
247 ; Draw, then move - or just move
248
249 @DrawMove:
250         bit     Flag
251         bpl     @Move                   ; Jump if move only
252
253 .if     0
254         ldy     #7                      ; Copy start coords into zp
255 :       lda     X1,y
256         sta     ptr1,y
257         dey
258         bpl     :-
259
260         jsr     tgi_line                ; Call the driver
261 .else
262         ldy     #7                      ; Copy start coords
263 :       lda     X1,y
264         sta     tgi_clip_x1,y
265         dey
266         bpl     :-
267
268         jsr     tgi_clippedline         ; Call line clipper
269 .endif
270
271 ; Move the start position
272
273 @Move:  ldy     #3
274 :       lda     X2,y
275         sta     X1,y
276         dey
277         bpl     :-
278
279 ; Loop if not done
280
281         bit     Flag
282         bvc     Loop
283
284 ; Done. Restore zp and return.
285
286         pla
287         sta     Flag
288         pla
289         sta     Ops+1
290         pla
291         sta     Ops
292         rts
293
294 .endproc
295