blob: 273cc6ba30b4e6261133fbbcc093df4a13ef98d7 [file] [log] [blame]
;; $Id$
;; -----------------------------------------------------------------------
;;
;; 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