-
Notifications
You must be signed in to change notification settings - Fork 21
/
drawing.s
executable file
·310 lines (258 loc) · 5.34 KB
/
drawing.s
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
/******************************************************************************
* drawing.s
* by Alex Chadwick
*
* A sample assembly code implementation of the input02 operating system.
* See main.s for details.
*
* drawing.s contains code to do with drawing shapes to the screen.
******************************************************************************/
/*
* The foreColour is the colour which all our methods will draw shapes in.
* C++ Signature: short foreColour;
*/
.section .data
.align 1
foreColour:
.hword 0xFFFF
/*
* graphicsAddress stores the address of the frame buffer info structure.
* C++ Signature: FrameBuferDescription* graphicsAddress;
*/
.align 2
.global graphicsAddress
graphicsAddress:
.int 0
/*
* Font stores the bitmap images for the first 128 characters.
*/
.align 4
font:
.incbin "font.bin"
/*
* SetForeColour changes the current drawing colour to the 16 bit colour in r0.
* C++ Signature: void SetForeColour(u16 colour);
*/
.section .text
.globl SetForeColour
SetForeColour:
cmp r0,#0x10000
movhi pc,lr
moveq pc,lr
ldr r1,=foreColour
strh r0,[r1]
mov pc,lr
/*
* SetGraphicsAddress changes the current frame buffer information to
* graphicsAddress;
* C++ Signature: void SetGraphicsAddress(FrameBuferDescription* value);
*/
.globl SetGraphicsAddress
SetGraphicsAddress:
ldr r1,=graphicsAddress
str r0,[r1]
mov pc,lr
/*
* DrawPixel draws a single pixel to the screen at the point in (r0,r1).
* C++ Signature: void DrawPixel(u32x2 point);
*/
.globl DrawPixel
DrawPixel:
px .req r0
py .req r1
addr .req r2
ldr addr,=graphicsAddress
ldr addr,[addr]
height .req r3
ldr height,[addr,#4]
sub height,#1
cmp py,height
movhi pc,lr
.unreq height
width .req r3
ldr width,[addr,#0]
sub width,#1
cmp px,width
movhi pc,lr
ldr addr,[addr,#32]
add width,#1
mla px,py,width,px
.unreq width
.unreq py
add addr, px,lsl #1
.unreq px
fore .req r3
ldr fore,=foreColour
ldrh fore,[fore]
strh fore,[addr]
.unreq fore
.unreq addr
mov pc,lr
showit:
mov pc,lr
/*
* DrawLine draws a line between two points given in (r0,r1) and (r2,r3).
* Uses Bresenham's Line Algortihm
* C++ Signature: void DrawLine(u32x2 p1, u32x2 p2);
*/
.globl DrawLine
DrawLine:
push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
x0 .req r9
x1 .req r10
y0 .req r11
y1 .req r12
mov x0,r0
mov x1,r2
mov y0,r1
mov y1,r3
dx .req r4
dyn .req r5 /* Note that we only ever use -deltay, so I store its negative for speed. (hence dyn) */
sx .req r6
sy .req r7
err .req r8
cmp x0,x1
subgt dx,x0,x1
movgt sx,#-1
suble dx,x1,x0
movle sx,#1
cmp y0,y1
subgt dyn,y1,y0
movgt sy,#-1
suble dyn,y0,y1
movle sy,#1
add err,dx,dyn
add x1,sx
add y1,sy
pixelLoop$:
teq x0,x1
teqne y0,y1
popeq {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
mov r0,x0
mov r1,y0
bl DrawPixel
cmp dyn, err,lsl #1
addle err,dyn
addle x0,sx
cmp dx, err,lsl #1
addge err,dx
addge y0,sy
b pixelLoop$
.unreq x0
.unreq x1
.unreq y0
.unreq y1
.unreq dx
.unreq dyn
.unreq sx
.unreq sy
.unreq err
/*
* DrawCharacter renders the image for a single character given in r0 to the
* screen, with to left corner given by (r1,r2), and returns the width of the
* printed character in r0, and the height in r1.
* C++ Signature: u32x2 DrawCharacter(char character, u32 x, u32 y);
*/
.globl DrawCharacter
DrawCharacter:
x .req r4
y .req r5
charAddr .req r6
cmp r0,#0x7F
movhi r0,#0
movhi r1,#0
movhi pc,lr
push {r4,r5,r6,r7,r8,lr}
mov x,r1
mov y,r2
ldr charAddr,=font
add charAddr, r0,lsl #4
lineLoop$:
bits .req r7
bit .req r8
ldrb bits,[charAddr]
mov bit,#8
charPixelLoop$:
subs bit,#1
blt charPixelLoopEnd$
lsl bits,#1
tst bits,#0x100
beq charPixelLoop$
add r0,x,bit
mov r1,y
bl DrawPixel
b charPixelLoop$
charPixelLoopEnd$:
.unreq bit
.unreq bits
add y,#1
add charAddr,#1
tst charAddr,#0b1111
bne lineLoop$
.unreq x
.unreq y
.unreq charAddr
width .req r0
height .req r1
mov width,#8
mov height,#16
pop {r4,r5,r6,r7,r8,pc}
.unreq width
.unreq height
/*
* DrawString renders the image for a string of characters given in r0 (length
* in r1) to the screen, with to left corner given by (r2,r3). Obeys new line
* and horizontal tab characters.
* C++ Signature: void DrawString(char* string, u32 length, u32 x, u32 y);
*/
.globl DrawString
DrawString:
x .req r4
y .req r5
x0 .req r6
string .req r7
length .req r8
char .req r9
push {r4,r5,r6,r7,r8,r9,lr}
mov string,r0
mov x,r2
mov x0,x
mov y,r3
mov length,r1
stringLoop$:
subs length,#1
blt stringLoopEnd$
ldrb char,[string]
add string,#1
mov r0,char
mov r1,x
mov r2,y
bl DrawCharacter
cwidth .req r0
cheight .req r1
teq char,#'\n'
moveq x,x0
addeq y,cheight
beq stringLoop$
teq char,#'\t'
addne x,cwidth
bne stringLoop$
add cwidth, cwidth,lsl #2
x1 .req r1
mov x1,x0
stringLoopTab$:
add x1,cwidth
cmp x,x1
bge stringLoopTab$
mov x,x1
.unreq x1
b stringLoop$
stringLoopEnd$:
.unreq cwidth
.unreq cheight
pop {r4,r5,r6,r7,r8,r9,pc}
.unreq x
.unreq y
.unreq x0
.unreq string
.unreq length