Gran's Guide to SVGA Programming (640 x 480 x 256 colors) -------------------------------- (For more information on all SVGA modes, see: http://www.osha.igs.net/~dandelong/nw/index.htm) Due to the VESA standards, SVGA is pretty simple to do. The screen is setup as if it were multiple screens all plopped onto one. These smaller screens are called banks. A sad excuse for a graphic follows (fig. 1). The banks are each of size 65536 bytes and each can be addressed just as a normal VGA screen. The number of pixels each bank encompasses is based on the number of colors while the number of banks on the screen is based on the screenmode. Calculating the number of banks and where banks start and stop are simple math exercises (similar to the VGA ones in the homeworks). For example, in 640x480x256 mode there are five banks but the fifth one (bank 4) is not entirely used. Be careful not to draw off the screen as this is a bad thing. ________________________________ | | | Bank 0 | | __________________| |___________| | | Bank 1 | | ________| |_____________________| | | | | Bank 2 | |______________________________| | .. etc .. | Figure 1 : SVGA Banks ( Disclaimer: This drawing is an approximation. The beginning and ending of banks is not exact ) The only trick is knowing which bank you are in and in calling the proper interrupts to set a bank. This is not really as difficult as it seems. A sample program is given below (You need lib291.lib for the rsave and rrest functions, but the rest of the code is self supporting). This program draws a diagonal line across the screen. This uses 640x480x256 mode. Other resolution modes can be used with little change in the code. The code is a bit long, but it does assemble. ---------------------- SVGA Program ---------------------- ; SVGA program ; Demo for ECE 291 ; Bryan Gran ; 11/25/97 ; extrn rsave:near extrn rrest:near ;============= Define stack segment ================== stackseg SEGMENT STACK db 256 dup ('STACK123') ; 2 Kbytes of stack space stackseg ends ;============= Code segment begins ==================== cseg SEGMENT PUBLIC 'CODE' ASSUME cs:cseg, ds:cseg, ss:stackseg, es:nothing ;============= Define global variables ================ newbank dw 0 currbank dw -1 xdiff dw ? ydiff dw ? errorterm dw ? pcolor db 12 ;============= Procedures go here ===================== main proc near mov ax, cs mov ds, ax mov bx, 101h ; 640x480x256 call setvgamode call laserzap mov bx, 0 mov ax, 0 mov cx, 480 mov byte ptr pcolor, 12 ; color is bright red line45: call pxy ; draw a 45 degree angled line inc ax ; from 0,0 to 479,479 inc bx loop line45 mov cx, 0ffffh l1: push cx mov cx, 05ffh l2: loop l2 pop cx loop l1 mov al,03h mov ah,0h int 010h ; restores text mode mov ah, 04Ch int 021h main endp ; Procedure setvgamode ; Sets the VGA mode. ; Inputs: ; BX = vgamode (101h for 640x480x256) ; Outputs: none setvgamode proc near push ax push bx mov ax,4F02h ; set mode function int 010h ; video bios call pop bx pop ax ret setvgamode endp ; Procedure setvbe ; This sets the bank of the SVGA memory to currently write. ; Inputs: ; newbank = bank to move to ; currbank = current bank ; Outputs: ; AX = error code, 004F if not error setvbe proc near call rsave mov ax, cs mov ds, ax mov ax, newbank cmp currbank,ax ; check if a change of bank is necessary je setvbexit mov ax,4F05h mov bx,0 ; SET READ window mov dx, newbank int 010h mov ax,4F05h mov bx,1 ; SET WRITE window mov dx, newbank int 010h setvbexit: call rrest ret setvbe endp ; Procedure laserzap ; Simple routine implementing problem 3 from exam 2 in SVGA mode. ; Inputs: ; None ; Outputs: ; Bright line from bottom left to top right of screen. laserzap proc near mov ax, 0a000h mov es, ax ; set up es to screen mov al, 15 ; bright white mov newbank, 0 mov xdiff, 640 mov ydiff, 480 mov di, 639 ; start at top left mov dx, xdiff mov errorterm, dx shr errorterm, 1 mov dx, ydiff sub errorterm, dx ; errorterm = xdiff/2 - ydiff mov cx, xdiff drawring: mov dx, ydiff add errorterm, dx ; errorterm = errorterm + ydiff mov dx, xdiff cmp errorterm, dx ; if errorterm >= xdiff then turnover mu st be reset jl noturnover sub errorterm, dx ; errorterm = errorterm - xdiff add di, 640 ; go to next row jnc noturnover inc byte ptr newbank noturnover: call setvbe mov es:[di],al ; store byte on screen dec di ; go left one jnc goandloop dec byte ptr newbank goandloop: loop drawring ret laserzap endp ; Procedure pxy ; Plots a pixel given by bx, ax onto the svga screen. ; Inputs: ; BX - X coordinate ; AX - Y coordinate ; pcolor - color ; Outputs: ; Pixel drawn to the SVGA screen. pxy proc near call rsave mov dx, 0a000h mov es, dx ; set up for video write mov cx, 640 mul cx ; after mul dx is bank while ax is di mov newbank, dx mov di, ax add di, bx jnc nobreakbank ; did adding x break to the next bank inc newbank ; add one to the bank if so nobreakbank: call setvbe ; set up the bank mov al, byte ptr pcolor ; set up the color mov es:[di],al ; put it on the screen call rrest ret pxy endp cseg ENDS ; end code segment END main ; program starts with main