1 |
|
2 |
; |
3 |
; Font description |
4 |
; |
5 |
rsreset |
6 |
font_address rs.l 1 ; Location of the bitmap data containing the pixels of the font |
7 |
font_charset rs.l 1 ; Points to a table the the list of all characters used in the font |
8 |
font_mapping rs.l 1 ; Points to a table with the adress of individual characters in the bitmap |
9 |
font_width rs.l 1 ; Points to a table with the width in pixels of each characters |
10 |
font_height rs.w 1 ; Height in pixel of one character |
11 |
font_stride rs.w 1 ; Width in bytes of a scanline |
12 |
font_v_stride rs.w 1 ; How much to skip to go to the next line of characters |
13 |
font_h_stride rs.w 1 ; How many bytes to skip to the next character in the same row |
14 |
font_spacing rs.w 1 ; How many pixels should be added between each character |
15 |
font_space_size rs.w 1 ; Size in pixels of the default space |
16 |
|
17 |
SECTION TEXT |
18 |
|
19 |
even |
20 |
|
21 |
; |
22 |
; This routine compute the adress of each character in a picture, |
23 |
; and stores it in an array provided by the caller. |
24 |
; |
25 |
; a6=pointer on the font description bloc |
26 |
ComputeCharactersAdressMapFromBitmap |
27 |
movem.l d0/d1/d2/a0/a1/a2/a3,-(sp) |
28 |
|
29 |
; a0=list of characters to map |
30 |
; a1=destination buffer |
31 |
; a2=adress of the font to map |
32 |
; d0=bytes to skip to go to the next character on the same row |
33 |
; d1=stride between two rows of characters |
34 |
move.l font_address(a6),a2 |
35 |
move.w font_h_stride(a6),d0 |
36 |
move.w font_v_stride(a6),d1 |
37 |
move.l font_mapping(a6),a1 |
38 |
move.l font_charset(a6),a0 |
39 |
|
40 |
; Clear the existing mappings |
41 |
move.l a1,a3 |
42 |
move.w #256-1,d2 |
43 |
.loop_erase |
44 |
clr.l (a3)+ |
45 |
dbra d2,.loop_erase |
46 |
|
47 |
; Compute the new mappings |
48 |
move.l a2,a3 |
49 |
.loop |
50 |
moveq.l #0,d2 |
51 |
move.b (a0)+,d2 |
52 |
beq.s .end |
53 |
cmp.b #13,d2 |
54 |
beq.s .newline |
55 |
add d2,d2 |
56 |
add d2,d2 |
57 |
move.l a3,(a1,d2.w) |
58 |
add.w d0,a3 |
59 |
bra.s .loop |
60 |
|
61 |
.newline |
62 |
add d1,a2 |
63 |
move.l a2,a3 |
64 |
bra.s .loop |
65 |
|
66 |
.end |
67 |
movem.l (sp)+,d0/d1/d2/a0/a1/a2/a3 |
68 |
|
69 |
; And get the table with the character width |
70 |
; Todo: This could be computed at the same time the mapping is done instead of two passes |
71 |
move.w font_spacing(a6),d4 |
72 |
move.w font_stride(a6),d3 |
73 |
move.w font_height(a6),d0 |
74 |
move.l font_width(a6),a1 |
75 |
move.l font_mapping(a6),a0 |
76 |
|
77 |
; a0=table of character adresses |
78 |
; a1=table where the computed width are stored |
79 |
; d0=height of a character |
80 |
.ComputeCharacterWidth |
81 |
movem.l d0-a6,-(sp) |
82 |
|
83 |
move d0,d6 |
84 |
subq #1,d6 |
85 |
|
86 |
move #256-1,d7 |
87 |
.loop_compute_width |
88 |
move font_space_size(a6),d0 ; Default width = space |
89 |
move.l (a0)+,d1 ; Get the adress |
90 |
beq.s .no_character |
91 |
|
92 |
; Compute the bitmask vertically to find the printout of the character |
93 |
move.l d1,a2 |
94 |
moveq #0,d1 |
95 |
move d6,d5 |
96 |
.vertical_loop |
97 |
or.l 0(a2),d1 |
98 |
or.l 4(a2),d1 |
99 |
add d3,a2 |
100 |
dbra d5,.vertical_loop |
101 |
|
102 |
move d1,d2 |
103 |
swap d1 |
104 |
or d2,d1 |
105 |
beq.s .done |
106 |
|
107 |
; Use the mask to find where the least significant bit is, |
108 |
; for each zero found, we reduce the size of the character by one |
109 |
moveq #16,d0 |
110 |
.search_widtch |
111 |
lsr #1,d1 |
112 |
bcs.s .done |
113 |
subq #1,d0 |
114 |
bra.s .search_widtch |
115 |
.done |
116 |
add d4,d0 ; Additional inter-character spacing |
117 |
|
118 |
.no_character |
119 |
move.w d0,(a1)+ ; Store the width |
120 |
dbra d7,.loop_compute_width |
121 |
|
122 |
movem.l (sp)+,d0-a6 |
123 |
rts |
124 |
|
125 |
|
126 |
|
127 |
; a0=message |
128 |
; a1=screen location |
129 |
; a6=pointer on the font description bloc |
130 |
CharacterDrawText |
131 |
.loop_draw |
132 |
moveq.l #0,d0 |
133 |
move.b (a0)+,d0 ; Get the current character |
134 |
beq.s .end |
135 |
cmp.b #13,d0 |
136 |
beq.s .newline |
137 |
cmp.b #'_',d0 |
138 |
beq.s .variable_space |
139 |
bsr CharacterDraw |
140 |
bra.s .loop_draw |
141 |
|
142 |
.variable_space |
143 |
moveq #0,d0 |
144 |
move.b (a0)+,d0 |
145 |
add d0,d0 ; x2 |
146 |
add d0,character_xpos |
147 |
bra.s .loop_draw |
148 |
|
149 |
.newline |
150 |
move #0,character_xpos |
151 |
add #21,character_ypos |
152 |
bra.s .loop_draw |
153 |
|
154 |
.end |
155 |
rts |
156 |
|
157 |
|
158 |
|
159 |
; d0=character index |
160 |
; a6=pointer on the font description bloc |
161 |
CharacterDraw |
162 |
movem.l d0-a6,-(sp) |
163 |
; a2=mapping table |
164 |
; a3=width mapping |
165 |
move.l font_mapping(a6),a2 |
166 |
move.l font_width(a6),a3 |
167 |
|
168 |
and #255,d0 |
169 |
add d0,d0 |
170 |
move.w (a3,d0.w),d5 ; Character width |
171 |
add d0,d0 |
172 |
move.l (a2,d0.w),a0 ; Sprite adress |
173 |
cmp.l #0,a0 |
174 |
beq.s .end |
175 |
|
176 |
move character_xpos,d0 |
177 |
move character_ypos,d1 |
178 |
bsr ComputeScreenOffset |
179 |
move.l character_buffer_base,a1 ; Destination |
180 |
add.l d2,a1 ; +actual offset |
181 |
|
182 |
move.l #0,a2 ; No mask |
183 |
move.w #1,d0 ; Width (Letters are 16 pixels wide=1 word) |
184 |
move.w font_height(a6),d1 ; Height (7 or 21 pixels high) |
185 |
move font_stride(a6),d2 ; Source offset |
186 |
move blit_stride,d3 ; Destination offset |
187 |
move character_xpos,d4 ; Pixel offset |
188 |
and #15,d4 |
189 |
|
190 |
tst.b character_wait_vbl |
191 |
beq.s .no_vbl_test |
192 |
bsr WaitVbl |
193 |
.no_vbl_test |
194 |
bsr BlitterDrawSprite |
195 |
|
196 |
.end |
197 |
add d5,character_xpos |
198 |
movem.l (sp)+,d0-a6 |
199 |
rts |
200 |
|
201 |
; |
202 |
; the _ characters are followed by the number of pixels to skip. |
203 |
; We search the ones with a null number, and we use that to compute |
204 |
; the "padding" value to get the full line lenght |
205 |
; |
206 |
; a0=pointer on text |
207 |
; a1=mapping table for width |
208 |
; d0=max size of a line |
209 |
ComputeCharacterJustification |
210 |
movem.l d0-a6,-(sp) |
211 |
|
212 |
move.l sp,a6 |
213 |
|
214 |
move.l d0,d7 ; Max size for a line |
215 |
.restart_line |
216 |
move.l a0,a2 |
217 |
move.l a0,a3 |
218 |
.next_line |
219 |
moveq #0,d6 ; Computed width for this line |
220 |
moveq #0,d5 ; Number of wide characters found so far |
221 |
.loop_line |
222 |
cmp.l d6,d7 |
223 |
blt.s .line_too_long |
224 |
moveq #0,d0 |
225 |
move.b (a2)+,d0 ; Get the character |
226 |
beq.s .endoftext ; End of text ? |
227 |
cmp.b #13,d0 ; End of line ? |
228 |
beq.s .newline |
229 |
cmp.b #' ',d0 ; Space ? |
230 |
beq.s .fixe_space |
231 |
cmp.b #'_',d0 ; Variable space ? |
232 |
beq.s .variable_space |
233 |
|
234 |
; Normal character |
235 |
.compute_width |
236 |
add d0,d0 |
237 |
add.w (a1,d0.w),d6 ; Add to this line's width |
238 |
|
239 |
bra.s .loop_line |
240 |
|
241 |
.done |
242 |
move.l a6,sp |
243 |
movem.l (sp)+,d0-a6 |
244 |
rts |
245 |
|
246 |
.line_too_long |
247 |
move.b #13,(a3) ; Replace the space by a carriage return |
248 |
bra.s .restart_line |
249 |
|
250 |
.fixe_space |
251 |
move.l a2,a3 ; Store the current space adress to be able to patch it later on |
252 |
subq #1,a3 |
253 |
bra.s .compute_width |
254 |
|
255 |
.variable_space |
256 |
move.b (a2)+,d0 ; Get the width |
257 |
cmp.b #'_',d0 ; Variable space ? |
258 |
beq.s .free_slot |
259 |
add.w d0,d0 ; x2 |
260 |
add.w d0,d6 ; Add to this line's width |
261 |
bra.s .loop_line |
262 |
|
263 |
.free_slot |
264 |
addq #1,d5 ; One more free slot for this line |
265 |
add.w 32*2(a1),d6 ; Add the default size of the space to this line |
266 |
move.l a2,-(sp) ; Store the pointer |
267 |
bra.s .loop_line |
268 |
|
269 |
; If d0=0 means end of text |
270 |
.endoftext |
271 |
.newline |
272 |
tst d5 |
273 |
beq.s .no_variable_space |
274 |
|
275 |
move.l d7,d4 |
276 |
sub.l d6,d4 ; Number of missing pixels |
277 |
lsr d4 |
278 |
move.l d4,d3 |
279 |
divu d5,d3 ; Number of missing pixels to add to each entry |
280 |
.loop_patch_spaces |
281 |
subq #1,d5 |
282 |
beq.s .last_patch |
283 |
move.l (sp)+,a4 |
284 |
move.b d3,-1(a4) |
285 |
sub d3,d4 |
286 |
bra.s .loop_patch_spaces |
287 |
.last_patch |
288 |
move.l (sp)+,a4 |
289 |
move.b d4,-1(a4) |
290 |
|
291 |
.no_variable_space |
292 |
tst.b d0 |
293 |
beq.s .done |
294 |
move.l a2,a0 ; Point on the next line |
295 |
move.l a2,a3 |
296 |
subq #1,a3 |
297 |
bra .next_line |
298 |
|
299 |
|
300 |
SECTION DATA |
301 |
|
302 |
AtasciiCharacterList |
303 |
dc.b " !",34,"#$%&'()*+,-./",13 |
304 |
dc.b "0123456789:;<=>?",13 |
305 |
dc.b "@ABCDEFGHIJKLMNO",13 |
306 |
dc.b "PQRSTUVWXYZ[\]^_",13 |
307 |
dc.b "`abcdefghijklmno",13 |
308 |
dc.b "pqrstuvwxyz{|}~",13 |
309 |
dc.b 128,129,130,131 ; arrow up, down, right, left |
310 |
dc.b 132,133,134,135 ; close, expand, maximize, check |
311 |
dc.b 136,137,138 ; time, bell, note |
312 |
dc.b 139,140 ; FF, CR |
313 |
dc.b 141 ; Fuji |
314 |
dc.b 142,143 ; Smoker |
315 |
dc.b 0 |
316 |
|
317 |
CommonCharacterList |
318 |
dc.b "ABCDEFGHIJKLM",13 |
319 |
dc.b "NOPQRSTUVWXYZ",13 |
320 |
dc.b "abcdefghijklm",13 |
321 |
dc.b "nopqrstuvwxyz",13 |
322 |
dc.b "ÅÆØåæøéèëêçà:",13 |
323 |
dc.b ".,;?!©&@ ()-/",13 |
324 |
dc.b "0123456789'",34,13 ; 34=double quote |
325 |
dc.b 0 |
326 |
|
327 |
even |
328 |
|
329 |
|
330 |
SECTION BSS |
331 |
|
332 |
even |
333 |
|
334 |
character_buffer_base ds.l 1 |
335 |
character_xpos ds.w 1 |
336 |
character_ypos ds.w 1 |
337 |
character_wait_vbl ds.b 1 |
338 |
|
339 |
even |
340 |
|
341 |
|
342 |
|
343 |
|