blob: 432d0e2ba8752e9c3bba1ed9bdac87f5eb8aacc4 [file] [log] [blame]
;; -----------------------------------------------------------------------
;;
;; 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 - module-dependent
;; cwritestr, crlf - writestr.inc
;; writehex* - writehex.inc
;;
;
; loadkeys: Load a LILO-style keymap; SI and DX:AX set by searchdir
;
section .text
loadkeys:
and dx,dx ; Should be 256 bytes exactly
jne loadkeys_ret
cmp ax,256
jne loadkeys_ret
mov bx,trackbuf
mov cx,1 ; 1 cluster should be >= 256 bytes
call getfssec
mov si,trackbuf
mov di,KbdMap
mov cx,256 >> 2
rep movsd
loadkeys_ret: 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
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:
RESET_IDLE
.again:
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
xchg dx,bx ; Data port
in al,dx
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: 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 .bss1
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
TextAttribute resb 1 ; Text attribute for message file
DisplayMask resb 1 ; Display modes mask