summaryrefslogtreecommitdiff
path: root/console.asm
blob: f992705a0131a77c3093d12a296696e7205bae3a (plain) (blame)
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
%ifndef _CONSOLE_ASM
%define _CONSOLE_ASM

%include "constants.asm"
%include "stdio.asm"
%include "string.asm"
%include "keyboard.asm"

MAX_ROWS equ 25
MAX_COLS equ 80

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 bx, 00h		; 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:
	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     bx, 0700h  ; 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:
	ret


console_driver:
	push bp
	mov bp, sp

	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, SPC
	jae .handle_SPC

	cmp al, TAB
	je .handle_TAB

	cmp al, BS
	je .handle_BS

	cmp al, CR
	je .handle_CR

	cmp al, LF
	je .handle_LF

	; etc...
	jmp .return


.handle_SPC:
	inc dl
	cmp dl, MAX_COLS
	jge .handle_CR
	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 bx, 00h
	mov cx, 1
	int 10h
	jmp .return_noupdate

.handle_CR:
	mov dl, 0		; set column zero
	; fall through

.handle_LF:
	inc dh			; increment row
	jmp .return


.return:
	push dx
	call setcursor
	add sp, 2


.return_noupdate:
	call console_scroll_up
	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 bx, 0700h		; color white/black
				; & video page zero
	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, 00h		; 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, 00h		; video page zero
	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


setcursor:
	push bp
	mov bp, sp
	pusha

	mov ah, 02h		; BIOS - set cursor position
	mov bh, 0		; video page zero
	mov dx, [bp + 4]	; address of new cursor value
	int 10h			; BIOS video service

	popa
	mov sp, bp
	pop bp
	ret


; data
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