From 62ca92287e71450514018da90a00da6392ec25b2 Mon Sep 17 00:00:00 2001 From: hpa Date: Fri, 26 Apr 2002 06:31:46 +0000 Subject: [PATCH] Move VGA graphics code to a shared include file --- graphics.inc | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ isolinux.asm | 312 ++------------------------------------------------------- ldlinux.asm | 311 ++------------------------------------------------------- pxelinux.asm | 311 ++------------------------------------------------------- 4 files changed, 336 insertions(+), 916 deletions(-) create mode 100644 graphics.inc diff --git a/graphics.inc b/graphics.inc new file mode 100644 index 0000000..0dd850e --- /dev/null +++ b/graphics.inc @@ -0,0 +1,318 @@ +;; $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, +;; Bostom 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 +; +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 near .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 + + + ; 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 + diff --git a/isolinux.asm b/isolinux.asm index c19d28b..34240a4 100644 --- a/isolinux.asm +++ b/isolinux.asm @@ -3999,315 +3999,15 @@ getfssec: TRACER 'f' ret +; ----------------------------------------------------------------------------- +; Common modules +; ----------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; VGA splash screen code -; ---------------------------------------------------------------------------------- +%include "graphics.inc" ; VGA graphics -; -; vgadisplayfile: -; Display a graphical splash screen. -; -; Input: -; -; SI = cluster/socket pointer -; -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 near .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 - - - ; 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 - -; ---------------------------------------------------------------------------------- +; ----------------------------------------------------------------------------- ; Begin data section -; ---------------------------------------------------------------------------------- +; ----------------------------------------------------------------------------- CR equ 13 ; Carriage Return LF equ 10 ; Line Feed diff --git a/ldlinux.asm b/ldlinux.asm index 74e1d75..3333937 100644 --- a/ldlinux.asm +++ b/ldlinux.asm @@ -3834,314 +3834,15 @@ lc_1: cmp al,lcase_low pop bx lc_ret: ret -; ---------------------------------------------------------------------------------- -; VGA splash screen code -; ---------------------------------------------------------------------------------- - -; -; vgadisplayfile: -; Display a graphical splash screen. -; -; Input: -; -; SI = cluster/socket pointer -; -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 near .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 - +; ----------------------------------------------------------------------------- +; Common modules +; ----------------------------------------------------------------------------- - ; 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 +%include "graphics.inc" ; VGA graphics -; ---------------------------------------------------------------------------------- +; ----------------------------------------------------------------------------- ; Begin data section -; ---------------------------------------------------------------------------------- +; ----------------------------------------------------------------------------- CR equ 13 ; Carriage Return LF equ 10 ; Line Feed diff --git a/pxelinux.asm b/pxelinux.asm index c72c8ba..1b84644 100644 --- a/pxelinux.asm +++ b/pxelinux.asm @@ -4406,314 +4406,15 @@ genipopt: popad ret -; ---------------------------------------------------------------------------------- -; VGA splash screen code -; ---------------------------------------------------------------------------------- +; ----------------------------------------------------------------------------- +; Common modules +; ----------------------------------------------------------------------------- -; -; vgadisplayfile: -; Display a graphical splash screen. -; -; Input: -; -; SI = cluster/socket pointer -; -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 near .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 - - - ; 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 +%include "graphics.inc" ; VGA graphics -; ---------------------------------------------------------------------------------- +; ----------------------------------------------------------------------------- ; Begin data section -; ---------------------------------------------------------------------------------- +; ----------------------------------------------------------------------------- CR equ 13 ; Carriage Return LF equ 10 ; Line Feed -- 2.7.4