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
396
397
398
399
400
|
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
;; Boston MA 02111-1307, USA; either version 2 of the License, or
;; (at your option) any later version; incorporated herein by reference.
;;
;; -----------------------------------------------------------------------
;;
;; conio.inc
;;
;; Console I/O code, except:
;; writechr, writestr_early - module-dependent
;; writestr, crlf - writestr.inc
;; writehex* - writehex.inc
;;
;
; loadkeys: Load a LILO-style keymap; file is open on the top of the
; getc stack.
;
section .text
loadkeys:
mov cx,256
mov di,trackbuf
call readc
jc .done ; EOF already?
; Make sure we are at EOF now...
call getc
jnc .done ; We should be at EOF now!
; It was okay, we can now move it into the KbdMap
mov si,trackbuf
mov di,KbdMap
mov cx,256 >> 2
rep movsd
.done:
call close
ret
;
; get_msg_file: Load a text file and write its contents to the screen,
; interpreting color codes. Call with the file already
; on the top of the open/getc stack.
;
; Assumes CS == DS == ES.
;
get_msg_file:
mov byte [TextAttribute],07h ; Default grey on white
mov byte [DisplayMask],07h ; Display text in all modes
call msg_initvars
print_msg_file:
.getc:
call getc
jc .done
cmp al,1Ah ; DOS EOF?
je .done
movzx cx,byte [UsingVGA]
and cl,01h
inc cx ; CL <- 01h = text mode,
; 02h = graphics mode
call [NextCharJump] ; Do what shall be done
jmp .getc
.done:
jmp close ; Tailcall!
msg_putchar: ; Normal character
cmp al,0Fh ; ^O = color code follows
je msg_ctrl_o
cmp al,0Dh ; Ignore <CR>
je msg_ignore
cmp al,0Ah ; <LF> = newline
je msg_newline
cmp al,0Ch ; <FF> = clear screen
je msg_formfeed
cmp al,07h ; <BEL> = beep
je msg_beep
cmp al,19h ; <EM> = return to text mode
je msg_novga
cmp al,18h ; <CAN> = VGA filename follows
je msg_vga
jnb .not_modectl
cmp al,10h ; 10h to 17h are mode controls
jae msg_modectl
.not_modectl:
msg_normal: call write_serial_displaymask ; Write to serial port
test [DisplayMask],cl
jz msg_ignore ; Not screen
test byte [DisplayCon],01h
jz msg_ignore
mov bl,[TextAttribute]
mov bh,[BIOS_page]
mov ah,09h ; Write character/attribute
mov cx,1 ; One character only
int 10h ; Write to screen
mov al,[CursorCol]
inc ax
cmp al,[VidCols]
ja msg_line_wrap ; Screen wraparound
mov [CursorCol],al
msg_gotoxy: mov bh,[BIOS_page]
mov dx,[CursorDX]
mov ah,02h ; Set cursor position
int 10h
msg_ignore: ret
msg_beep: mov ax,0E07h ; Beep
xor bx,bx
int 10h
ret
msg_ctrl_o: ; ^O = color code follows
mov word [NextCharJump],msg_setbg
ret
msg_newline: ; Newline char or end of line
mov si,crlf_msg
call write_serial_str_displaymask
msg_line_wrap: ; Screen wraparound
test [DisplayMask],cl
jz msg_ignore
mov byte [CursorCol],0
mov al,[CursorRow]
inc ax
cmp al,[VidRows]
ja msg_scroll
mov [CursorRow],al
jmp short msg_gotoxy
msg_scroll: xor cx,cx ; Upper left hand corner
mov dx,[ScreenSize]
mov [CursorRow],dh ; New cursor at the bottom
mov bh,[ScrollAttribute]
mov ax,0601h ; Scroll up one line
int 10h
jmp short msg_gotoxy
msg_formfeed: ; Form feed character
mov si,crff_msg
call write_serial_str_displaymask
test [DisplayMask],cl
jz msg_ignore
xor cx,cx
mov [CursorDX],cx ; Upper lefthand corner
mov dx,[ScreenSize]
mov bh,[TextAttribute]
mov ax,0600h ; Clear screen region
int 10h
jmp msg_gotoxy
msg_setbg: ; Color background character
call unhexchar
jc msg_color_bad
shl al,4
test [DisplayMask],cl
jz .dontset
mov [TextAttribute],al
.dontset:
mov word [NextCharJump],msg_setfg
ret
msg_setfg: ; Color foreground character
call unhexchar
jc msg_color_bad
test [DisplayMask],cl
jz .dontset
or [TextAttribute],al ; setbg set foreground to 0
.dontset:
jmp short msg_putcharnext
msg_vga:
mov word [NextCharJump],msg_filename
mov di, VGAFileBuf
jmp short msg_setvgafileptr
msg_color_bad:
mov byte [TextAttribute],07h ; Default attribute
msg_putcharnext:
mov word [NextCharJump],msg_putchar
ret
msg_filename: ; Getting VGA filename
cmp al,0Ah ; <LF> = end of filename
je msg_viewimage
cmp al,' '
jbe msg_ret ; Ignore space/control char
mov di,[VGAFilePtr]
cmp di,VGAFileBufEnd
jnb msg_ret
mov [di],al ; Can't use stosb (DS:)
inc di
msg_setvgafileptr:
mov [VGAFilePtr],di
msg_ret: ret
msg_novga:
call vgaclearmode
jmp short msg_initvars
msg_viewimage:
mov si,[VGAFilePtr]
mov byte [si],0 ; Zero-terminate filename
mov si,VGAFileBuf
mov di,VGAFileMBuf
call mangle_name
call open
jz msg_putcharnext ; Not there
call vgadisplayfile
; Fall through
; Subroutine to initialize variables, also needed
; after loading a graphics file
msg_initvars:
pusha
mov bh,[BIOS_page]
mov ah,03h ; Read cursor position
int 10h
mov [CursorDX],dx
popa
jmp short msg_putcharnext ; Initialize state machine
msg_modectl:
and al,07h
mov [DisplayMask],al
jmp short msg_putcharnext
;
; write_serial: If serial output is enabled, write character on serial port
; write_serial_displaymask: d:o, but ignore if DisplayMask & 04h == 0
;
write_serial_displaymask:
test byte [DisplayMask], 04h
jz write_serial.end
write_serial:
pushfd
pushad
mov bx,[SerialPort]
and bx,bx
je .noserial
push ax
mov ah,[FlowInput]
.waitspace:
; Wait for space in transmit register
lea dx,[bx+5] ; DX -> LSR
in al,dx
test al,20h
jz .waitspace
; Wait for input flow control
inc dx ; DX -> MSR
in al,dx
and al,ah
cmp al,ah
jne .waitspace
.no_flow:
xchg dx,bx ; DX -> THR
pop ax
call slow_out ; Send data
.noserial: popad
popfd
.end: ret
;
; write_serial_str: write_serial for strings
; write_serial_str_displaymask: d:o, but ignore if DisplayMask & 04h == 0
;
write_serial_str_displaymask:
test byte [DisplayMask], 04h
jz write_serial_str.end
write_serial_str:
.loop lodsb
and al,al
jz .end
call write_serial
jmp short .loop
.end: ret
;
; pollchar: check if we have an input character pending (ZF = 0)
;
pollchar:
pushad
call do_idle
mov ah,11h ; Poll keyboard
int 16h
jnz .done ; Keyboard response
mov dx,[SerialPort]
and dx,dx
jz .done ; No serial port -> no input
add dx,byte 5 ; DX -> LSR
in al,dx
test al,1 ; ZF = 0 if data pending
jz .done
inc dx ; DX -> MSR
mov ah,[FlowIgnore] ; Required status bits
in al,dx
and al,ah
cmp al,ah
setne al
dec al ; Set ZF = 0 if equal
.done: popad
ret
;
; getchar: Read a character from keyboard or serial port
;
getchar:
.again:
call do_idle
mov ah,11h ; Poll keyboard
int 16h
jnz .kbd ; Keyboard input?
mov bx,[SerialPort]
and bx,bx
jz .again
lea dx,[bx+5] ; DX -> LSR
in al,dx
test al,1
jz .again
inc dx ; DX -> MSR
mov ah,[FlowIgnore]
in al,dx
and al,ah
cmp al,ah
jne .again
.serial: xor ah,ah ; Avoid confusion
mov dx,bx ; Data port
in al,dx
lea dx,[bx+2] ; DX -> IIR
in al,dx ; Read IIR to discard any IRQ bits
ret
.kbd: mov ah,10h ; Get keyboard input
int 16h
cmp al,0E0h
jnz .not_ext
xor al,al
.not_ext:
and al,al
jz .func_key
mov bx,KbdMap ; Convert character sets
xlatb
.func_key:
call reset_idle ; Character received
ret
%ifdef DEBUG_TRACERS
;
; debug hack to print a character with minimal code impact
;
debug_tracer: pushad
pushfd
mov bp,sp
mov bx,[bp+9*4] ; Get return address
mov al,[cs:bx] ; Get data byte
inc word [bp+9*4] ; Return to after data byte
call writechr
popfd
popad
ret
%endif ; DEBUG_TRACERS
section .data
%if IS_ISOLINUX == 0 ; Defined elsewhere for ISOLINUX
crlf_msg db CR, LF
null_msg db 0
%endif
crff_msg db CR, FF, 0
section .config
; This is a word to pc_setint16 can set it
DisplayCon dw 01h ; Console display enabled
ScrollAttribute db 07h ; Grey on white (normal text color)
section .bss
alignb 2
NextCharJump resw 1 ; Routine to interpret next print char
CursorDX equ $
CursorCol resb 1 ; Cursor column for message file
CursorRow resb 1 ; Cursor row for message file
ScreenSize equ $
VidCols resb 1 ; Columns on screen-1
VidRows resb 1 ; Rows on screen-1
; Serial console stuff...
BaudDivisor resw 1 ; Baud rate divisor
FlowControl equ $
FlowOutput resb 1 ; Outputs to assert for serial flow
FlowInput resb 1 ; Input bits for serial flow
FlowIgnore resb 1 ; Ignore input unless these bits set
FlowDummy resb 1 ; Unused
TextAttribute resb 1 ; Text attribute for message file
DisplayMask resb 1 ; Display modes mask
|