Chris presents a VGA chip-set detection method, including functions for addressing video memory and displaying pixels at specified locations.
July 01, 1990
URL:http://www.drdobbs.com/parallel/super-vga-programming/184408376
Chris is president of Genus Microprogramming, which provides a number of tools that support Super VGA (including the PCX Programmer's Toolkit, PCX Effects, and PCX Text). He can be reached at Genus Microprogramming, 11315 Meadow Lake, Houston, TX 77077, or on CompuServe: 75100,17.
Once upon a time users were presented a short and simple list of display adapter choices -- color or monochrome. Although, from a programmer's perspective those days are still enticing -- a myriad of standards has developed since then. The resolutions of the Hercules, CGA, EGA, and VGA adapters have all provided a common ground for users and developers alike. The next step (as defined by IBM) is the 8514/A, but it has been slow in its adoption. There is also Texas Instruments TIGA (pronounced TIE-GA), an interface for its 34010 and 34020 chips, but it, too, is in the first stages of support. Meanwhile, a number of video board manufacturers have released adapters with capabilities beyond the IBM VGA standard resolution of 320 x 200 x 256. These extended resolutions are collectively known as Super VGA.
In the simpler days of CGA and Hercules, the graphics screen was directly memory mapped. All a programmer had to do was point at it and write it. Aside from the minor headache of interleave addressing, graphics programming was relatively easy. To save the screen, just save that block of memory with a function such as BSAVE, and load it with BLOAD. Later came the EGA with its planar memory and hosts of registers, and things suddenly got more complicated and easier at the same time. Although functions such as BSAVE would no longer work, features like masking and logical operations became easier. The VGA followed this theme with higher resolutions and more colors, and finally we have Super VGA.
This article provides the ability to program the Super VGA modes for some of the major chipsets. A method of detecting each of the chipsets is presented, along with functions for addressing video memory and displaying a pixel at any location. Because any graphics function reduces down to plotting a pixel somewhere on the display, it is possible to extrapolate these functions to any other graphics operation, from the simple to the complex.
Currently, there are many chipsets on the market that provide Super VGA capabilities. In order to provide an adequate sample, I'll cover three of the major chipsets -- Tseng Labs, Paradise, and Video Seven. Although board vendors may use the same chipset, it is still up to the vendor which features are incorporated into a particular adapter (see Table 1). Super VGA offers the advantages of higher resolution and color capabilities, with the disadvantage of no existing standard. In fact, each chipset must be programmed separately even though you may wish to support only one mode, such as 640 x 480 x 256. Even something as basic as mode numbers can vary wildly between board manufacturers.
Chipset Adapter 800x 640x 640x 640x 800x 600x 350x 400x 480x 600x 16 256 256 256 256 ------------------------------------------------------------------ Tseng Labs Orchid ProDesigner VGA 29H Orchid ProDesigner Plus 29H 2DH 2EH 3DH Genoa 5300 29H Genoa 5400 29H 2DH 2EH 30H STB Extra/EM 29H 2DH 2EH 30H Tseng 29H 2DH 2EH 30H Paradise Paradise Plus-16 58H Paradise Professional 58H 5EH 5F Video Seven Video Seven Fastwrite 62H 66H Video Seven VRAM 62H 66H 67H 69H
Some manufacturers have made it easy to identify their chips. One of the easiest is Video Seven. Basically, they have provided an extended BIOS function call that returns valid information when the chipset is present, and garbage otherwise. This provides a consistent and reliable interface.
The other vendors, however, provide no method of identifying their chips. In these cases, a crude but effective BFAI (brute force and ignorance) approach can be used. All vendors include a copyright notice at the beginning of the video BIOS. You can search this area for strings -- such as "Tseng" or "PARADISE" -- in order to identify the chip. This method has worked rather well, but I would like to take this opportunity to suggest that these vendors provide a solution similar to Video Seven's.
This method is not a new one. Many software vendors used a similar technique in order to identify an IBM adapter, and they keyed in the letters "IBM" in the copyright string. This, of course, caused problems for clone vendors. How could they remain compatible with those software packages, and still use the letters IBM without copyright conflicts? Orchid Technology's solution is shown in Figure 1, but for fun you can use DEBUG to display your video board's BIOS by running DEBUG and using the command D C000:0, 100 to dump the first 256 bytes of your VGA's ROM BIOS.
C000:0000 55AA30EB 5B546869 73206973 206E6F74 This is not C000:0010 20612070 726F6475 6374206F 66204942 a product of IB C000:0020 4D202028 49424D20 69732061 20747261 M (IBM is a tra C000:0030 64656D61 726B206F 6620496E 7465726E demark of Intern C000:0040 6174696F 6E616C20 42757369 6E657373 ational Business C000:0050 204D6163 68696E65 7320436F 72702E29 Machines Corp. C000:0060 EB6F202A 20436F70 79726967 68742863 Copyright (c) C000:0070 29313938 38205473 656E6720 4C61626F 1988 Tseng Labo C000:0080 7261746F 72696573 2C20496E 632E2030 ratories, Inc. O C000:0090 382F3039 2F383820 56382E30 3058014F 8/09/88 V8.00X O C000:00A0 72636869 64205465 63686E6F 6C6F6779 rchid Technology C000:00B0 20496E63 2EAB4400 C0000000 00000000 Inc.
Initially, a function should be called that identifies the standard adapters (such as HGC, CGA, EGA, or VGA), but that would cover another article. An excellent reference is Richard Wilton's book, Programmer's Guide to PC and PS/2 Video Systems (Microsoft Press). Once a VGA adapter has been identified, the svQueryChipset function can be called to identify whether the VGA has a chipset that supports Super VGA resolutions. It tests for boards that have a BIOS function call first, and continues with ROM BIOS searches if that fails. In the event no match is found, it returns an error code. At that point your program must query the user, or assume that no supported Super VGA adapter exists.
Initializing the Super VGA graphics mode is no different from setting any standard graphics mode. Each adapter has extended the ROM BIOS interrupt 10H function so that the Super VGA modes are included. However, each board vendor has assigned its own mode numbers to those extended modes -- which is one reason why they are harder to support. Because there is no standard mode number, a table of modes must be maintained for all supported chipsets.
The example code uses a two-step process for managing display modes, based on the method Genus Microprogramming uses for our graphics products. First, the display type is set with the function svSetDisplay, which selects the chipset and the mode. A defined constant is used so that other display types and modes can be easily added, thereby hiding the internal workings of the library. Note that this function does not actually set the mode -- it only performs initialization internal to the Super VGA library and does not affect the calling program's environment. The mode change is performed in the svSetMode function, which takes as its arguments either the svTEXT or svGRAPHICS constants. Listing One , page 82, and Listing Two, page 84, contain the defines macros for Super VGA graphics manipulation. Both are implemented in Microsoft ASM, Version 5.x. The file in Listing Three, page 84, contains procedures for identifying various Super VGA adapters and uses the procedures svQueryChipset. Listing Four, page 85, contains the internal routine procedures for calculating a pixel's address for any given display mode using the procedures svPixelAddr2D, svPixelAddr30, and svPixelAddr5F. Listing Five, page 86, contains procedures for putting (displaying) a pixel for any given display mode or virtual buffer using the procedure svPutPixel. Listing Six, page 90, lists the function declarations for the Super VGA library for C, while Listing Seven, page 90, is a Microsoft C 5.1 test program for testing the Super VGA QueryChipset and PutPixel functions. (Compile with CL /c /AS svTest.C and link svTest ,,, svLib;). Listings Eight (page 91) and Nine (page 92) are the make files for making the Super VGA Library and the Super VGA test program. For more detail on Super VGA used, Table 2 lists the ports, indexes, and functions. Figure 3 illustrates the bits required for Bank selection.
Port Index Function Description ----------------------------------------------------------------------- EGAgraph (3CEH) EGA/VGA/SVGA graphics controller parPROA (09H) (bank) Paradise PROA reg used for bank sel parPR5 (0FH) parLOCK (0H) Paradise PR5 reg used for locking and unlocking parUNLOCK (5H) EGAseq (3C4H) EGA/VGA/SVGA Sequencer register v7pagesel (F9H) v7banksel (F6H) v7SR6 (06H) v7enable (EAH) Video7 SR6 reg used for locking and unlocking v7disable (AEH) VGAsegsel (3CDH) (bank) VGA Segment select (Tseng) VGAmisci (3CCH) VGA Miscellaneous In VGAmisco (3C2H) VGA Miscellaneous Out
There are several reasons for splitting up the initialization and mode change functions. First, it allows the library to coexist with other graphics libraries, each of which requires an initialization routine of its own -- and its routine needs to set the mode. In that case, a call to svSetDisplay and then its init would set the mode and make both libraries usable. Second, most initialization is required only once, not every time the mode is set. By calling svSetDisplay once, later calls to svSetMode can be made to switch back and forth between graphics and text modes. Lastly, the program is easier to maintain because the initialization function is performed once at the top of the program, not every time the mode is changed.
What you may notice is that the mode numbers in the table for the Video Seven chipset do not match the published mode constants. Technically, the correct modes are the 66H, 67H, and 69H numbers, and Video Seven recommends that the mode be set through a modified BIOS SetMode function. We found that every time the mode was set to 66H, a BIOS GetMode function call would always return 1AH. This caused problems because the svSetMode function always reads back the mode to ensure it was successfully set -- and it would always appear that it did not. To get around this problem and provide a standard way of setting and getting the mode, all of our libraries just go ahead and set the mode to 1AH (or 1BH or 1DH), and everything works fine. If you wish to set the mode for the Video Seven in the recommended way, use the @V7Mode macro provided.
There is one Super VGA mode that remains fairly constant across all boards, the 800 x 600 x 16 color mode. It is basically an extension of the 640 x 350 x 16 color EGA and 640 x 480 x 16 color VGA modes. It is programmed in exactly the same way, with the major changes being the mode number and pixel addressing. Because EGA programming has been well covered for several years now, we will not go into it here. To summarize, it is still planar, with each of the four planes fitting into one segment (64K bytes), for a total memory requirement of just under 256K bytes. To address a single pixel, use the formula b = ((y*800)+ x)/8, then mask out the pixel in that byte. The bit you want to affect is x mod 8. All logical operations and bit masking are performed as any normal EGA or VGA 16-color mode.
The Super VGA 256-color modes are an entirely new format. The memory layout is different from any previous video mode. It is not interleaved such as the CGA or Hercules adapters, nor is it planar such as the EGA and VGA 16-color modes. It is closest to the 320 x 200 x 256 VGA 13H mode, complicated by the fact that the memory crosses 64K-byte segment boundaries.
Like the EGA and VGA, the Super VGA video memory is accessed through a 64K-byte area located at A0000 hex. To get around the memory requirements of the Super VGA modes (a mode like 640 x 480 x 256 requires over 300K of video RAM), all chipsets use a sliding window scheme. For the Tseng and Video Seven chipsets, this window can be thought of as a 64K bank of memory that can be located at any 64K boundary. Do not think of it as a purely rectangular window -- the 64K window can start and stop anywhere within video memory (see Figure 2). This also means that the window starts and stops in the middle of a scanline, limiting some optimizations (such as checking for a bank change at the end of a scanline instead of any pixel). For the Tseng chipset, bank selection is all handled within a single byte. However, the Video Seven chipset gets the award for the most complicated bank switch. It involves setting three different bits in three different registers. The bank selection code for the example library is performed through macros, called @TsengSeg and @V7Seg.
The Paradise chipset is a little different in that it does not restrict the window to 64K boundaries. It is closer to an actual sliding window because it can be placed at any 4K increment. Unlike the Tseng and Video Seven, the window can be kept purely rectangular by placing it every 32 lines. This is because 32 lines * 640 bytes = 20480 = 5 * 4K increment. For some functions this is an advantage, but in the case of svPutPixel it does not help. The macro @ParSeg emulates the other chipsets by forcing the window to a 64K increment (every sixteenth 4K position).
Note that both the Video Seven and the Paradise chipsets require that the extended Super VGA registers be unlocked/enabled before they can be written to, and they recommend that these registers be locked/disabled when the function has completed using them. This is done with an out to a port, and they are supposedly locked in order to prevent accidental writes to those port locations. The only extended registers used in these examples involve bank selection.
Address calculations are simpler in the 256-color modes because each pixel is represented by 1 byte, and the memory is linear (all in a row, with no planes, and no interleaving). Compared to the CGA and Hercules interleaving and the planes of the EGA and VGA, Super VGA is the easiest.
The address calculations are performed by the functions in the svPA.ASM module (see Listing Four). Only two functions are necessary: One for 640-wide modes, and one for 800-wide Tseng and Video Seven modes. The routines merely involve multiplying the y coordinate by the screen width, and then adding in the x coordinate. Because each pixel is a byte, no conversion is necessary. The 64K bank number is automatically determined by the multiplication, because the AX register holds a maximum of 64K before it overflows into DX. Thus, the bank is returned to DX and the offset into that bank is returned in AX -- easy.
Now that the pixel can be addressed, it is only a matter of writing it. The svPutPixel function contained in the svPP.ASM module (see Listing Five) simply uses the information returned from the svPixelAddr function to set the window bank and update the pixel. The function appears a little more convoluted due to the logical operations supported. To set the logical operation, use the function svSetOp before calling the svPutPixel function.
These example functions were derived from Genus Microprogramming's current graphics tools that support multiple languages and compilers. Although the routines are fast, the derivation presented here is not necessarily optimized for speed. Optimizations may include streamlining the svPutPixel functions themselves so that the @Entry and @Exit macros are removed, or including separate pixel functions within other primitives such as line or circle functions. The examples are meant to illustrate the Super VGA programming process itself, and modular programming techniques. As my old physics professor used to eloquently understate, "The rest of the proof is trivial, and is left as an exercise for the student." In other words, why hand it to you when you can have fun trying?
The Super VGA modes are, in my opinion, easier to program than most other video modes for two main reasons:
The only constraining factor is the lack of standardization, which has slowed the adoption of the extended modes. With new standards such as VESA on the horizon, this situation should change soon.
_SUPER VGA PROGRAMMING_ by Christopher A. Howard
[LISTING ONE]
Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.
; svDefs.INC ;
; Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. ;
;**************************************************************************;
; This file contains defines for Super VGA graphics manipulation. ;
; Microsoft ASM 5.x version. Programmer: Chris Howard ;
;**************************************************************************;
;Display Segments
EGAseg equ 0A000H ;EGA/VGA/SVGA graphics segment
BIOSseg equ 0C000H ;Graphics BIOS segment
;EGA defines
EGAgraph equ 03CEH ;EGA Graphics Register
EGAseq equ 03C4H ;EGA Sequencer Register
;VGA defines
VGAsegsel equ 03CDH ;VGA Segment select
VGAmisci equ 03CCH ;VGA Misc In
VGAmisco equ 03C2H ;VGA Misc Out
;Paradise defines
parPROA equ 09H ;proa index value
parPR5 equ 0FH ;pr5 index value
parLOCK equ 0 ;Lock proa to pr4 (write to pr5)
parUNLOCK equ 5 ;Unlock proa to pr4 (write to pr5)
parFUNC equ 6FH ;Paradise Function
;Video 7 defines
v7SR6 equ 06H ;sr6 index value
v7banksel equ 0F6H ;Bank select
v7pagesel equ 0F9H ;Page select
v7enable equ 0EAH ;Enable extensions
v7disable equ 0AEH ;Disable extensions
v7modenum equ 06F05H ;Number to use for mode sets
;Display mode numbers
TEXTMODE equ 3 ;Text mode number
;Display mode types
svTEXT equ 0 ;Text mode
svGRAPH equ 1 ;Graphics mode
;Display types
mindisp equ 0 ;Minimum display type
svDISP_2D equ 0 ;Tseng 2DH (640x350x256)
svDISP_2E equ 1 ;Tseng 2EH (640x480x256)
svDISP_30 equ 2 ;Tseng 30H (800x600x256)
svDISP_5E equ 3 ;Paradise 5EH (640x400x256)
svDISP_5F equ 4 ;Paradise 5FH (640x480x256)
svDISP_66 equ 5 ;Video 7 66H (640x400x256)
svDISP_67 equ 6 ;Video 7 67H (640x480x256)
svDISP_69 equ 7 ;Video 7 69H (800x600x256)
maxdisp equ 7 ;Maximum display type
;Logical Operations
RMWbits equ 18H ;Read-Modify-Write bits
svOpREP equ 00000000B ;SET pixel value directly
svOpAND equ 00000001B ;AND pixel value with data
svOpOR equ 00000010B ;OR pixel value with data
svOpXOR equ 00000011B ;XOR pixel value with data
;Chipsets
svUNKNOWN equ 0 ;Unknown chip set
svTSENG equ 1 ;Tseng Labs chip set
svPARA equ 2 ;Paradise
svV7 equ 3 ;Video 7
;Masks
capmask equ 11011111B ;To convert letters to caps
;Error codes
svSUCCESS equ 0 ;Success
svBADMODE equ -1 ;Bad display mode
;Internal Constants
unknown equ -1 ;A constant is unknown
bytesrow equ 80 ;CGA bytes per full row
bitsbyte equ 8 ;Bits per byte
;Display structure
svstruc STRUC
svtype db ? ;Display type
svmode db ? ;Display mode
svfunc dd ? ;Display function
svstruc ENDS
[LISTING TWO]
; svMacs.INC ;
; Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. ;
;**************************************************************************;
; This file contains macros for Super VGA graphics manipulation. ;
; Microsoft ASM 5.x version. Programmer: Chris Howard ;
;**************************************************************************;
; Interrupts
INT_BIOS equ 10H ;BIOS (video)
INT_DOS equ 21H ;DOS Functions
; BIOS Functions (int 10H)
SETMODE equ 00H ;Set the Display mode
GETMODE equ 0FH ;Check the Display mode
; Macros
@DOS MACRO func ;;Macro to use DOS function calls
mov ah,func
int INT_DOS
ENDM
@BIOS MACRO func ;;Macro to use BIOS function calls
push bp ;;Some functions destroy bp
mov ah,func
int INT_BIOS
pop bp
ENDM
@@LoadSeg MACRO seg,val ;;Macro to load a segment reg
mov ax,val
mov seg,ax
ENDM
@@Data MACRO seg ;;Macro to load data seg in reg
ASSUME seg:@data
mov ax,@data
mov seg,ax
ENDM
@SetMode MACRO mode ;;Macro to set display mode
IFDIFI <mode>,<al>
mov al,mode
ENDIF
@BIOS SETMODE
ENDM
@GetMode MACRO ;;Macro to get display mode
@BIOS GETMODE
ENDM
@Port MACRO portnum,portval ;;Macro to set a port to a value
IFDIFI <portval>,<al>
mov al,portval
ENDIF
IFDIFI <portnum>,<dx>
mov dx,portnum
ENDIF
out dx,al
ENDM
@EGAPort MACRO portnum,portreg,portval ;;Macro to set an EGA port
IFDIFI <portreg>,<al>
mov al,portreg
ENDIF
IFDIFI <portnum>,<dx>
mov dx,portnum
ENDIF
out dx,al
inc dx
mov al,portval
out dx,al
ENDM
@TsengSeg MACRO seg ;;Macro to set the Tseng VGA seg
push ax
IFDIFI <seg>,<al>
mov al,seg
ENDIF
mov ah,al ;;Save a copy
shl ah,1 ;;Rotate up (Bits 0-2 = write seg
shl ah,1 ;; 3-5 = read seg
shl ah,1 ;; 6-7 = seg cnfg)
or al,ah ;;Combine read and write segs
or al,01000000B ;; and set to configuration 2
@Port VGAsegsel,al ;;Now set it
pop ax
ENDM
@ParSeg MACRO seg ;;Macro to set Paradise VGA seg
push cx
IFDIFI <seg>,<ch>
mov ch,seg
ENDIF
mov cl,4 ;Turn 4K window into 64K window
shl ch,cl ; by multiplying by 16
@EGAPort EGAgraph,parPROA,ch ; and set the new index
pop cx
ENDM
@V7Seg MACRO seg ;;Macro to set the V7VGA segment
push ax
push bx
IFDIFI <seg>,<bh>
mov bh,seg
ENDIF
mov bl,bh
and bl,00000001B ;;Mask for bank bit 0
@EGAPort EGAseq,V7pagesel,bl ;;Set the bit
mov bl,bh ;;Get a copy of seg again
and bl,000000010B ;;Mask for bank bit 1
shl bl,1 ;;Shift it up
shl bl,1
shl bl,1
shl bl,1
mov dx,VGAmisci ;;Read the Misc In reg
in al,dx
and al,NOT 00100000B ;;Make sure bit is clear
or bl,al
@Port VGAmisco,bl ;;Write to Misc Out
@Port EGAseq,v7banksel
inc dx
in al,dx
mov bl,bh ;;Get a copy of seg again
shr bl,1 ;;Dupe bit 2 to bit 0 (r/w equal)
shr bl,1
add bl,7
not bl
and bl,5
and al,11110000B ;;Clear bank select bits
or al,bl
out dx,al
pop bx
pop ax
ENDM
@V7Mode MACRO mode ;;Macro to set Video7 mode
IFDIFI <mode>,<bl>
mov bl,mode
ENDIF
mov ax,v7modenum ;;Indicate Video7 mode set
int INT_BIOS
ENDM
@Entry MACRO splocal ;;Macro for entering routine
push bp ;; and setting up frame
mov bp,sp
sub sp,splocal ;;Allocate local space
push ds
push es
push si
push di
@@Data ds
ENDM
@Exit MACRO retcode,splocal ;;Macro for setting return code
mov ax,retcode ;; and restoring regs
pop di
pop si
pop es
pop ds
mov sp,bp ;;Remove local space
pop bp ;;Restore frame
ret splocal ;;Remove parms
ENDM
@SetRet MACRO retcode,errcode
mov WORD PTR retcode,errcode
ENDM
[LISTING THREE]
; svQC.ASM ;
; Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. ;
;**************************************************************************;
; This file contains procedures for identifying various Super VGA adapters. ;
; Procedures: svQueryChipset ;
; Microsoft ASM 5.x version. Programmer: Chris Howard ;
;**************************************************************************;
; Include files
INCLUDE svDefs.inc
INCLUDE svMacs.inc
.model small
.data
.code
PUBLIC svQueryChipset
;**********
; This procedure attempts to determine the type of VGA chip set.
; Calling: retcode = pcxQueryChipset()
;
;Define variable locations on the stack (pascal model)
qcparm equ 0
;Define local variables
qcret equ <[bp- 2]> ;return code
qclocal equ 2 ;Total local space needed
svQueryChipset PROC FAR
@Entry qclocal ;Set up frame and save regs
mov al,0 ;Look for a V7VGA
@BIOS parFUNC
xor al,al ;Clear al
cmp bx,'V7' ;Is this a Video7?
jne svQC_Para
@SetRet qcret,svV7 ;Indicate that this is a Video7
jmp svQC_exit
svQC_Para:
@@LoadSeg es,BIOSseg ;Point to the BIOS location
mov di,0
mov cx,500 ;Search the first 500 bytes
mov al,'P' ;Look for 'PARADISE'
svQC_Parafind:
repne scasb ;Search
jcxz svQC_Tseng
cmp BYTE PTR es:[di ],'A' ;Next Letter?
jne svQC_Parafind ; Compare one at a time, so
; we can avoid static data ...)
cmp BYTE PTR es:[di+1],'R' ;
jne svQC_Parafind ; If not a match, continue search
cmp BYTE PTR es:[di+2],'A'
jne svQC_Parafind
cmp BYTE PTR es:[di+3],'D'
jne svQC_Parafind
cmp BYTE PTR es:[di+4],'I'
jne svQC_Parafind
cmp BYTE PTR es:[di+5],'S'
jne svQC_Parafind
cmp BYTE PTR es:[di+6],'E'
jne svQC_Parafind
@SetRet qcret,svPARA ;We found the Paradise name
jmp SHORT svQC_exit
svQC_Tseng:
@@LoadSeg es,BIOSseg ;Point to the BIOS location
mov di,0
mov cx,500 ;Search the first 500 bytes
mov al,'T' ;Look for 'Tseng'
svQC_Tsfind:
repne scasb ;Search
jcxz svQC_unknown
cmp BYTE PTR es:[di ],'s' ;Next Letter?
jne svQC_Tsfind ; Compare one at a time, so
; we can avoid static data ...)
cmp BYTE PTR es:[di+1],'e' ;
jne svQC_Tsfind ; If not a match, continue search
cmp BYTE PTR es:[di+2],'n'
jne svQC_Tsfind
cmp BYTE PTR es:[di+3],'g'
jne svQC_Tsfind
@SetRet qcret,svTSENG ;We found the Tseng name
jmp SHORT svQC_exit
svQC_unknown:
@SetRet qcret,svUNKNOWN ;We did not find anything
svQC_exit:
@Exit qcret,qcparm ;Return
svQueryChipset ENDP
END
[LISTING FOUR]
; svPA.ASM ;
; Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. ;
;**************************************************************************;
; This file contains procedures for calculating a pixel's address for any ;
; given display mode. These are INTERNAL routines. ;
; Procedures: svPixelAddr2D svPixelAddr30 svPixelAddr5F ;
; Microsoft ASM 5.x version. Programmer: Chris Howard ;
;**************************************************************************;
; Include files
INCLUDE svDefs.inc
INCLUDE svMacs.inc
.model small
.data
.code
PUBLIC svPixelAddr2D
PUBLIC svPixelAddr30
;**********
; This function determines the address of a pixel in SVGA 256 color
; modes:
; 2DH 640x350x256 Tseng
; 2EH 640x480x256 Tseng
; 66H 640x400x256 Video7
; 67H 640x480x256 Video7
; 5EH 640x400x256 Paradise
; 5FH 640x480x256 Paradise
; Calling: AX = y-coordinate
; BX = x-coordinate
; Returns: ES:BX = pixel pointer
; DX = video segment
;
svPixelAddr2D PROC FAR
mov dx,640 ;Multiply y*BytesPerLine
mul dx
add bx,ax ;Add in x coordinate
adc dx,0 ; and any carry
@@LoadSeg es,EGAseg ;ES:BX = byte address of pixel
ret
svPixelAddr2D ENDP
;**********
; This function determines address of pixel in SVGA 800x600x256 color modes:
; 30H 800x600x256 Tseng
; 69H 800x600x256 Video7
; Calling: AX = y-coordinate (0-599)
; BX = x-coordinate (0-799)
; Returns: ES:BX = pixel pointer
; DX = video segment
;
svPixelAddr30 PROC FAR
mov dx,800 ;Multiply y*bytesrow
mul dx
add bx,ax ;Add in x coordinate
adc dx,0 ; and any carry
@@LoadSeg es,EGAseg ;ES:BX = byte address of pixel
ret
svPixelAddr30 ENDP
END
[LISTING FIVE]
; svPP.ASM ;
; Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. ;
;***************************************************************************;
; This file contains procedures for putting (displaying) a pixel for any ;
; given display mode or virtual buffer. ;
; Procedures: svPutPixel ;
; Microsoft ASM 5.x version. Programmer: Chris Howard ;
;***************************************************************************;
; Include files
INCLUDE svDefs.inc
INCLUDE svMacs.inc
.model small
.data
svDisplay svstruc <svDISP_2D,2DH,svPutPixel2D> ;Tseng Labs
svlen EQU $-svDisplay
svstruc <svDISP_2E,2EH,svPutPixel2D>
svstruc <svDISP_30,30H,svPutPixel30>
svstruc <svDISP_5E,5EH,svPutPixel5F> ;Paradise
svstruc <svDISP_5F,5FH,svPutPixel5F>
svstruc <svDISP_66,1AH,svPutPixel67> ;Video7
svstruc <svDISP_67,1BH,svPutPixel67>
svstruc <svDISP_69,1DH,svPutPixel69>
PUBLIC svCurDisp,svLogOp
svCurDisp dw svDISP_2D ;Current display type
svPixFunc dd ? ;Current pixel function
svBank db -1 ;Current window bank
svLogOp db svOpREP ;Logical operation
EXTRN svPixelAddr2D : FAR
EXTRN svPixelAddr30 : FAR
.code
PUBLIC svSetDisplay
PUBLIC svSetMode
PUBLIC svSetOp
PUBLIC svPutPixel
;**********
; This function sets the display type by selecting the correct pixel
; function for all svPutPixel calls.
;Define variable locations on the stack (pascal model)
sddisp equ <[bp+ 6]> ;Display type
sdparm equ 2
;Define local variables
sdret equ <[bp- 2]> ;return code
sdlocal equ 2 ;Total local space needed
svSetDisplay PROC FAR
@Entry sdlocal ;Set up frame and save regs
@@Data es ;Point to table
mov ax,sddisp ;Get the display type
mov svCurDisp,ax ;Assume valid, and store
mov bx,svlen ;Get offset into table
mul bx
mov di,OFFSET svDisplay ;Add starting location of table
add di,ax
mov ax,WORD PTR es:[di].svfunc[2] ;Store current function
mov WORD PTR svPixFunc[2],ax ; for fast reference
mov ax,WORD PTR es:[di].svfunc[0]
mov WORD PTR svPixFunc[0],ax
@SetRet sdret,svSUCCESS
svSD_exit:
@Exit sdret,sdparm
svSetDisplay ENDP
;**********
; This function sets graphics mode for the currently selected display type.
;Define variable locations on the stack (pascal model)
smmode equ <[bp+ 6]> ;Flag for TEXT or GRAPHICS mode
smparm equ 2
;Define local variables
smret equ <[bp- 2]> ;return code
smlocal equ 2 ;Total local space needed
svSetMode PROC FAR
@Entry smlocal ;Set up frame and save regs
mov svBank,-1 ;Initialize bank
mov ax,smmode ;Get requested "mode"
cmp ax,svGRAPH ;Setting to graphics?
je svSM_graph
@SetMode TEXTMODE ;Set to text mode
@SetRet smret,svSUCCESS
jmp SHORT svSM_exit
svSM_graph:
@@Data es ;Point to table
mov ax,svCurDisp ;Get the display type
mov bx,svlen ;Get offset into table
mul bx
mov di,OFFSET svDisplay ;Add starting location of table
add di,ax
@SetMode es:[di].svmode ;Set to correct graphics mode
@GetMode ;Make sure it stuck
cmp al,es:[di].svmode
je svSM_ok
@SetRet smret,svBADMODE ;No, so return error
jmp SHORT svSM_exit
svSM_ok:
@SetRet smret,svSUCCESS
svSM_exit:
@Exit smret,smparm
svSetMode ENDP
;**********
; This function sets the logical operation for all svPutPixel calls.
;Define variable locations on the stack (pascal model)
soop equ <[bp+ 6]> ;Logical Operation
soparm equ 2
;Define local variables
soret equ <[bp- 2]> ;return code
solocal equ 2 ;Total local space needed
svSetOp PROC FAR
@Entry solocal ;Set up frame and save regs
mov ax,soop ;Get the logical operation
cmp ax,svOpXOR ;Check range
jbe svSO_store
@SetRet soret,svBADMODE ;Error
jmp SHORT svSO_exit
svSO_store:
mov svLogOp,al ;Store it
@SetRet soret,svSUCCESS
svSO_exit:
@Exit soret,soparm
svSetOp ENDP
;**********
; This function is the main entry point to all of the specific PutPixel
; routines. It sets up the appropriate parameters, then branches to the
; correct routine for the current display device.
;Define variable locations on the stack (pascal model)
ppx equ <[bp+10]> ;Pixel coordinate
ppy equ <[bp+ 8]>
ppcolor equ <[bp+ 6]> ;Color
ppparm equ 6
;Define local variables
ppret equ <[bp- 2]> ;return code
pplocal equ 2 ;Total local space needed
svPutPixel PROC FAR
@Entry pplocal ;Set up frame and save regs
mov ax,ppx ;Call pixel function
push ax
mov ax,ppy
push ax
mov ax,ppcolor
push ax
call DWORD PTR svPixFunc
@SetRet ppret,ax
svPP_exit:
@Exit ppret,ppparm
svPutPixel ENDP
;**********
; NOTE: The stack frame is defined in svPutPixel
svPutPixel2D PROC FAR
@Entry pplocal
mov ax,ppy ;Set up call to address routine
mov bx,ppx
call svPixelAddr2D ;ES:BX -> buffer, DL -> seg
cmp dl,svBank ;Is bank currently selected?
je svPP2D_op
@TsengSeg dl
svPP2D_op:
mov al,ppcolor ;Get color
mov dl,svLogOp ;Get operation
cmp dl,svOpRep
jz svPP2D_rep ; (fastest if replace)
cmp dl,svOpXOR ;Is this XOR?
je svPP2D_xor
cmp dl,svOpAND ;Is this AND?
je svPP2D_and
svPP2D_or:
or es:[bx],al ;Or the pixel
jmp short svPP2D_ok
svPP2D_and:
and es:[bx],al ;And the pixel
jmp short svPP2D_ok
svPP2D_xor:
xor es:[bx],al ;Routine to XOR
jmp short svPP2D_ok
svPP2D_rep:
mov es:[bx],al ;Set the pixel value
svPP2D_ok:
@TsengSeg 0 ;Reset
@SetRet ppret,svSUCCESS
@Exit ppret,ppparm
svPutPixel2D ENDP
;**********
; NOTE: The stack frame is defined in svPutPixel
svPutPixel30 PROC FAR
@Entry pplocal
mov ax,ppy ;Set up call to address routine
mov bx,ppx
call svPixelAddr30 ;ES:BX -> buffer, DL -> seg
cmp dl,svBank ;Is bank currently selected?
je svPP30_op
@TsengSeg dl
svPP30_op:
mov al,ppcolor ;Get color
mov dl,svLogOp ;Get operation
cmp dl,svOpRep
jz svPP30_rep ; (fastest if replace)
cmp dl,svOpXOR ;Is this XOR?
je svPP30_xor
cmp dl,svOpAND ;Is this AND?
je svPP30_and
svPP30_or:
or es:[bx],al ;Or the pixel
jmp short svPP30_ok
svPP30_and:
and es:[bx],al ;And the pixel
jmp short svPP30_ok
svPP30_xor:
xor es:[bx],al ;Routine to XOR
jmp short svPP30_ok
svPP30_rep:
mov es:[bx],al ;Set the pixel value
svPP30_ok:
@TsengSeg 0 ;Reset
@SetRet ppret,svSUCCESS
@Exit ppret,ppparm
svPutPixel30 ENDP
;**********
; NOTE: The stack frame is defined in svPutPixel
svPutPixel5F PROC FAR
@Entry pplocal
@EGAPort EGAgraph,parPR5,parUNLOCK ;Unlock proa to pr4
mov ax,ppy ;Set up call to address routine
mov bx,ppx
cmp dl,svBank ;Is bank currently selected?
je svPP5F_op
call svPixelAddr2D ;ES:BX -> buffer, DL -> seg
@ParSeg dl
svPP5F_op:
mov al,ppcolor ;Get color
mov dl,svLogOp ;Get operation
cmp dl,svOpRep
jz svPP5F_rep ; (fastest if replace)
cmp dl,svOpXOR ;Is this XOR?
je svPP5F_xor
cmp dl,svOpAND ;Is this AND?
je svPP5F_and
svPP5F_or:
or es:[bx],al ;Or the pixel
jmp short svPP5F_ok
svPP5F_and:
and es:[bx],al ;And the pixel
jmp short svPP5F_ok
svPP5F_xor:
xor es:[bx],al ;Routine to XOR
jmp short svPP5F_ok
svPP5F_rep:
mov es:[bx],al ;Set the pixel value
svPP5F_ok:
@EGAPort EGAgraph,parPROA,0 ;Zero out proa
@EGAPort EGAgraph,parPR5,parLOCK ;Lock proa to pr4
@SetRet ppret,svSUCCESS
@Exit ppret,ppparm
svPutPixel5F ENDP
;**********
; NOTE: The stack frame is defined in svPutPixel
svPutPixel67 PROC FAR
@Entry pplocal
@EGAPort EGAseq,v7SR6,v7enable ;Enable Video 7 extensions
mov ax,ppy ;AX = y
mov bx,ppx ;BX = x
call svPixelAddr2D ;ES:BX -> buffer, DL -> seg
cmp dl,svBank ;Is bank currently selected?
je svPP67_op
mov cl,dl
@V7Seg cl
svPP67_op:
mov al,ppcolor ;Get color
mov dl,svLogOp ;Get operation
cmp dl,svOpRep
jz svPP67_rep ; (fastest if replace)
cmp dl,svOpXOR ;Is this XOR?
je svPP67_xor
cmp dl,svOpAND ;Is this AND?
je svPP67_and
svPP67_or:
or es:[bx],al ;Or the pixel
jmp short svPP67_ok
svPP67_and:
and es:[bx],al ;And the pixel
jmp short svPP67_ok
svPP67_xor:
xor es:[bx],al ;Routine to XOR
jmp short svPP67_ok
svPP67_rep:
mov es:[bx],al ;Set the pixel value
svPP67_ok:
@V7Seg 0 ;Reset
@EGAPort EGAseq,v7SR6,v7disable ;Disable Video 7 extensions
@SetRet ppret,svSUCCESS
@Exit ppret,ppparm
svPutPixel67 ENDP
;**********
; NOTE: The stack frame is defined in svPutPixel
svPutPixel69 PROC FAR
@Entry pplocal
@EGAPort EGAseq,v7SR6,v7enable ;Enable Video 7 extensions
mov ax,ppy ;Set up call to address routine
mov bx,ppx
call svPixelAddr30 ;ES:BX -> buffer, DL -> seg
cmp dl,svBank ;Is bank currently selected?
je svPP69_op
mov cl,dl
@V7Seg cl
svPP69_op:
mov al,ppcolor ;Get color
mov dl,svLogOp ;Get operation
cmp dl,svOpRep
jz svPP69_rep ; (fastest if replace)
cmp dl,svOpXOR ;Is this XOR?
je svPP69_xor
cmp dl,svOpAND ;Is this AND?
je svPP69_and
svPP69_or:
or es:[bx],al ;Or the pixel
jmp short svPP69_ok
svPP69_and:
and es:[bx],al ;And the pixel
jmp short svPP69_ok
svPP69_xor:
xor es:[bx],al ;Routine to XOR
jmp short svPP69_ok
svPP69_rep:
mov es:[bx],al ;Set the pixel value
svPP69_ok:
@V7Seg 0 ;Reset
@EGAPort EGAseq,v7SR6,v7disable ;Disable Video 7 extensions
@SetRet ppret,svSUCCESS
@Exit ppret,ppparm
svPutPixel69 ENDP
END
[LISTING SIX]
/* svLib.H */
/* Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. */
/**************************************************************************
Function declarations for the Super VGA Library, for C.
Microsoft C version 5.1 Programmer: Chris Howard
***************************************************************************/
/* Display modes */
#define svTEXT 0 /* Text mode */
#define svGRAPHICS 1 /* Graphics mode */
/* Display types */
#define svMINDISP 0
#define svDISP_2D 0 /* Tseng 2DH (640x350x256) */
#define svDISP_2E 1 /* Tseng 2EH (640x480x256) */
#define svDISP_30 2 /* Tseng 30H (800x600x256) */
#define svDISP_5E 3 /* Paradise 5EH (640x400x256) */
#define svDISP_5F 4 /* Paradise 5FH (640x480x256) */
#define svDISP_66 5 /* Video 7 66H (640x400x256) */
#define svDISP_67 6 /* Video 7 67H (640x480x256) */
#define svDISP_69 7 /* Video 7 69H (800x600x256) */
#define svMAXDISP 7
/* Logical Operations */
#define svSET 0 /* SET pixel value directly */
#define svAND 1 /* AND pixel value with data */
#define svOR 2 /* OR pixel value with data */
#define svXOR 3 /* XOR pixel value with data */
/* Chip sets */
#define svUNKNOWN 0 /* Unknown chip set */
#define svTSENG 1 /* Tseng Labs */
#define svPARA 2 /* Paradise */
#define svV7 3 /* Video 7 */
/* Error Codes */
#define svSUCCESS 0 /* Successful */
#define svBADMODE -1 /* Bad display mode */
/* Functions */
extern int far pascal svSetDisplay (int);
extern int far pascal svSetMode (int);
extern int far pascal svSetOp (int);
extern int far pascal svPutPixel (int,int,int);
extern int far pascal svQueryChipset (void);
[LISTING SEVEN]
/* svTest.C */
/* Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. */
/**************************************************************************
This is a simple test program, for testing the Super VGA QueryChipset
and PutPixel functions.
Compile: CL /c /AS svTest.C
link svTest,,,svLib;
Microsoft C version 5.1 Programmer: Chris Howard
***************************************************************************/
#include <stdio.h>
#include <conio.h>
#include "svlib.h"
/* Global data */
static char *chip[] = {"[Unknown]","Tseng Labs","Paradise","Video7"};
/**********/
/* This is a crude box drawing routine. Uses the svPutPixel function to draw */
void svPutSquare(x,y,w,c)
int x,y,w,c;
{
int i;
for (i=0; i<w; i++) {
svPutPixel(x+i,y, c);
svPutPixel(x+i,y+w,c);
svPutPixel(x, y+i,c);
svPutPixel(x+w,y+i,c);
}
} /* end of svPutSquare */
/**********/
void main(void)
{
int i,j,k,chipset,svdisplay,retcode;
/* Display a header */
printf("\n\nSuper VGA Test Program\n\n");
/* Query the chipset, and see what we have */
chipset = svQueryChipset();
printf("Your Super VGA chipset is: %s\n\n",chip[chipset]);
printf("Press any key to continue ...\n\n");
getch();
/* If we have a chipset we recognize, keep going */
if (chipset != svUNKNOWN) {
/* Based on the chipset, select a display type for 256 colors */
switch (chipset) {
case svTSENG:
/* 640x480x256 */
svdisplay = svDISP_2E;
break;
case svPARA:
/* 640x400x256 */
svdisplay = svDISP_5E;
break;
case svV7:
/* 640x480x256 */
svdisplay = svDISP_67;
break;
}
/* Set the display and mode */
retcode = svSetDisplay(svdisplay);
retcode = svSetMode(svGRAPHICS);
/* If the mode was set successfully, try displaying some pixels */
if (retcode == svSUCCESS) {
/* Display a rainbow bar, a few lines thick */
for (j=0; j<10; j++) {
for (i=0; i<256; i++)
svPutPixel(200+i,200+j,i);
}
/* Demonstrate logical operations by XORing a 'square' across rainbow */
retcode = svSetOp(svXOR);
for (i=0; i<256; i++) {
svPutSquare(200+i,200,10,15);
/* Dummy delay */
for (j=0; j<5000; j++)
k = j;
svPutSquare(200+i,200,10,15);
}
/* Wait for a key */
getch();
/* Return to text mode, and display completion message */
svSetMode(svTEXT);
printf("svTest completed\n\n");
}
}
else {
/* We could not recognize the chip, so suggest something */
printf("No test can be run ...\n\n");
printf("If you are sure of your chipset, try changing the program so\n");
printf("the chip type is forced.\n\n");
}
} /* end of main */
[LISTING EIGHT]
# svLIB Make File #
# Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. #
############################################################################
# This make file is for making the Super VGA Library. #
# Usage: Make svLib /I #
# Microsoft ASM 5.1 Programmer: Chris Howard #
############################################################################
# Compiler and linker flags
AFLAGS = /DLINT_ARGS /W2 /B63 /ZI
# /D = Define /W2 = Max ASM warnings /B = Buffer size
CFLAGS = /G0 /AS /Os /c /Zi
# /G0 = 8088 code /AS = Small model /Os = Optimize Size
# /c = Compile only
DFLAGS = /DLINT_ARGS /W3
# /D = Define /W3 = Max C warnings
LFLAGS =
# Compiler Programs
CC = cl $(CFLAGS) $(DFLAGS)
ASM = masm $(AFLAGS)
LINK = link $(LFLAGS)
LIB = lib
# ASM Include files
SVDEFS = svDefs.inc
SVMACS = svMacs.inc
# Libraries
SVLIB = svLib
# Remember:
#
# $* = Base name of the outfile (without extension)
# $@ = Complete outfile name
# $** = Complete list of infiles
#
############
# Query Chipset
svQC.obj: $*.asm $(SVDEFS) $(SVMACS)
$(ASM) $*,$@;
$(LIB) $(SVLIB) -$* +$@;
# Pixel Addressing
svPA.obj: $*.asm $(SVDEFS) $(SVMACS)
$(ASM) $*,$@;
$(LIB) $(SVLIB) -$* +$@;
# Put Pixel
svPP.obj: $*.asm $(SVDEFS) $(SVMACS)
$(ASM) $*,$@;
$(LIB) $(SVLIB) -$* +$@;
# End.
[LISTING NINE]
# svTest Make File #
# Copyright (c) Genus Microprogramming, Inc. 1988-89 All Rights Reserved. #
############################################################################
# This make file is for making the Super VGA Test program. #
# Microsoft C 5.1 Programmer: Chris Howard #
############################################################################
# Compiler and linker flags
CFLAGS = /G0 /AS /Os /c
# /G0 = 8088 code /AS = Small model /Os = Optimize Size
# /c = Compile only
DFLAGS = /DLINT_ARGS /W3 /Zi
# /D = Define /W3 = Max C warnings /Zi = Codeview
LFLAGS = /CO
# /CO = Codeview
# Compiler Programs
CC = cl $(CFLAGS) $(DFLAGS)
ASM = masm
LINK = link $(LFLAGS)
# Include files
SV = svlib.h
# Libraries
SVLIB = svlib.lib
############
# The Test program
svtest.obj: $*.c $(SV)
$(CC) $*.c
# Now link it all together
svtest.exe: $*.obj $(SVLIB)
$(LINK) $*,,,$(SVLIB);