-
Notifications
You must be signed in to change notification settings - Fork 2
/
draw_text.asm
342 lines (319 loc) · 8 KB
/
draw_text.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
; generic text drawing routines
; draw a single font tile to a framebuffer
; inputs:
; r0: tile number
; r1: X coordinate
; r2: Y coordinate
; r3: foreground color
; r4: background color
; r5: pointer to font graphics
; r6: font width
; r7: font height
; r8: pointer to framebuffer
; r9: framebuffer width (pixels)
; outputs:
; none
draw_font_tile_generic:
push r0
push r1
push r2
push r5
push r6
push r7
push r8
push r9
;movz.8 r0, r0 ; ensure the tile number is a single byte
; calculate pointer to the tile data
push r6
mul r6, r7
mul r0, r6
mul r0, 4 ; 4 bytes per pixel
add r0, r5 ; r0: pointer to tile data
pop r6
; calculate pointer to the framebuffer
mul r9, 4 ; 4 bytes per pixel
mul r2, r9 ; y * width * 4
mul r1, 4 ; x * 4
add r1, r2 ; y * width * 4 + (x * 4)
add r1, r8 ; r1: pointer to framebuffer
; r8: font width in bytes
mov r8, r6
mul r8, 4
draw_font_tile_generic_y_loop:
mov r5, r6 ; x counter
draw_font_tile_generic_x_loop:
mov r2, [r0]
cmp r2, 0xFF000000
ifz jmp draw_font_tile_generic_x_loop_background
; drawing foreground pixel
cmp r3, 0x00000000 ; is the foreground color supposed to be transparent?
ifz jmp draw_font_tile_generic_x_loop_end
mov [r1], r3 ; draw foreground color
jmp draw_font_tile_generic_x_loop_end
draw_font_tile_generic_x_loop_background:
; drawing background pixel
cmp r4, 0x00000000 ; is the background color supposed to be transparent?
ifz jmp draw_font_tile_generic_x_loop_end
mov [r1], r4 ; draw background color
draw_font_tile_generic_x_loop_end:
add r0, 4 ; increment tile pointer
add r1, 4 ; increment framebuffer pointer
dec r5
ifnz jmp draw_font_tile_generic_x_loop ; loop if there are still more X pixels to draw
sub r1, r8 ; return to the beginning of this line
add r1, r9 ; increment to the next line by adding the framebuffer width in bytes
dec r7 ; decrement height counter
ifnz jmp draw_font_tile_generic_y_loop ; loop if there are still more Y pixels to draw
pop r9
pop r8
pop r7
pop r6
pop r5
pop r2
pop r1
pop r0
ret
; draw text to a framebuffer, using printf-style formatting
; inputs:
; r0: pointer to null-terminated string
; r1: X coordinate
; r2: Y coordinate
; r3: foreground color
; r4: background color
; r5: pointer to font graphics
; r6: font width
; r7: font height
; r8: pointer to framebuffer
; r9: framebuffer width
; r10-r15: optional format values
; outputs:
; r1: X coordinate of end of text
draw_format_str_generic:
push r0
push r1
push r2
push r5
push r6
push r7
push r8
push r9
push r16
push r17
mov r16, 0 ; current format specifier counter
draw_format_str_generic_loop:
cmp.8 [r0], 0
ifz jmp draw_format_str_generic_end
cmp.8 [r0], '%'
ifz jmp draw_format_str_generic_found_format_specifier
; if this is not a format specifier or the end of the string, print the character
push r0
movz.8 r0, [r0]
call draw_font_tile_generic
pop r0
add r1, r6 ; add the font width to the X coordinate
inc r0
jmp draw_format_str_generic_loop
draw_format_str_generic_found_format_specifier:
inc r0
; percent sign
cmp.8 [r0], '%'
ifz call draw_format_str_generic_percent_sign
; character
cmp.8 [r0], 'c'
ifz call draw_format_str_generic_character
; unsigned decimal
cmp.8 [r0], 'u'
ifz call draw_format_str_generic_unsigned_decimal
; hex
cmp.8 [r0], 'x'
ifz call draw_format_str_generic_hex
inc r0
jmp draw_format_str_generic_loop
draw_format_str_generic_percent_sign:
push r0
mov r0, '%'
call draw_font_tile_generic
add r1, r6
pop r0
inc r16
ret
draw_format_str_generic_character:
call draw_format_str_generic_get_parameter
push r0
mov r0, r17
call draw_font_tile_generic
add r1, r6
pop r0
inc r16
ret
draw_format_str_generic_unsigned_decimal:
call draw_format_str_generic_get_parameter
push r0
mov r0, r17
call draw_decimal_generic
pop r0
inc r16
ret
draw_format_str_generic_hex:
call draw_format_str_generic_get_parameter
push r0
mov r0, r17
call draw_hex_generic
pop r0
inc r16
ret
draw_format_str_generic_get_parameter:
; load the correct format parameter into r17
; this is messy, but i don't know of any other way to do this at the moment
cmp r16, 0
ifz jmp draw_format_str_generic_get_parameter_0
cmp r16, 1
ifz jmp draw_format_str_generic_get_parameter_1
cmp r16, 2
ifz jmp draw_format_str_generic_get_parameter_2
cmp r16, 3
ifz jmp draw_format_str_generic_get_parameter_3
cmp r16, 4
ifz jmp draw_format_str_generic_get_parameter_4
cmp r16, 5
ifz jmp draw_format_str_generic_get_parameter_5
mov r17, 0
ret
draw_format_str_generic_get_parameter_0:
mov r17, r10
ret
draw_format_str_generic_get_parameter_1:
mov r17, r11
ret
draw_format_str_generic_get_parameter_2:
mov r17, r12
ret
draw_format_str_generic_get_parameter_3:
mov r17, r13
ret
draw_format_str_generic_get_parameter_4:
mov r17, r14
ret
draw_format_str_generic_get_parameter_5:
mov r17, r15
ret
draw_format_str_generic_end:
pop r17
pop r16
pop r9
pop r8
pop r7
pop r6
pop r5
pop r2
pop r1
pop r0
ret
; draw text to a framebuffer
; inputs:
; r0: pointer to null-terminated string
; r1: X coordinate
; r2: Y coordinate
; r3: foreground color
; r4: background color
; r5: pointer to font graphics
; r6: font width
; r7: font height
; r8: pointer to framebuffer
; r9: framebuffer width
; outputs:
; r1: X coordinate of end of text
draw_str_generic:
push r0
push r10
mov r10, r0
draw_str_generic_loop:
movz.8 r0, [r10]
call draw_font_tile_generic
inc r10
add r1, r6
cmp.8 [r10], 0x00
ifnz jmp draw_str_generic_loop
pop r10
pop r0
ret
; draw a decimal value to a framebuffer
; inputs:
; r0: value
; r1: X coordinate
; r2: Y coordinate
; r3: foreground color
; r4: background color
; r5: pointer to font graphics
; r6: font width
; r7: font height
; r8: pointer to framebuffer
; r9: framebuffer width
; outputs:
; r1: X coordinate of end of text
draw_decimal_generic:
push r0
push r10 ; r10: original stack pointer
push r11 ; temp 1
push r12 ; temp 2
push r13 ; temp 3
mov r10, rsp
mov r12, r0
push.8 0x00 ; end the string with a terminator
draw_decimal_generic_find_loop:
push r12
div r12, 10 ; quotient goes into r12
pop r13
rem r13, 10 ; remainder goes into r13
mov r11, r13
add r11, '0'
push.8 r11
cmp r12, 0
ifnz jmp draw_decimal_generic_find_loop
draw_decimal_generic_print:
mov r0, rsp ; point to start of string in the stack
call draw_str_generic
mov rsp, r10
pop r13
pop r12
pop r11
pop r10
pop r0
ret
; draw a hex value to a framebuffer
; inputs:
; r0: value
; r1: X coordinate
; r2: Y coordinate
; r3: foreground color
; r4: background color
; r5: pointer to font graphics
; r6: font width
; r7: font height
; r8: pointer to framebuffer
; r9: framebuffer width
; outputs:
; r1: X coordinate of end of text
draw_hex_generic:
push r10
push r11
push r12
push r31
mov r10, r0
mov r31, 8
draw_hex_generic_loop:
rol r10, 4
movz.16 r11, r10
and r11, 0x0F
mov r12, draw_hex_generic_characters
add r12, r11
movz.8 r0, [r12]
call draw_font_tile_generic
add r1, r6
loop draw_hex_generic_loop
pop r31
pop r12
pop r11
pop r10
ret
draw_hex_generic_characters: data.str "0123456789ABCDEF"