summaryrefslogtreecommitdiff
path: root/console.asm
blob: 23463e413cc2e3e47521a7a01e8f070c7b5b8f7d (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
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