SuperVGA library for Borland/Turbo Pascal 7.0
(C)oded by Asp / VR group
Virtual Research independent group production, 1996-1998
-----------------------------------------------------------------------------
Revision 4
-----------------------------------------------------------------------------

Excuse my English, whoever you're readin' it.
This document is for dummies. If you think you're Cool Coder, RTFS ;)

Following text covers SVGA and VGA256 units from VR group's SuperVGA library.
There is also LFB256 library performed since Revision 1.2 of SuperVGA library,
which is intended for 32-bit Protected Mode environment and must be compiled
with 32-bit compiler (TMT Pascal Lite 2.0 or later). LFB256 provides
interface to VESA 2.0 Linear Framebuffer 256-colors videomodes. Banked
modes is not supported. On the other side, SVGA unit only supports banked
videomodes and is intended for 16-bit Real Mode or V86 environment
(must be compiled with Borland Pascal 7.0 or later). This ideology most
likely will be continued in future versions of library (if any), i. e. only 
LFB videomodes will be supported for 32-bit runtime system, and only banked
modes - for 16-bit. Only 320x200x256 VGA mode is currently available for
Borland 16-bit DPMI (VGA256 unit).
There are no special documentation for VGA256 unit, because it is mostly
similar to SVGA unit in its interface part.
LFB256 library is described in separate document LFB256.TXT.

Note: most recent library changes possibly are not reflected in documentation.
It is recommended to browse through units interface part in any case.
-----------------------------------------------------------------------------


                                  CONTENTS

                [1.] What is SuperVGA library and Why use it?
                [2.] Disclaimer
                [3.] Requirements
                [4.] Introduction to SuperVGA
                [5.] How to use it
                [6.] Procedures in SVGA unit interface
                   [6.1] Initialization procedures
                   [6.2] Drawing routines
                   [6.3] Image manipulation routines
                   [6.4] Palette manipulation routines
                   [6.5] Image files handling procedures
                   [6.6] Fonts and text output
                   [6.7] Virtual display control
                   [6.8] Other procedures and functions
                   [6.9] Global variables
                [7.] Using SVGA unit together with Borland graphics
                [8.] SVGA unit and DPMI
                [9.] VGA256 unit
                   [9.1] Using virtual screens
                   Appendix A: Tested videocards
                   Appendix B: SVGA unit limitations

-----------------------------------------------------------------------------


[1.] What is SuperVGA library and Why use it?


        SuperVGA library is a pack of routines and utilities, which allows
you to use hi-resolution 256-colors SVGA graphics in your applications 
written in Pascal (particularly Borland Pascal dialect). It has been under 
development since 1996, and for now is quite stable and fast (but not yet
finished, I guess.. maybe never will be :). Maybe it's not the best graphics
library you may get, but, hey, it's for free and it works, so what else do
you want?
        You might want to use it because you get bored of 16-colors VGA
graphics and those stupid BGI, and because source code is included and such
a cool coder like you of course will improve it greatly, and because it is
absolutely free.
-----------------------------------------------------------------------------


[2.] Disclaimer


This one is made very short :)
This is FREEWARE, I give NO WARRANTIES and take NO LIABILITY for anything. 
Period.
-----------------------------------------------------------------------------


[3.] Requirements


        Hardware:
        - SVGA videocard (VESA VBE 1.1 or later recommended),
          with at least 1 Mb of memory on it; 
        - appropriate SVGA monitor; 
        - 386 or better computer with 80x87 math co-processor 
          and at least 2 Mb of RAM. 

        Software:
        - Turbo Pascal or Borland Pascal compiler, v. 7.0.
          It also may be compiled with Stony Brook Pascal+,
          v. 6.1 or later. You need TMT Pascal compiler
          v. 2.00 or later to compile 32-bit parts of
          SuperVGA library.
        - HIMEM.SYS or other XMS driver should be properly
          installed for handling images larger then 65520 bytes
          in size with SVGA unit.
-----------------------------------------------------------------------------


[4.] Introduction to SuperVGA


        I think it will be good to define some terms and discuss some matters
before we begin to describe procedures of SVGA.TPU. However, note, that I'm
not kinda professional system programmer or video cards developer, so
following text may contain errors or some inexact information. I am not
responsible for this. 
        What is SuperVGA? Well, as you probably know, standard VGA adapter
was developed by IBM (and it is an IBM industrial standard) for their PS/2
machines. There also was an MCGA (Multi Color Graphics Adapter) in earlier
models of PS/2. Actually, VGA is almost identical to EGA in its internal 
structure, and MCGA is almost identical to CGA respectively. But (among other
differences) there is one very important thing - both VGA and MCGA provide 
new 320x200 256 colors mode, and, thus, analog video output. SuperVGA is not 
a kind of standard; it is even not an exactly defined term. In common words, 
SuperVGA is _any_ graphics adapter, which is fully compatible with VGA on soft 
(i. e. VideoBIOS) and hard (i. e. ports and registers) levels, plus it 
provides some extended features, like non-standard videomodes. Variety of 
SuperVGA cards were created by different manufacturers. After all, several 
extended modes became "standard", and now are being provided by any videocard.
These are: 640x480 pixels, 800x600 pixels, 1024x768 and 1280x1024. There are 
also different number of colors, like: 256, 32768, 65536, 16777216. Here we 
will discuss mostly 256 colors modes. Why? because they have very much in 
common with standard VGA mode $13 (320x200x256), while other have essential 
differences. 
        So, you say, what's the problem with those SVGA modes, if they're
almost standard? Well, "almost" is a keyword here :) What is "standard mode"
at all? Here we define standard videomode as videocard output (i. e., 
electrical signals at monitor input connector pins), which may be obtained 
via VideoBIOS calls, documented in some kind of standard or specification. 
The first question here is how to put your videocard in desired videomode? 
Usually mode is set by calling to VideoBIOS function 0 (BIOS interrupt $10, 
AH=0, AL=<mode number>), though it actually can be set by direct videochip 
programming (i. e. writing some data to videocard's ports). But SVGA 
videomodes don't have standard mode numbers! Their numbers (which you must 
put in AL CPU register) are different for different videocards. It means, that
you must get documentation on _every_ particular SVGA videocard, if you want 
your program to work with all SuperVGA adapters.
        There is also another big problem. As you probably know, there is
Random Access Memory, located on every videocard. It is so called
videomemory. What's the point of having memory on videocard, if you already
got RAM chips on mainboard? Here's the point - image displayed on the screen
must be stored somewhere. Of course, it could be stored in system RAM, but
transferring it through the bus to videocard and then to monitor would be
very slow. So, image is stored in videomemory. If any data appears in
videomemory, it appears on the screen in the same time. But how can you put
data to videomemory? There's a little trick. Address area from $A000:0000 to
$A000:FFFF of system RAM is mapped directly to videomemory. This segment
(segment in 16-bit program is a memory area not bigger then 65536 bytes in
size and starting at address, which is divisible by 16) is called videobuffer.
What does it mean? It means, that when you're putting data to some of these
addresses, it actually goes to those RAM chips on your videoboard instead of
RAM chips on your mainboard. Well, now it's simple. In 256 colors mode each
pixel (element of screen) is defined by 1 byte. When you write 1 byte to
address somewhere in $A000 segment, you see the pixel on the screen. So what's
the problem, you say? A little of arithmetics. $FFFF - $0000 + 1 = $10000 = 
65536, i. e. 64  Kb. And the size of entire screen image in e. g. 1024x768x256 
videomode is 1024 * 768 * 1 byte/pixel = 786432 bytes, i. e. 768 Kb. Ooops!
        This problem was solved in two basic ways. The first and classic
solution is banked videomemory structure. It means, that all available
videomemory is split in so called banks. One or several of videomemory
banks may be mapped to videobuffer at one time, but their summary size must
not exceed 64 K. When you need to write pixel in some part of picture, you
must at first define number of bank, and pixel offset within this bank,
then switch to this bank, and then write pixel value to videobuffer. What
does it mean "switch"? You have to write some certain data to some certain
videocard ports, and after that $A000 segment will become mapped to some 
certain part of videomemory :) Again, size of bank varies from one card to
another, and method of bank switching varies as well. And again, you must
get documentation on _any_ particular videocard you want to work with. 
        The second, newer way is so called linear framebuffer. You must
have heard of it. Some videocards provide support for linear addressing to
videomemory in 32-bit protected mode. What is linear framebuffer? In simple
words, it is an address area, not existing in physical address space, and
mapped directly to videomemory. Due to 32-bit addressing, you don't need
banks anymore. You just write pixels to addresses, where linear framebuffer
is located, and they appear on the screen. Address of pixel is one 32-bit
number, no more segments and offsets! But the same old story: you must know,
how to set up particular videocard for linear framebuffer use. Plus - you must
use 32-bit compiler and code for 32-bit DPMI. If we're talking about Pascal,
it means TMT Pascal or Delphi 2+ (there are several other 32-bit compilers
available, but for now they are mostly in beta stage). You also may try 
assembler :)
        After all you must be wondering, how people can do something with
SVGA at all! They're must be using magic or something... Well, yes, they do.
There is the magic word - VESA. VESA is Video Electronics Standards
Association. It is group of people, who tried to make SVGA standard. They
have succeed, at least partially. Most videocards at these days provide VESA
VideoBIOS Extensions (VESA VBE). There are different versions of VESA VBE,
the last (as far as I know) is VESA VBE 3.0. VESA VBE is a set of functions,
that may be accessed via BIOS call INT $10. It provides standard functions
for mode setting, bank switching, and (since version 2.0) linear framebuffer
support. I think that something about 80% (or even more) of DOS-based
software with SVGA graphics using VESA interface, including well-known
id Software's Quake (ah, good old times..). The little minus of VESA VBE - it
is slow (except 32-bit DPMI VESA interface). The big plus - it _always_ works,
and you don't need to know anything about videocard, just is it VESA 
compatible or not. All modern cards provide VESA VBE, at least version 1.2. 
        Whew! That was lotsa stuff. Now, I hope you see, why coding for SVGA
graphics is not easy, and why SVGA needs pretty fast machine. Though SVGA unit
is not a masterpiece, you still can create nice programs with it. Enjoy it,
if you can - this is not the worst thing of those you can get for free ;) 
-----------------------------------------------------------------------------


[5.] How to use it


        To get access to SVGA procedures, you need to do the following: 
        - copy SVGA.TPU to the UNITS (or anywhere your units are usually 
          located) subdir in your Pascal directory; 
        - add "uses svga;" line (without a quotes :) after your main program
          header; if there already is "uses" keyword, just add "svga" to
          units list.
        - now you may call routines from SVGA.TPU. 
-----------------------------------------------------------------------------


[6.] Procedures in SVGA.TPU


[6.1] Initialization procedures



        You have to do some init stuff before calling any routine from SVGA
unit. There are basically 3 routines you may need to use: 

[6.1.1] procedure _Init(chipset:byte);

        This routine sets up graphics system for particular videocard. Chipset
parameter specifies needed videocard type. Supported cards are: 

       _VESA           - VESA compatible (default)
       _AHEADA         - Ahead A chipset
       _AHEADB         - Ahead B chipset
       _ATI            - ATI, not guaranteed to work with all cards
       _CHIPSNTECS     - Chips & Technologies  82C45x 
       _CIRRUS1M       - Cirrus Logic CL-GD 542x with 1M onboard memory
       _CIRRUS2M       - Cirrus Logic CL-GD 542x with 2M onboard memory
       _COMPAQ         - Compaq QVision/AVGA 
       _ET3000         - Tseng Labs ET3000 
       _ET4000         - Tseng Labs ET4000 (will work with ET6000/6100)
       _ET4000W32      - Tseng Labs ET4000-W32
       _GENOA          - Genoa 6x00 chipset 
       _NCR            - NCR 77C22
       _OAK            - OAK chipset
       _PARADISE       - Paradise / Western Digital WD90Cxx
       _REALTEK        - Realtek 
       _TRIDENT        - Trident 8900 and 9000 
       _VIDEO7         - Video 7  VRAM II 

If your card is VESA VBE compatible (all modern cards are), you don't need
to call for _Init, it will be called automatically in the beginning of
your program with _VESA parameter. However, if your videocard does not
have VESA VBE, you _must_ call for _Init before any other procedure from
SVGA unit.

[6.1.2] procedure _InitMode(mode:word);

This procedure will set up some global variables, but will not actually set
specified videomode. You should call it if you want to use BGI graphics
together with SVGA unit graphics. See section [8.] for more details. Available
videomodes are listed in the next subsection. 

[6.1.3] function _SetMode(mode:word):boolean;

This one is important - it sets display to specified videomode. Available
values for Mode are: _640x350, _640x400, _640x480, _800x600,
_1024x768. Not all the modes are supported by all videocards. If mode
is not supported, _SetMode will return False. If mode was set properly,
_SetMode will return True. However note, that on some systems attempt to
set unsupported videomode may hang up the machine or even cause damage to
your monitor, so be careful!


[6.2] Drawing routines


        This routines will put some graphics onto your monitor screen.
There are two sets of drawing routines: plain and clipped. Plain routines
are faster, but if you will give them coordinates out of screen bounds, bad
things will happen. Clipped routines are a bit slower, but they will clip
graphics in current clipwindow. Clipwindow is defined with _MinClipX,
_MinClipY, _MaxClipX and _MaxClipY variables.
        The names of clipped procedures are the same that of plain procedures,
but start with double underline character "__". For example, __PutPixel etc.

[6.2.1] _PutPixel(x,y:word;color:byte);

Sets pixel of specified color at specified (x,y) coordinates.

[6.2.2] _PutTransparentPixel(x,y:word;color:byte);

This one is similar to previous, but it won't put pixel, if
color=_TransparentColor. See more about it in section [6.8] (Global
variables).

[6.2.3] _GetPixel(x,y:word;var color:byte);

Gets pixel value at specified coordinates and returns it in color variable
parameter.

[6.2.4] _Line(x1,y1,x2,y2:word;color:byte);

Draws a line from (x1,y1) to (x2,y2) in specified color.

[6.2.5] _MaskedLine(x1,y1,x2,y2:word;color:byte;mask:word);

Draws a line from (x1,y1) to (x2,y2) in specified color, with 16-bit mask.
For example, if mask=$8888 (1000100010001000 binary), dot line will be drawn
with 3 invisible pixels between each visible.

[6.2.6] _HLine(x1,x2,y:word;color:byte);

Draws horizontal line from x1 to x2 at Y scanline, with specified color. This
one is much faster then _Line. Note, that x1 MUST be bigger than x2, or
it'll not work.

[6.2.7] _VLine(x,y1,y2:word;color:byte);

Draws vertical line from y1 to y2 at X position, with specified color. This
one is much faster then _Line. Again, y1 _must_ be bigger than y2. 

[6.2.8] _Ellipse(xc,yc,rx,ry:word;color:byte);

Draws an ellipse with center at (xc,yc) and Rx and Ry half-axis', in specified
color.

[6.2.9] _FilledEllipse(xc,yc,rx,ry:word;color:byte);

The same as previous, but ellipse is filled with specified color.

[6.2.10] _Box(x1,y1,x2,y2:word;color,fill:byte);

Draws a box with upper left corner at (x1,y1) and lower right corner at
(x2,y2), in specified color. If Fill<>0, box will be filled with Fill color.
Note, that x1 _must_ be bigger than x2, and y1 _must_ be bigger than y2, or it
will not work. Yeah, yeah, I know this sucks... but it speeds things up!

[6.2.11] _Triangle(x1,y1,x2,y2,x3,y3:word;color:byte);

Draws an unfilled triangle with vertexes at (x1,y1), (x2,y2), (x3,y3).

[6.2.12] _FilledTriangle(x1,y1,x2,y2,x3,y3:word;color:byte);

Draws a triangle with vertexes at (x1,y1), (x2,y2), (x3,y3), filled
with specified color.

[6.2.13] _FilledPolygon(var VertexArray;NumOfVertexes,color:byte);

Draws filled polygon. VertexArray must be an array containing coordinates
of polygon vertexes, i. e. ((x1,y1),(x2,y2),...,(xN,yN)) (each vertex is a
pair of words or integers). NumOfVertexes is number of vertexes in array. 
Vertexes must be ordered, and polygon must be convex.


[6.3] Image manipulation routines


[6.3.1] _GetImage(x1,y1,x2,y2:word;clip:pointer);

Gets rectangular part of screen, determined by (x1,x2) - upper left corner
and (x2,y2) - lower right corner, and stores it in memory buffer, at which
Clip points. Note, that image size must not exceed 64 K, i. e. something
about 320x200 pixels.

[6.3.2] _PutImage(x1,y1:integer;width,height:word;clip:pointer);

Puts previously grabbed image. (x1,y1) determines upper left corner, and
Width and Height is image width and height respectively. Clip is pointer to
image buffer. Note, that x1 and y1 may also take negative values. <:) 

[6.3.3] _PutTransparentImage(x1,y1:integer;width,height:word;clip:pointer);

The same as previous, but won't put transparent pixels. See section [6.8] 
about _TransparentColor variable.

[6.3.4] _GetLargeImage(x1,y1,x2,y2:word;handle:word);

Will get large (more than 64 K) image part and store it in XMS buffer. Handle
is an Extended Memory Block handle. Note, that you must allocate EMB by
yourself, and it must be big enough! Use VR group's XMANAGER unit (included
with this package) for this, or any other XMS support unit.

[6.3.5] _PutLargeImage(x1,y1:integer;width,height:word;handle:word);

Puts previously grabbed large image. You got the idea :)

Note, that PutImage procedures will always clip image within logical screen
bounds (0,0,_MaxX,_MaxY), independently of clipwindow coordinates.
In VGA256, however, image will be clipped within clip bounds, defined by
vgaMinClipX, vgaMinClipY, vgaMaxClipX and vgaMaxClipY.


[6.4] Palette manipulation routines


[6.4.1] _SetPalette(var pal);

Sets the current palette. Parameter Pal must be the first element of static
or either dynamic array of size at least 768 bytes, in which palette
information is stored. The palette format is R, G, B, R, G,... etc., where R,
G, B - red, green and blue components for corresponding colors, one byte
each (first 3 bytes are for color 0, second 3 bytes - for color 1 etc.). Only
lower 6 bits of each byte are valid.

[6.4.2] _FixedPalette(var pal);

The same as previous, but waits for vertical retrace before palette setting,
avoiding some image defects in this way.

[6.4.3] _GetPalette(var pal);

Gets current palette. Meaning of Pal parameter is the same that in [6.4.1]. 

[6.4.4] _FadeIn(pal:array of byte;speed:real);

Smoothly changes palette entries from 0 to specified in Pal parameter palette,
i. e. making so called 'fade in' effect. You must set blank palette (all
zeros in palette array) before calling this procedure. The speed parameter
determines fading speed. It may take values from 1 through 65536, the bigger
the slower. Normal fading speed is something about 50..60, 100 is quite slow,
200 is VERY slow (on a 486 machine).
This procedure needs at least 16 K of free stack.

[6.4.5] _FadeOut(pal:array of byte;speed:real);

Smoothly changes palette entries from specified values to 0. This procedure
is similar to previous, but works vice-versa. 
This procedure needs at least 16 K of free stack.

[6.4.6] _SetColor(color,r,g,b:byte);

Sets Red, Green and Blue values for color. R, G and B must be in range 0..63.

[6.4.7] _GetColor(color:byte;var r,g,b:byte);

Gets Red, Green and Blue components of specified color.


Note: RGB and Palette types are provided for convenience:

 type TRGB=record
  R,G,B:byte;
 end;

 type TPalette=array[0..255] of TRGB;


[6.5] Image files handling procedures


        These routines are for saving and loading pictures. SVGA unit uses
PCX format for image files. Note, that I/O errors checking is _not_ performed
within these procedures.

[6.5.1] _LoadPCX(filename:string;fileoffset:longint;x,y:word);

Loads image from PCX file with corresponding name. File will be opened and
then closed. FileOffset must point to image start location in somewhat big
image library. If loading from single file, set FileOffset to 0. (x,y) specify
the upper left corner of image on the screen. File format check is performed,
so images from invalid files will not be loaded. Maximal allowed picture width
is 4096 pixels, height is 65535 pixels.

[6.5.2] _SavePCX(filename:string;x1,y1,x2,y2:word);

Saves rectangular part of screen, determined by (x1,y1), (x2,y2) to PCX image
file with specified name. If file exists it will be overwritten without any
prompts nor warnings.

[6.5.3] _GetPCXPalette(filename:string;var palette);

Reads palette from specified PCX file. Palette then may be applied by call to
_SetPalette. You must use this procedure to see correct picture colors.
Palette itself will always be read from the end of file, doesn't matter how 
many PCX images are actually stored in it. So, if you have joined several PCX
files into large library, _GetPCXPalette will always return palette of the 
last bound file.
File type checking is not performed, so actually you can get palette from text
file or something :)

[6.5.4] _GetPCXSize(filename:string;fileoffset:longint;var x,y:word);

Reads image width and height from specified file and returns them in x and
y variable parameters. Other parameters meaning is the same that in
_LoadPCX routine. File format is checked.


[6.6] Fonts handling and text output


        SVGA unit uses 8x16 bitmap fonts for text output. You may use custom
8x16 fonts (.TXF). Before calling to _WriteStr, font must be loaded and
defined. You also may link fonts to EXE body as usually. You may use some
third-party font editor program (there are several available over BBS's and
ftp sites) to create your own fonts. Some fonts are supplied with this library,
you will find then in /font subdirectory of distribution archive. 

[6.6.1] _WriteStr(x,y:word;S:string;color:byte);

Writes text string S at the position (x,y), with specified color and current
font.

[6.6.2] _SetFont(p:pointer);

Sets new current font. P is pointer to font location in memory. Just
GetMem(p,4096) and then load font file:

       .
       .
       .
        Assign(F,'MYFONT.TXF');
        Reset(F,4096);
        BlockRead(F,p^,1);
        _SetFont(p);
       .
       .
       .


[6.7] Virtual display control


        With virtual display control you may perform scrolling and
pageflipping effects. However, it is only possible if your videocard has VESA
BIOS extension according to VESA specification v. 1.2 or later. There are two
procedures:

[6.7.1] _SetLogicalWidth(newwidth:word);

Sets logical display width to NewWidth pixels. You must clear videomemory
before doing this, because image will be screwed up. This procedure modifies
_MaxX and _MaxY, but you have to call _RestoreDisplayBounds in order
to set correct values for clipwindow.

[6.7.2] _SetDisplayOrigin(x,y):word;

This one sets virtual display origin to the point with (x,y) coordinates.
you may perform scrolling and pageflipping with this procedure. To emulate
pageflipping, first store _MaxY in some variable, like OldMaxY:=_MaxY,
and call _SetLogicalWidth(_MaxX+1). Then determine number of pages:
NumOfPages:=(_MaxY+1) div (OldMaxY+1). Now to set visual page Page, you
have to call _SetDisplayOrigin(0,(OldMaxY+1)*Page). To put graphics on
active page Page, you have to add (OldMaxY+1)*Page to your Y coordinate.


[6.8] Other procedures and functions


        There are several routines, which can't be included to any of the
above categories.

[6.8.1] _Fill(color:byte);

Fills the entire screen with specified color.

[6.8.2] _SetTextMode;

Sets display to text mode 80x25 16 colors.

[6.8.3] _WaitVSync;

Waits for vertical retrace. Does not wait if display is already in retrace
state.

[6.8.4] _WaitVSyncStart;

Waits for vertical retrace start.

[6.8.5] Copyleft_Id;

This function returns a string, containing description and version number
of the product. Version also can be obtained from Version string constant.

[6.8.6] _RestoreDisplayBounds;

Restores clipwindow to full screen size.


[6.9] Global variables


        There are 11 global variables defined in unit interface. 

[6.9.1] _MaxX:word;

This one holds maximal X coordinate allowed for current videomode.
Should not be modified by user.

[6.9.2] _MaxY:word;

This one holds maximal Y coordinate allowed for current videomode. 
Should not be modified by user.

[6.9.3 - 6.9.6] _MinClipX,_MinClipY,_MaxClipX,_MaxClipY:word;  

These four determine current window for clipping.
May be modified by user.

[6.9.7] _Mode:word;

This is current videomode, or 0 for text or undefined mode.
Should not be modified by user.

[6.9.8] _VESAPresent:boolean;

True if VESA VBE was found, otherwise False.
Should not be modified by user.

[6.9.9] _VESAInfo:T_VESAInfo;

Holds VESA VBE information, if one was found. This is a record with
following fields:

  Signature:array[1..4] of char;  - VESA signature, i. e.'VESA'
  Version:word;                   - VESA VBE version in BCD
  OEMId:pointer;                  - Far pointer to ASCIIZ OEM id. string
  Flags:longint;                  - VESA capabilities
  ModeList:pointer;               - Used to be pointer to modes list structure
                                    at initialization time. You should not use
                                    it because after init stuff is done, it is not
                                    a valid pointer any longer
  VideoMemory:word;               - Videomemory in 64 K banks
  Reserved:array[1..236] of byte; - Some additional VESA 2.0+ info

Should not be modified by user.

[6.9.10] _Chipset:word;

Currently selected chipset, or 0 for VESA.
Should not be modified by user.

[6.9.11] _TransparentColor:byte;

Defines 'transparent' color. Pixels with this color will not be displayed.
It works not for all the procedures. This variable affects only procedures
[6.2.2], [6.2.5], [6.2.10] and [6.3.3].
May be modified by user.
-----------------------------------------------------------------------------


[7.] Using SVGA.TPU together with Borland graphics


        There are lots of SuperVGA BGI drivers like VESA.BGI, BGI256.BGI,
SVGA256.BGI etc. They allow you to use standard Borland graphics functions
from GRAPH.TPU in hi-resolution VESA modes. To activate BGI SVGA driver, 
you have to use InstallUserDriver as usually. 
        You may use both BGI driver and SVGA.TPU, but there are some things
you must keep on mind. Both driver and module must be initialized. Specific
global variables in SVGA unit get their values during mode setting. But if
you're using BGI, mode setting is performed by InitGraph routine. It is stupid
to set the same videomode twice, so I added special procedure, _InitMode, to 
initialize mode without actual setting. So, after setting mode via InitGraph,
you have to call _InitMode for the same mode. After that, you may use 
functions from GRAPH.TPU and from SVGA.TPU without any problems (I hope... ;).
The example program template is: 

        program crazy;
        uses graph, svga;
        var driver:integer;
            path:string;
            mode:integer;
        begin
         driver:=InstallUserDriver('vesa',nil);
         path:=''; (* or something... *)
         mode:=3;  (* 800x600         *) 
         InitGraph(driver, mode, path);
         _InitMode(_800x600); (* The _same_ mode! *)
          (* Now both graphics interfaces are initialized *)
                 .
                 .
                 .
        end.

Drawing routines from SVGA.TPU also should work in 320x200 mode, provided
by many SVGA BGI drivers, but you must set _MaxX:=319 and _MaxY:=199
manually. All palette routines will work correctly in any case, because
they're independent from screen resolution. 
-----------------------------------------------------------------------------


[8.] SVGA unit and DPMI


        In current version SVGA unit can _not_ be compiled for DPMI target.
To make it DPMI compatible it needs some essential remaking (at least you 
need to change all '$A000' to 'segA000', but this would be just beginning). 
I don't plan to write DPMI version, because I don't  think it is really 
necessary, especially now, when LFB256 is done and TMTPC 3.x is out. You may 
try if you want to, though, but this wouldn't be easy, I warn you. If you 
really need SVGA graphics in protected mode, you better use GRAPH unit with 
appropriate VESA BGI driver. Or go get TMT Pascal and enjoy true 32-bit 
accelerated graphics :)
-----------------------------------------------------------------------------


[9.] VGA256 unit


        VGA256 unit is generally similar to SVGA unit and provides the same
functions for VGA 320x200x256 mode $13. It may be compiled for either Protected
Mode or Real Mode target. Main differences from SVGA are: 1) you don't need to
perform videocard initialization; 2) vgaSetMode has no input parameters
(naturally!); 3) there is no vgaGetLargeImage, because entire screen fits in
64000 bytes; 4) when calling for vgaPutLargeImage in Protected Mode you must
specify large memory block pointer returned by GlobalAllocPtr instead of 16-bit
EMB handle. There are also other differences, but I think that source code is
pretty clear, so take a look at it.


[9.1] Using virtual screens


        Virtual screens are the main difference (for a while) between VGA
and SVGA units. What is virtual screen? It's just an area of 64000 bytes
somewhere in memory, which is being considered a videobuffer. For first, you 
have to allocate a screen by calling vgaAllocVirtualScreen. It returns virtual
screen segment (pointer type) or nil if an error has occurred. Remember, that
each virtual screen eats up 64 K off the heap, so don't get excited :).
        When you call to vgaSetVirtualOutput(S), all graphics output will
be redirected to virtual screen with segment S. You may call for drawing
routines, PutImage, GetImage etc. - nothing will be really displayed. Then
call vgaFlushVirtualScreen(S) - and everything will appear on the display! To
set normal graphics output again, use vgaSetNormalOutput. You also may use
vgaMoveToVirtualScreen(S), to move current display contents to specified
virtual screen.
        When you don't need them anymore, allocated virtual screens may be 
released with vgaFreeVirtualScreen(segment:pointer), where segment is the 
pointer returned by vgaAllocVirtualScreen.
        Virtual screens are the same that "videopages", and they are
especially useful for smooth animation and real-time rendering.
-----------------------------------------------------------------------------



Appendix A: Tested videocards


        This unit was tested and found to be fully compatible with: 

   Card type                                             _Init parameter(s)
                                                         used
   ------------------------------------------            ------------------
 
 - Western Digital WD90C33, VLB, 1M, VESA 1.1            _PARADISE,
                                                         _VESA       
 - S3 ViRGE DX, PCI, 2M, VESA 2.0                        _VESA       
 - S3 Trio 32, PCI, 1M, VESA 1.2                         _VESA       
 - Tseng Labs ET6000, PCI, 2M, VESA 2.0                  _ET3000,
                                                         _ET4000,
                                                         _ET4000W32,
                                                         _VESA        
 - Trident TVGA 9000i, ISA, 512K, VESA 1.2               _TRIDENT,
                                                         _VESA       

        You are welcome to add your videocard to this list (it is not
considered as a changes to this documentation, so go for it). Please write
card name, chipset, bus type, onboard memory, VESA VBE version and _Init
parameter used.
------------------------------------------------------------------------------


Appendix B: SVGA unit limitations


 - Maximal screen resolution supported is 1024x768
 - Maximal PCX image width can be processed is 4096 pixels
 - Virtual display controls only work with VESA videocards
 - Other limitations may depend on your hardware and software configuration

-----------------------------------------------------------------------------

                That's all for a while. See you..
-----------------------------------------------------------------------------

 - Asp
   6th of September, Cold & Lonely Fall of 1997
   last updated in July 1999


