;; ----------------------------------------------------------------------- ;; ;; Copyright 1994-2005 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. Is called with SI and DX:AX ; set by routine searchdir ; get_msg_file: push es shl edx,16 ; EDX <- DX:AX (length of file) mov dx,ax mov ax,xfer_buf_seg ; Use for temporary storage mov es,ax mov byte [TextAttribute],07h ; Default grey on white mov byte [DisplayMask],07h ; Display text in all modes call msg_initvars get_msg_chunk: push edx ; EDX = length of file xor bx,bx ; == xbs_textbuf mov cx,[BufSafe] call getfssec pop edx push si ; Save current cluster xor si,si ; == xbs_textbuf mov cx,[BufSafeBytes] ; Number of bytes left in chunk print_msg_file: push cx push edx es lodsb cmp al,1Ah ; DOS EOF? je msg_done_pop push si mov cl,[UsingVGA] inc cl ; 01h = text mode, 02h = graphics call [NextCharJump] ; Do what shall be done pop si pop edx pop cx dec edx jz msg_done loop print_msg_file pop si jmp short get_msg_chunk msg_done_pop: add sp,byte 6 ; Drop pushed EDX, CX msg_done: pop si pop es ret msg_putchar: ; Normal character cmp al,0Fh ; ^O = color code follows je msg_ctrl_o cmp al,0Dh ; Ignore je msg_ignore cmp al,0Ah ; = newline je msg_newline cmp al,0Ch ; = clear screen je msg_formfeed cmp al,07h ; = beep je msg_beep cmp al,19h ; = return to text mode je msg_novga cmp al,18h ; = 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 ; = 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: push es push ds pop es ; ES <- DS mov si,[VGAFilePtr] mov byte [si],0 ; Zero-terminate filename mov si,VGAFileBuf mov di,VGAFileMBuf push di call mangle_name pop di call searchdir pop es 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 ; 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 TextAttribute resb 1 ; Text attribute for message file DisplayMask resb 1 ; Display modes mask