;; $Id: graphics.inc,v 1.4 2004/12/17 06:42:01 hpa Exp $ ;; ----------------------------------------------------------------------- ;; ;; Copyright 1994-2002 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. ;; ;; ----------------------------------------------------------------------- ; ---------------------------------------------------------------------------- ; VGA splash screen code ; ---------------------------------------------------------------------------- ; ; vgadisplayfile: ; Display a graphical splash screen. ; ; Input: ; ; SI = cluster/socket pointer ; section .text vgadisplayfile: mov [VGACluster],si push es ; This is a cheap and easy way to make sure the screen is ; cleared in case we were in graphics mode already call vgaclearmode call vgasetmode jnz .error_nz .graphalready: mov ax,xfer_buf_seg ; Use as temporary storage mov es,ax mov fs,ax call vgagetchunk ; Get the first chunk ; The header WILL be in the first chunk. cmp dword [es:xbs_vgabuf],0x1413f33d ; Magic number .error_nz: jne .error mov ax,[es:xbs_vgabuf+4] mov [GraphXSize],ax mov dx,xbs_vgabuf+8 ; Color map offset mov ax,1012h ; Set RGB registers xor bx,bx ; First register number mov cx,16 ; 16 registers int 10h .movecursor: mov ax,[es:xbs_vgabuf+6] ; Number of pixel rows mov dx,[VGAFontSize] add ax,dx dec ax div dl xor dx,dx ; Set column to 0 cmp al,[VidRows] jb .rowsok mov al,[VidRows] dec al .rowsok: mov dh,al mov ah,2 xor bx,bx int 10h ; Set cursor below image mov cx,[es:xbs_vgabuf+6] ; Number of graphics rows mov si,xbs_vgabuf+8+3*16 ; Beginning of pixel data mov word [VGAPos],0 .drawpixelrow: push cx mov cx,[GraphXSize] mov di,xbs_vgatmpbuf ; Row buffer call rledecode ; Decode one row push si mov si,xbs_vgatmpbuf mov di,si add di,[GraphXSize] mov cx,640/4 xor eax,eax rep stosd ; Clear rest of row mov di,0A000h ; VGA segment mov es,di mov di,[VGAPos] mov bp,640 call packedpixel2vga add word [VGAPos],byte 80 ; Advance to next pixel row push fs pop es pop si pop cx loop .drawpixelrow .error: pop es ret ; ; rledecode: ; Decode a pixel row in RLE16 format. ; ; FS:SI -> input ; CX -> pixel count ; ES:DI -> output (packed pixel) ; rledecode: shl esi,1 ; Nybble pointer xor dl,dl ; Last pixel .loop: call .getnybble cmp al,dl je .run ; Start of run sequence stosb mov dl,al dec cx jnz .loop .done: shr esi,1 adc si,byte 0 ret .run: xor bx,bx call .getnybble and al,al jz .longrun mov bl,al .dorun: push cx mov cx,bx mov al,dl rep stosb pop cx sub cx,bx ja .loop jmp short .done .longrun: call .getnybble mov ah,al call .getnybble shl al,4 or al,ah mov bl,al add bx,16 jmp short .dorun .getnybble: shr esi,1 fs lodsb jc .high dec si and al,0Fh stc rcl esi,1 ret .high: shr al,4 cmp si,xbs_vgabuf+trackbufsize ; Chunk overrun jb .nonewchunk call vgagetchunk mov si,xbs_vgabuf ; Start at beginning of buffer .nonewchunk: shl esi,1 ret ; ; vgagetchunk: ; Get a new trackbufsize chunk of VGA image data ; ; On input, ES is assumed to point to the buffer segment. ; vgagetchunk: pushad mov si,[VGACluster] and si,si jz .eof ; EOF overrun, not much to do... mov cx,[BufSafe] ; One trackbuf worth of data mov bx,xbs_vgabuf call getfssec jnc .noteof xor si,si .noteof: mov [VGACluster],si .eof: popad ret ; ; packedpixel2vga: ; Convert packed-pixel to VGA bitplanes ; ; FS:SI -> packed pixel string ; BP -> pixel count (multiple of 8) ; ES:DI -> output ; packedpixel2vga: mov dx,3C4h ; VGA Sequencer Register select port mov al,2 ; Sequencer mask out dx,al ; Select the sequencer mask inc dx ; VGA Sequencer Register data port mov al,1 mov bl,al .planeloop: pusha out dx,al .loop1: mov cx,8 .loop2: xchg cx,bx fs lodsb shr al,cl rcl ch,1 ; VGA is bigendian. Sigh. xchg cx,bx loop .loop2 mov al,bh stosb sub bp,byte 8 ja .loop1 popa inc bl shl al,1 cmp bl,4 jbe .planeloop ret ; ; vgasetmode: ; Enable VGA graphics, if possible; return ZF=1 on success ; DS must be set to the base segment; ES is set to DS. ; vgasetmode: push ds pop es mov ax,1A00h ; Get video card and monitor xor bx,bx int 10h sub bl, 7 ; BL=07h and BL=08h OK cmp bl, 1 ja .error ; ZF=0 ; mov bx,TextColorReg ; mov dx,1009h ; Read color registers ; int 10h mov ax,0012h ; Set mode = 640x480 VGA 16 colors int 10h mov dx,linear_color mov ax,1002h ; Write color registers int 10h mov [UsingVGA], byte 1 call use_font ; Set graphics font/data mov byte [ScrollAttribute], 00h xor ax,ax ; Set ZF .error: ret ; ; vgaclearmode: ; Disable VGA graphics. It is not safe to assume any value ; for DS or ES. ; vgaclearmode: push ds push es pushad mov ax,cs mov ds,ax mov es,ax cmp [UsingVGA], byte 1 jne .done mov ax,0003h ; Return to normal video mode int 10h ; mov dx,TextColorReg ; Restore color registers ; mov ax,1002h ; int 10h mov [UsingVGA], byte 0 call use_font ; Restore text font/data mov byte [ScrollAttribute], 07h .done: popad pop es pop ds ret ; ; vgashowcursor/vgahidecursor: ; If VGA graphics is enabled, draw a cursor/clear a cursor ; vgashowcursor: pushad mov al,'_' jmp short vgacursorcommon vgahidecursor: pushad mov al,' ' vgacursorcommon: cmp [UsingVGA], byte 1 jne .done mov ah,09h mov bx,0007h mov cx,1 int 10h .done: popad ret section .data ; Map colors to consecutive DAC registers linear_color db 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0 UsingVGA db 0 section .bss alignb 2 GraphXSize resw 1 ; Width of splash screen file VGAPos resw 1 ; Pointer into VGA memory VGACluster resw 1 ; Cluster pointer for VGA image file VGAFilePtr resw 1 ; Pointer into VGAFileBuf TextColorReg resb 17 ; VGA color registers for text mode %if IS_SYSLINUX VGAFileBuf resb FILENAME_MAX+2 ; Unmangled VGA image name %else VGAFileBuf resb FILENAME_MAX ; Unmangled VGA image name %endif VGAFileBufEnd equ $ VGAFileMBuf resb FILENAME_MAX ; Mangled VGA image name