community.borland.com

Article #15355: Using the VESA16.BGI that Comes with BP 7.0

 Technical Information Database

TI355D.txt - Using the VESA16.BGI that Comes with BP 7.0

Category   :Turbo Pascal
Platform   :All
Product    :

Description:

VESA DRIVERS

     With the release of Borland Pascal for Objects 7.0,
programmers can now use BGI graphics to obtain 16 color
resolutions of 800 X 600, 1024 X 768, and 1280 X 1024.

HOW TO USE THE VESA16.BGI DRIVER

     The VESA unit included with this Tech Info Sheet shows you a
simple way to use  the new VESA driver in your own program. To
get started, you need only include the word VESA in your uses
clause and then call the included Initialize procedure. So the
simplest possible program using the VESA driver might look like
this:

program Simple;
uses
   Graph,
   Vesa;
begin
  Initialize('c:\bp\bgi');
  OutText('Hello');
  ReadLn;
  CloseGraph;
end.


This program assumes, of course, that you have the VESA unit
available on disk and that your BGI drivers are kept in the
C:\BP\BGI sub directory. If the system this program is run on
does not support the VESA BIOS then the code in the VESA unit
will automatically switch your computer into the highest
available mode.
      The next few paragraphs describe a somewhat more complex
program, also included in this TI, which shows you how to use the
new high resolution modes. This program is called VesaSamp.Pas.
It uses the VESA unit, also listed below, to load the BGI  VESA
graphics driver into memory. The program then shows you the
highest available resolution on your system.
     In order to simplify the process of entering graphics mode,
the VESA UNIT provides you with an easy to use Initialize
procedure which takes the location of the BGI drivers as its sole
parameter. This procedure will automatically switch you into
graphics mode, and also initialize several useful variables.
     As presented below, program VesaSamp.Pas hardcodes the
location of the BGI drivers as being in the C:\BP\BGI sub
directory. If this is not the case on your system, then you need
to change this code before running the program. For instance, if
you store the BGI drivers in the D:\PASCAL\DRIVERS sub directory,
then you should change the call that reads:

Initialize('c:\bp\bgi');

so that it reads:

Initialize('d:\pascal\drivers');

If you have the BGI drivers available in the current sub
directory, then you would initialize the graphics system with the
following code:

Initialize('');

After correctly setting up the Initialize procedure, the VesaSamp
program will pop into graphics mode and show you the highest
available resolution.

WHAT IS THE VESA BIOS?

     The VESA BIOS represents a standard for accessing SUPER VGA
resolutions. The problem it addresses is that there are many
different Super VGA boards on the market, but no common API for
addressing them.
     To attempt to bring some sort of sanity to this madness, the
Video Electronics Standards Association (VESA) defined a set of
BIOS extensions that allow programmers to ask the video adapter
about its abilities. These BIOS extensions are sometimes
implemented directly in ROM and sometimes loaded into memory by a
special TSR. Many of these TSRs are available on the Compuserve
Information Service (1-800-848-8990).
     Since it is always possible that the video card on any
particular system might not support the VESA extensions, you
should be aware that your program might not actually run in a
high resolution mode. But the Borland Graphics Interface will
find the highest available mode and then switch you into it.
     The rest of this TI contains the sample code which shows you
how to use the VESA BGI driver. You should be aware of the fact
that it is necessary for the VESA .PAS unit to automatically
detect whether or not you have compiled your program as a
protected mode application. In other words, if you want to copy
code from the VESA unit directly into your program, make sure you
are getting the DOS code for DOS apps and the DPMI code for DPMI
apps.

program VesaSamp;
{
 A test program for unit Vesa
 which provides Super VGA Resolutions
}
uses
  Graph,
  Vesa;

{ Converts an integer to a string }
function Int2Str(L : LongInt) : string;
var
  S : string;
begin
  Str(L, S);
  Int2Str := S;
end; { Int2Str }

var
  S: String;
begin
  Initialize('c:\bp\bgi');
  Rectangle(0,0,MaxX,MaxY);
  SetColor(LightGreen);
  SetBkColor(Blue);
  SetTextStyle(TriplexFont, HorizDir, 8);
  S := 'MaxX = ' + Int2Str(MaxX);
  OutTextXY((MaxX Div 2)  - (TextWidth(S) div 2),
            (MaxY div 2) - 220, S);
  S := 'MaxY = ' + Int2Str(MaxY);
  OutTextXY((MaxX Div 2) - (TextWidth(S) div 2), (MaxY div 2) -
80, S);
  S := 'MemAvail = ' + Int2Str(MemAvail);
  OutTextXY((MaxX Div 2)  - (TextWidth(S) div 2), (MaxY div 2) +
60, S);
  ReadLn;
  CloseGraph;
end.

{***************************************************}
{******************** VESA UNIT *********************}
{***************************************************}

unit Vesa;
{
        Add this unit to programs that want Vesa support
  for high resolutions such as 800 X 600, 1024 X 768
  and 1280 X 1024. If Vesa is not supported on a system
  the code automatically defaults to an available driver
  such as EGAVGA.
       To Initialize the graphics system, just call
  Initialize with the path to VESA.BGI as the sole
  parameter. Pass an empty string if the driver
  is in the current subdirectory.
       The code will automatically detect if you are
  running in protected mode or real mode.

  Examples:
    Initialize('c:\bp\bin');
    Initialize('');
}
Interface

uses
  Graph {$IfDef DPMI}, WinApi {$EndIf};

const
  VESA16Modes: array[0..2] of Word =
    ($0102, $0104, $0106);

type
  VgaInfoBlock = record
    VESASignature: array[0..3] of Byte;
    VESAVersion: Word;
    OEMStringPtr: Pointer;
    Capabilities: array[0..3] of Byte;
    VideoModePtr: Pointer;
  end;

var
  MaxColor,
  MaxX, MaxY: Integer;

procedure Initialize(PathToDriver: String);
implementation

var
  VESA16      : Integer;  { Driver number of 16 color driver }

function GetHighestCap(Table: Pointer; Modes: Word; Size:
Integer): Integer;
  near; assembler;
asm
        XOR     AX,AX
        LES     DI, Table

1:
        MOV     SI, Modes
        ADD     SI, Size
        ADD     SI, Size
        SUB     SI, 2
        MOV     BX, ES:[DI]
        CMP     BX, 0FFFFH
        JE      
4
        INC     DI
        INC     DI
        MOV     CX,Size

2:
        CMP     BX,[SI]
        JZ      
3
        DEC     SI
        DEC     SI
        LOOP    
2

3:
        CMP     AX,CX
        JA      
1
        MOV     AX,CX
        JMP     
1

4:
        DEC     AX
end;

{$IFDEF DPMI}
type
  TRealRegs = record
    RealEDI: Longint;
    RealESI: Longint;
    RealEBP: Longint;
    Reserved: Longint;
    RealEBX: Longint;
    RealEDX: Longint;
    RealECX: Longint;
    RealEAX: Longint;
    RealFlags: Word;
    RealES: Word;
    RealDS: Word;
    RealFS: Word;
    RealGS: Word;
    RealIP: Word;
    RealCS: Word;
    RealSP: Word;
    RealSS: Word;
  end;

function DetectVesa16: Integer; far; assembler;
var
  Segment, Selector, VesaCap: Word;
asm
{$IFOPT G+}
        PUSH    0000H
        PUSH    0100H
{$ELSE}
        XOR     AX,AX
        PUSH    AX
        INC     AH
        PUSH    AX
{$ENDIF}
        CALL    GlobalDosAlloc
        MOV     Segment,DX
        MOV     Selector,AX
        MOV     DI,OFFSET RealModeRegs
        MOV     WORD PTR [DI].TRealRegs.RealSP, 0
        MOV     WORD PTR [DI].TRealRegs.RealSS, 0
        MOV     WORD PTR [DI].TRealRegs.RealEAX, 4F00H
        MOV     WORD PTR [DI].TRealRegs.RealES, DX
        MOV     WORD PTR [DI].TRealRegs.RealEDI, 0
        MOV     AX,DS
        MOV     ES,AX
        MOV     AX,0300H
        MOV     BX,0010H
        XOR     CX,CX
        INT     31H
        MOV     DI,OFFSET RealModeRegs
        MOV     AX,grError
        PUSH    AX
        CMP     WORD PTR [DI].TRealRegs.RealEAX,004FH
        JNZ     
Exit
        POP     AX
        MOV     ES,Selector
        XOR     DI,DI
        CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
        JNZ     
Exit
        CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
        JNZ     
Exit
        MOV     AX,0000
        MOV     CX,1
        INT     31H
        MOV     VesaCap,AX
        MOV     DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[2]
        MOV     CX,4
        XOR     AX,AX

Convert:
        SHL     DX,1
        RCL     AX,1
        LOOP    
Convert
        ADD     DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[0]
        ADC     AX,0
        MOV     CX,AX
        MOV     BX,VesaCap
        MOV     AX,0007H
        INT     31H
        INC     AX
        XOR     CX,CX
        MOV     DX,0FFFFH
        INT     31H
        MOV     ES,BX
        PUSH    ES
        PUSH    DI
{$IFOPT G+}
        PUSH    OFFSET Vesa16Modes
        PUSH    0003H
{$ELSE}
        MOV     SI, OFFSET Vesa16Modes
        PUSH    SI
        MOV     AX, 5
        PUSH    AX
{$ENDIF}
        CALL    GetHighestCap
        PUSH    AX
        MOV     BX,VesaCap
        MOV     AX,0001H
        INT     31H

Exit:
        PUSH    Selector
        CALL    GlobalDosFree
        POP     AX
end;
{$ELSE}
function DetectVesa16: Integer; far; assembler;
var
  VesaInfo: array[0..255] of Byte;
asm
        MOV     AX,SS
        MOV     ES,AX
        LEA     DI,VesaInfo
        MOV     AX,4F00H
        INT     10H
        CMP     AX,004FH
        MOV     AX,grError
        JNZ     
Exit
        CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
        JNZ     
Exit
        CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
        JNZ     
Exit
        LES     DI,ES:[DI].VgaInfoBlock.VideoModePtr
        PUSH    ES
        PUSH    DI
        MOV     AX, OFFSET Vesa16Modes
        PUSH    AX
        MOV     AX,3
        PUSH    AX
        CALL    GetHighestCap

Exit:
end;
{$ENDIF}

procedure Initialize(PathToDriver: String);
var
  MaxColor,
  ErrorCode,
  GraphMode,
  GraphDriver: Integer;
begin
  VESA16 := InstallUserDriver('VESA16', 
DetectVESA16);
  GraphDriver := Detect;
  InitGraph(GraphDriver, GraphMode, PathToDriver);
  ErrorCode := GraphResult;
  if ErrorCode <> grOK then begin
    WriteLn('Graphics error: ', GraphErrorMsg(ErrorCode));
    ReadLn;
    Halt;
  end;
  MaxX := GetMaxX;
  MaxY := GetMaxY;
  MaxColor := GetMaxColor;
end;
end.


Reference:
 

3/30/99 2:58:27 PM
 

Last Modified: 01-SEP-99