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
|
%ifndef _CONSOLE_ASM
%define _CONSOLE_ASM
%include "constants.asm"
%include "stdio.asm"
%include "string.asm"
%include "keyboard.asm"
putc:
; Write single character at cursor position
push bp
mov bp, sp
pusha
cmp al, 20h
jl .non_graphical
mov ah, 0ah ; BIOS - write character
mov bh, [video_page] ; video page zero
mov cx, 01h ; repeat character N times
int 10h ; BIOS video service
.non_graphical:
push ax
call console_driver
add sp, 2
popa
mov sp, bp
pop bp
ret
console_scroll_up:
push bp
mov bp, sp
pusha
cmp dh, MAX_ROWS - 1
jne .no_action
mov dh, MAX_ROWS - 2
push dx
call setcursor
add sp, 2
; scroll window up:
mov ah, 06h ; scroll up function id.
mov al, 1 ; lines to scroll.
mov bh, 07h ; attribute for new lines.
mov cl, 0 ; upper col.
mov ch, 0 ; upper row.
mov dl, MAX_COLS ; lower col.
mov dh, MAX_ROWS ; lower row.
int 10h
.no_action:
popa
mov sp, bp
pop bp
ret
console_driver:
push bp
mov bp, sp
pusha
call console_cursor_getpos
mov dh, [cursor_row]
mov dl, [cursor_col]
mov ax, [bp + 4]
.do_fn:
.do_scancode:
cmp al, 00h ; when AL is 00h, check scan-code
jne .do_ascii
cmp ah, SC_ARROW_LEFT
je .handle_sc_arrow_left
cmp ah, SC_ARROW_RIGHT
je .handle_sc_arrow_right
.handle_sc_arrow_left:
dec dl
jmp .return
.handle_sc_arrow_right:
inc dl
jmp .return
.do_ascii:
; ASCII control block
cmp al, ASCII_SPC
jae .handle_SPC
cmp al, ASCII_TAB
je .handle_TAB
cmp al, ASCII_BS
je .handle_BS
cmp al, ASCII_CR
je .handle_CR
cmp al, ASCII_LF
je .handle_LF
; etc...
jmp .return
.handle_SPC:
inc dl
cmp dl, MAX_COLS
jge .handle_LF
jmp .return
.handle_TAB:
add dl, 4
jmp .return
.handle_BS:
dec dl
cmp dl, 0
jl .skip_bs
push dx
call setcursor
add sp, 2
.skip_bs:
mov ah, 0ah
mov al, 20h
mov bh, byte [video_page]
mov cx, 1
int 10h
jmp .return_noupdate
.handle_CR:
mov dl, 0 ; set column zero
jmp .return
.handle_LF:
inc dh ; increment row
mov dl, 0 ; set column zero
jmp .return
.return:
push dx
call setcursor
add sp, 2
.return_noupdate:
call console_scroll_up
popa
mov sp, bp
pop bp
ret
cls:
push bp
mov bp, sp
pusha
mov ah, 07h ; BIOS - scroll down
mov al, 00h ; lines to scroll (0 == entire screen)
mov bh, 07h ; color white/black
mov cx, 0
mov dh, 24 ; rows
mov dl, 79 ; cols
int 10h ; BIOS video service
popa
mov sp, bp
pop bp
ret
console_cursor_getpos:
push bp
mov bp, sp
pusha
mov ah, 03h ; BIOS - query cursor position and size
mov bh, byte [video_page] ; video page zero
int 10h
mov [cursor_sl_start], byte ch ; record data
mov [cursor_sl_end], byte cl
mov [cursor_row], byte dh
mov [cursor_col], byte dl
popa
mov sp, bp
pop bp
ret
console_cursor_read:
push bp
mov bp, sp
push ax
push bx
mov ah, 08h ; BIOS - read character/attr at cursor
mov bh, byte[video_page] ; video page
int 10h
mov [cursor_attr], byte ah
mov [cursor_char], byte al
pop bx
pop ax
mov sp, bp
pop bp
ret
console_cursor_read_last:
push bp
mov bp, sp
push dx
call console_cursor_getpos
mov dh, [cursor_row]
mov dl, [cursor_col]
cmp dh, 0 ; is this column zero?
je .finalize
sub dl, 1 ; previous column
js .prev_row ; column went negative
jmp .finalize
.prev_row:
cmp dh, 0 ; is this row zero?
je .return
sub dh, 1 ; go up one row
add dl, 80 ; return to last column of row (-1 + 80 = 79)
.finalize:
push dx
call setcursor
call console_cursor_getpos
call console_cursor_read
; restore original cursor position
mov dh, [cursor_row]
mov dl, [cursor_col]
push dx
call setcursor
.return:
add sp, 4
pop dx
mov sp, bp
pop bp
ret
console_set_video_page:
push bp
mov bp, sp
pusha
mov [video_page], dl
mov ah, 05h
mov al, [video_page]
int 10h
popa
pop bp
ret
setcursor:
push bp
mov bp, sp
pusha
mov ah, 02h ; BIOS - set cursor position
mov bh, byte [video_page] ; video page
mov dx, [bp + 4] ; address of new cursor value
int 10h ; BIOS video service
popa
mov sp, bp
pop bp
ret
; data
video_page: db 0
cursor_sl_start: db 0
cursor_sl_end: db 0
cursor_row: db 0
cursor_col: db 0
cursor_row_vram: dw 0
cursor_col_vram: dw 0
cursor_vram: dw 0
cursor_attr: db 0
cursor_char: db 0
%endif
|