forked from aviatorRHK/rpiForth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathterminal.s
executable file
·395 lines (340 loc) · 7.74 KB
/
terminal.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
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
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/******************************************************************************
* terminal.s
* by Alex Chadwick
*
* A sample assembly code implementation of the input02 operating system.
* See main.s for details.
*
* terminal.s contains code to do with the text terminal which the os uses
******************************************************************************/
.section .data
.align 4
/* NEW
* terminalStart is the address in the terminalBuffer of the first valid
* character.
* C++ Signature: u32 terminalStart;
*/
terminalStart:
.int terminalBuffer
/* NEW
* terminalStop is the address in the terminalBuffer of the last valid
* character.
* C++ Signature: u32 terminalStop;
*/
terminalStop:
.int terminalBuffer
/* NEW
* terminalView is the address in the terminalBuffer of the first displayed
* character.
* C++ Signature: u32 terminalView;
*/
terminalView:
.int terminalBuffer
/* NEW
* terminalInput is the address in the terminalBuffer of the first character of
* the text being input.
* C++ Signature: u32 terminalView;
*/
terminalColour:
.byte 0xf
/* NEW
* terminalBuffer is where all text is stored for the console.
* C++ Signature: u16 terminalBuffer[128*128];
*/
.align 8
terminalBuffer:
.rept 128*128
.byte 0x7f
.byte 0x0
.endr
/* NEW
* terminalScreen stores the text last rendered to the screnn by the console.
* This means when redrawing the screen, only changes need be drawn.
* C++ Signature: u16 terminalScreen[1024/8 * 768/16];
*/
terminalScreen:
.rept ((1024/8) * (768/16))
.byte 0x7f
.byte 0x0
.endr
.section .text
/* NEW
* Sets the fore colour to the specified terminal colour. The low 4 bits of r0
* contains the terminal colour code.
* C++ Signature: void TerminalColour(u8 colour);
*/
.globl TerminalColour
TerminalColour:
teq r0,#6
ldreq r0,=0x02B5
beq SetForeColour
tst r0,#0b1000
ldrne r1,=0x52AA
moveq r1,#0
tst r0,#0b0100
addne r1,#0x15
tst r0,#0b0010
addne r1,#0x540
tst r0,#0b0001
addne r1,#0xA800
mov r0,r1
b SetForeColour
/* NEW
* Copies the currently displayed part of TerminalBuffer to the screen.
* C++ Signature: void TerminalDisplay();
*/
.globl TerminalDisplay
TerminalDisplay:
push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
x .req r4
y .req r5
char .req r6
col .req r7
screen .req r8
taddr .req r9
view .req r10
stop .req r11
ldr taddr,=terminalStart
ldr view,[taddr,#terminalView - terminalStart]
ldr stop,[taddr,#terminalStop - terminalStart]
add taddr,#terminalBuffer - terminalStart
add taddr,#128*128*2
mov screen,taddr
mov y,#0
yLoop$:
mov x,#0
xLoop$:
teq view,stop
ldrneh char,[view]
moveq char,#0x7f
ldrh col,[screen]
teq col,char
beq xLoopContinue$
strh char,[screen]
lsr col,char,#8
and char,#0x7f
lsr r0,col,#4
bl TerminalColour
mov r0,#0x7f
mov r1,x
mov r2,y
bl DrawCharacter
and r0,col,#0xf
bl TerminalColour
mov r0,char
mov r1,x
mov r2,y
bl DrawCharacter
xLoopContinue$:
add screen,#2
teq view,stop
addne view,#2
teq view,taddr
subeq view,#128*128*2
add x,#8
ldr r12,=scrwidth
teq x,r12
bne xLoop$
add y,#16
ldr r12,=scrheight
teq y,r12
bne yLoop$
pop {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}
.unreq x
.unreq y
.unreq char
.unreq col
.unreq screen
.unreq taddr
.unreq view
.unreq stop
/* NEW
* Clears the terminal to blank.
* C++ Signature: void TerminalClear();
*/
.globl TerminalClear
TerminalClear:
ldr r0,=terminalStart
add r1,r0,#terminalBuffer-terminalStart
str r1,[r0]
str r1,[r0,#terminalStop-terminalStart]
str r1,[r0,#terminalView-terminalStart]
mov pc,lr
/* NEW
* Prints a string to the terminal at the current location. r0 contains a
* pointer to the ASCII encoded string, and r1 contains its length. New lines
* are obeyed.
* C++ Signature: void Print(char* string, u32 length);
*/
.globl Print
Print:
teq r1,#0
moveq pc,lr
push {r4,r5,r6,r7,r8,r9,r10,r11,lr}
bufferStart .req r4
taddr .req r5
x .req r6
string .req r7
length .req r8
char .req r9
bufferStop .req r10
view .req r11
mov string,r0
mov length,r1
ldr taddr,=terminalStart
ldr bufferStop,[taddr,#terminalStop-terminalStart]
ldr view,[taddr,#terminalView-terminalStart]
ldr bufferStart,[taddr]
add taddr,#terminalBuffer-terminalStart
add taddr,#128*128*2
and x,bufferStop,#0xfe
lsr x,#1
charLoop$:
ldrb char,[string]
and char,#0x7f
teq char,#'\b'
beq charBS$
teq char,#'\n'
bne charNormal$
mov r0,#0x7f
clearLine$:
strh r0,[bufferStop]
add bufferStop,#2
add x,#1
cmp x,#128
blt clearLine$
b charLoopContinue$
charBS$:
mov char,#0x020
strb char,[bufferStop]
ldr r0,=terminalColour
ldrb r0,[r0]
strb r0,[bufferStop]
add bufferStop,#-2
add x,#-1
b charLoopContinue$
charNormal$:
strb char,[bufferStop]
ldr r0,=terminalColour
ldrb r0,[r0]
strb r0,[bufferStop,#1]
add bufferStop,#2
add x,#1
charLoopContinue$:
cmp x,#128
blt noScroll$
/* scroll here */
mov x,#0
subs r0,bufferStop,view
addlt r0,#128*128*2
cmp r0,#128*(768/16)*2
addge view,#128*2
teq view,taddr
subeq view,taddr,#128*128*2
/* no scroll */
noScroll$:
teq bufferStop,taddr
subeq bufferStop,taddr,#128*128*2
teq bufferStop,bufferStart
addeq bufferStart,#128*2
teq bufferStart,taddr
subeq bufferStart,taddr,#128*128*2
subs length,#1
add string,#1
bgt charLoop$
charLoopBreak$:
sub taddr,#128*128*2
sub taddr,#terminalBuffer-terminalStart
str bufferStop,[taddr,#terminalStop-terminalStart]
str view,[taddr,#terminalView-terminalStart]
str bufferStart,[taddr]
pop {r4,r5,r6,r7,r8,r9,r10,r11,pc}
.unreq bufferStart
.unreq taddr
.unreq x
.unreq string
.unreq length
.unreq char
.unreq bufferStop
.unreq view
/* NEW
* Reads the next string a user types in up to r1 bytes and stores it in r0.
* Characters types after maxLength are ignored. Keeps reading until the user
* presses enter or return. Length of read string is returned in r0.
* C++ Signature: u32 Print(char* string, u32 maxLength);
*/
.globl ReadLine
ReadLine:
teq r1,#0
moveq r0,#0
moveq pc,lr
string .req r4
maxLength .req r5
input .req r6
taddr .req r7
length .req r8
view .req r9
push {r4,r5,r6,r7,r8,r9,lr}
mov string,r0
mov maxLength,r1
ldr taddr,=terminalStart
ldr input,[taddr,#terminalStop-terminalStart]
ldr view,[taddr,#terminalView-terminalStart]
mov length,#0
cmp maxLength,#128*64
movhi maxLength,#128*64
sub maxLength,#1
mov r0,#'_'
strb r0,[string,length]
readLoop$:
str input,[taddr,#terminalStop-terminalStart]
str view,[taddr,#terminalView-terminalStart]
mov r0,string
mov r1,length
add r1,#1
bl Print
bl TerminalDisplay
bl KeyboardUpdate
bl KeyboardGetChar
teq r0,#'\n'
beq readLoopBreak$
teq r0,#0
beq cursor$
teq r0,#'\b'
bne standard$
delete$:
cmp length,#0
subgt length,#1
b cursor$
standard$:
cmp length,maxLength
bge cursor$
strb r0,[string,length]
add length,#1
cursor$:
ldrb r0,[string,length]
teq r0,#'_'
moveq r0,#' '
movne r0,#'_'
strb r0,[string,length]
b readLoop$
readLoopBreak$:
mov r0,#'\n'
strb r0,[string,length]
str input,[taddr,#terminalStop-terminalStart]
str view,[taddr,#terminalView-terminalStart]
mov r0,string
mov r1,length
add r1,#1
bl Print
bl TerminalDisplay
mov r0,#0
strb r0,[string,length]
mov r0,length
pop {r4,r5,r6,r7,r8,r9,pc}
.unreq string
.unreq maxLength
.unreq input
.unreq taddr
.unreq length
.unreq view