@Submissives VESA VBE Interface

:Introduction
^Introduction

% Welcome to Submissives VESA VBE Interface

 If you want to program the VESA VBE 2.0 interface from protected mode
 you might already know that you have to deal with realmode-interrupts
 and other nasty stuff.

 Therefore I wrote a short and easy to use library which gives you all
 the tools you need to work with the VBE 2.0 extensions.

 This library isn't perfect nor it covers all aspects of the VBE 2.0
 standard. However, during all my tests I found it very usefull and
 didn't found any card where this library fails.

 Please note, that you have to initialize the libary before you use it.

 You might check out the ~Example Code~ before you use it.

 Visit our homepage: http://www.cubic.org
 reach me via email me at: submissive@cubic.org

:VBE Constants
^VBE Constants

  Bit-Definition of the ControllerInfo Capability fields
  #define CAP_8bit_DAC              1
  #define CAP_VGACompatible         2
  #define CAP_Use_VBE_DAC_Functions 4

  Bit-Definition of the ModeInfo Attribute fields
  #define ATTR_HardwareMode         1
  #define ATTR_TTY_Support          2
  #define ATTR_ColorMode            4
  #define ATTR_GraphicsMode         8
  #define ATTR_No_VGA_Mode         16
  #define ATTR_No_SegA000          32
  #define ATTR_LFB_Support         64

  Bit-Definitions of the Window Attributes
  #define WATTR_Relocatable         1
  #define WATTR_Readable            2
  #define WATTR_Writeable           4

  Definitions of the MemoryModel Field
  #define MM_TextMode               0
  #define MM_CGA_Graphics           1
  #define MM_Hercules_Graphics      2
  #define MM_Planar                 3
  #define MM_PackedPixel            4
  #define MM_UnChained              5
  #define MM_DirectColor            6   // e.g. truecolor or highcolor
  #define MM_YUV                    7


:VBE Structures
^VBE Structures

  struct bcd16 {
    unsigned char lo;
    unsigned char hi;
  };

 struct DPMI_PTR
 {
   unsigned short int segment;
   unsigned short int selector;
 };

 struct VBE_VbeInfoBlock {
   unsigned long  vbeSignature;
   bcd16    vbeVersion;         // note: this changed from short int
   char *   OemStringPtr;
   unsigned long  Capabilities;
   unsigned short * VideoModePtr;
   unsigned short TotalMemory;
   unsigned short OemSoftwareRev;
   char *   OemVendorNamePtr;
   char *   OemProductNamePtr;
   char *   OemProductRevPtr;
   char     Reserved[222];
   char     OemData[256];
 };

 struct VBE_ModeInfoBlock {
   unsigned short ModeAttributes;
   char WinAAttributes;
   char WinBAttributes;
   unsigned short Granularity;
   unsigned short WinSize;
   unsigned short WinASegment;
   unsigned short WinBSegment;
   void *         WinFuncPtr;
   unsigned short BytesPerScanline;
   unsigned short XResolution;
   unsigned short YResolution;
   char XCharSize;
   char YCharSize;
   char NumberOfPlanes;
   char BitsPerPixel;
   char NumberOfBanks;
   char MemoryModel;
   char BankSize;
   char NumberOfImagePages;
   char Reserved;
   char RedMaskSize;
   char RedFieldPosition;
   char GreenMaskSize;
   char GreenFieldPosition;
   char BlueMaskSize;
   char BlueFieldPosition;
   char RsvdMaskSize;
   char RsvdFieldPosition;
   char DirectColorModeInfo;
   void * PhysBasePtr;
   void * OffScreenMemOffset;
   unsigned short OffScreenMemSize;
   char  reserved2[206];
 };

:VBE_VbeInfoBlock
^VBE_VbeInfoBlock

 struct VBE_VbeInfoBlock {
   char  vbeSignature[4];
   unsigned short vbeVersion;
   char *   OemStringPtr;
   unsigned long  Capabilities;
   unsigned short * VideoModePtr;
   unsigned short TotalMemory;
   unsigned short OemSoftwareRev;
   char *   OemVendorNamePtr;
   char *   OemProductNamePtr;
   char *   OemProductRevPtr;
   char     Reserved[222];
   char     OemData[256];
 };

:VBE_ModeInfoBlock
^VBE_ModeInfoBlock

 struct VBE_ModeInfoBlock {
   unsigned short ModeAttributes;
   char WinAAttributes;
   char WinBAttributes;
   unsigned short Granularity;
   unsigned short WinSize;
   unsigned short WinASegment;
   unsigned short WinBSegment;
   void *         WinFuncPtr;
   unsigned short BytesPerScanline;
   unsigned short XResolution;
   unsigned short YResolution;
   char XCharSize;
   char YCharSize;
   char NumberOfPlanes;
   char BitsPerPixel;
   char NumberOfBanks;
   char MemoryModel;
   char BankSize;
   char NumberOfImagePages;
   char Reserved;
   char RedMaskSize;
   char RedFieldPosition;
   char GreenMaskSize;
   char GreenFieldPosition;
   char BlueMaskSize;
   char BlueFieldPosition;
   char RsvdMaskSize;
   char RsvdFieldPosition;
   char DirectColorModeInfo;
   void * PhysBasePtr;
   void * OffScreenMemOffset;
   unsigned short OffScreenMemSize;
   char  reserved2[206];
 };

:VBE_Init
^VBE_Init

% void VBE_Init (void);

 Must be called before any of the other functions will be called,
 otherwise your system will crash.

 You might also take a look at the counterpart ~VBE_Done~

:VBE_Done
^VBE_Done

% void VBE_Done (void);

 Frees all memory allocated by ~VBE_Init~.. Not a must to call, but
 it frees about 1k

:DPMI_AllocDOSMem
^DPMI_AllocDOSMem

% void DPMI_AllocDOSMem (short int paras, DPMI_PTR *p);

  Allocate paras numbers of memory-paragraphs (16 bytes)
  in realmode memory and store the segment/selector in
  structure p. The memory allocated using this  routine is
  below the 640k limit and may be used for data-exchange with
  realmode-routines, interrupts and DMA-transfers.

  to get a valid protected mode pointer from a DPMI_PTR you
  have to use (void *) ptr.segment*16

    See also: ~DPMI_FreeDOSMem~
              ~DPMI_MAP_PHYSICAL~
              ~DPMI_UNMAP_PHYSICAL~
              ~VBE Structures~


:DPMI_FreeDOSMem
^DPMI_FreeDOSMem

% void DPMI_FreeDOSMem (DPMI_PTR *p);

  Free a allocated realmode memory block allocated with ~DPMI_AllocDOSMem~.

    See also: ~DPMI_MAP_PHYSICAL~
              ~DPMI_UNMAP_PHYSICAL~
              ~DPMI_AllocDOSMem~
              ~VBE Structures~

:DPMI_MAP_PHYSICAL
^DPMI_MAP_PHYSICAL

void * DPMI_MAP_PHYSICAL (void *p, long size);

 Create a physical mapping for the memory pointed at p with a
 size of size bytes. This is important if you want to map non
 memory adresses such as Linear Frame Buffers and other hardware
 into the DPMI address-range (the VESAVBE library will do this
 for you, but this routine is included for completeness.

    See also: ~DPMI_FreeDOSMem~
              ~DPMI_AllocDOSMem~
              ~DPMI_UNMAP_PHYSICAL~
              ~VBE Structures~

void DPMI_UNMAP_PHYSICAL (void *p);

 Destroys the physical mapping at pointer p. You have to pass
 a pointer that you got from ~DPMI_MAP_PHYSICAL~.

 The library takes care that it demaps its memory itself, so you
 don't have to take care about this if you only use the vesa-stuff.

    See also: ~DPMI_FreeDOSMem~
              ~DPMI_AllocDOSMem~
              ~DPMI_MAP_PHYSICAL~
              ~VBE Structures~

:VBE_Test
^VBE_Test

% int VBE_Test (void);

  Returns true if a VBE BIOS-extension version 2.0 or greater is available
  Returns zero otherwise

:VBE_Controller_Information
^VBE_Controller_Information

% void VBE_Controller_Information  (VBE_VbeInfoBlock * a);

  Request the VBE_vbeInfoBlock. Look into the VBE 2.0 Specs. for more
  information.

  This Infoblock contains some interesting informations about the
  installed graphic card. Please note, that all pointers will be
  translated into protected mode pointers, so you can directly use them.

  struct bcd16 {
    unsigned char lo;
    unsigned char hi;
  };

  struct VBE_VbeInfoBlock {
    unsigned long  vbeSignature;
    bcd16    vbeVersion;
    char *   OemStringPtr;
    unsigned long  Capabilities;
    unsigned short * VideoModePtr;
    unsigned short TotalMemory;
    unsigned short OemSoftwareRev;
    char *   OemVendorNamePtr;
    char *   OemProductNamePtr;
    char *   OemProductRevPtr;
    char     Reserved[222];
    char     OemData[256];
  };

  Bit-Definition of the ControllerInfo Capability fields

  #define CAP_8bit_DAC              1
  #define CAP_VGACompatible         2
  #define CAP_Use_VBE_DAC_Functions 4

:VBE_IsModeLinear
^VBE_IsModeLinear


% int  VBE_IsModeLinear (short Mode);

  Returns nonzero if specified mode supports a linear framebuffer.

  Use this after you found a mode using ~VBE_FindMode~ since the
  Mode-Find routine doesn't distinquish between banked and linear
  modes.

:VBE_SetBank
^VBE_SetBank

% void VBE_SetBank (short bnk);

  Sets the A-Window to the specified bank. 0xa0000 points to another
  location of the video memory. Be aware, that the bank is dependent
  of the granularity field in the ~VBE_ModeInfoBlock~.

  If you enable the support for the Protected Mode Extensions in the
  VESAVBE.H File the function will (if available) use the protected
  mode interface. However, I discoverd, that most VBE2.0  drivers
  are buggy in these functions.

:VBE_VideoMemory
^VBE_VideoMemory

% unsigned int VBE_VideoMemory (void);

  Return the amount of display memory available  (in bytes)

:VBE_Mode_Information
^VBE_Mode_Information

% void VBE_Mode_Information (short Mode, VBE_ModeInfoBlock  * a);

  Request the VBE_ModeInfoBlock for the specified mode. Look into the
  VBE 2.0 specs for more information.

  struct VBE_ModeInfoBlock {
    unsigned short ModeAttributes;
    char WinAAttributes;
    char WinBAttributes;
    unsigned short Granularity;
    unsigned short WinSize;
    unsigned short WinASegment;
    unsigned short WinBSegment;
    void *         WinFuncPtr;
    unsigned short BytesPerScanline;
    unsigned short XResolution;
    unsigned short YResolution;
    char XCharSize;
    char YCharSize;
    char NumberOfPlanes;
    char BitsPerPixel;
    char NumberOfBanks;
    char MemoryModel;
    char BankSize;
    char NumberOfImagePages;
    char Reserved;
    char RedMaskSize;
    char RedFieldPosition;
    char GreenMaskSize;
    char GreenFieldPosition;
    char BlueMaskSize;
    char BlueFieldPosition;
    char RsvdMaskSize;
    char RsvdFieldPosition;
    char DirectColorModeInfo;
    void * PhysBasePtr;
    void * OffScreenMemOffset;
    unsigned short OffScreenMemSize;
    char  reserved2[206];
  };

  Bit-Definition of the ModeInfo Attribute fields
  #define ATTR_HardwareMode         1
  #define ATTR_TTY_Support          2
  #define ATTR_ColorMode            4
  #define ATTR_GraphicsMode         8
  #define ATTR_No_VGA_Mode         16
  #define ATTR_No_SegA000          32
  #define ATTR_LFB_Support         64

  Bit-Definitions of the Window Attributes
  #define WATTR_Relocatable         1
  #define WATTR_Readable            2
  #define WATTR_Writeable           4

  Definitions of the MemoryModel Field
  #define MM_TextMode               0
  #define MM_CGA_Graphics           1
  #define MM_Hercules_Graphics      2
  #define MM_Planar                 3
  #define MM_PackedPixel            4
  #define MM_UnChained              5
  #define MM_DirectColor            6
  #define MM_YUV                    7

:VBE_FindMode
^VBE_FindMode

% int VBE_FindMode (int xres, int yres, char bpp);

  Search the modelist for the specified mode. bpp is BytesPerPixel
  (8 for 256 colors). Returns -1 if the mode isn't available.

  Afterwards you might have to check if the mode supports a linear
  framebuffer using ~VBE_IsModeLinear~.

:VBE_SetMode
^VBE_SetMode

% void VBE_SetMode (short Mode, int linear, int clear);

  Set VGA to the specified VBE-Mode. Use linear frame buffer if linear=1
  Clear the video-memory if clear=1.

:VBE_GetVideoPtr
^VBE_GetVideoPtr

% char * VBE_GetVideoPtr (int mode);

  Get the (mapped) pointer to the linear frame buffer for the specified
  mode. May fail on weired DPMI-Systems (tested: pmodew, dos4g, win95)

  This function will only work if the mode supports a linear frame buffer.
  you might use ~VBE_IsModeLinear~.

:VBE_SetDisplayStart
^VBE_SetDisplayStart

% void VBE_SetDisplayStart (short x, short y);

  Adjust the position of the logical upper left pixel.
  (for scrolling & page flipping)

  If you enable the support for the Protected Mode Extensions in the
  VESAVBE.H File the function will (if available) use the protected
  mode interface. However, I discoverd, that most VBE2.0  drivers
  are buggy in these functions.

:VBE_SetPixelsPerScanline
^VBE_SetPixelsPerScanline

% void VBE_SetPixelsPerScanline (short Pixels);

  Sets the number of pixels per scanline. Warning, not all VESA VBE
  implementations support this feature. However, it might be usefull
  if you have to deal with non linear frame buffers.

:VBE_MaxBytesPerScanline
^VBE_MaxBytesPerScanline

% short VBE_MaxBytesPerScanline (void);

  Returns the maxumum bytes per scanline. Unfortunately this function is
  more or less useless because most vesa implementations doesn't give valid
  results.

:VBE_SetDACWidth
^VBE_SetDACWidth

% void VBE_SetDACWidth (char bits);

  Sets the DAC into the 6 (default) or 8 bit color mode. You have to
  check first if the DAC supports 8 bit using the ~VBE_8BitDAC~ function.

:VBE_8BitDAC
^VBE_8BitDAC

% int VBE_8BitDAC (void);

  Returns non-zero, if the DAC can be switched into the 8-Bit mode.
  (only usefull in 256 color modes).

:Example Code
^Example Code

% This is a short example how to use the VESA VBE 2.0 library:

    #include "vesavbe.h"
    #include <math.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <conio.h>

    void error (char *msg)
    {
      printf ("Error: %s\n", msg);
      exit(1);
    }

    void Test_8Bit (void)
    {
      // Test 8-bit modes:
      int mode;
      VBE_ModeInfoBlock ModeInfo;
      int x;
      int y;
      char *VIDEO;

      mode = VBE_FindMode (640,480,8);
      if ( mode==-1 ) error( "640x480x8 not found");
      if ( !VBE_IsModeLinear(mode)) error ("Mode is not linear");

      // Set the video-mode
      VBE_SetMode (mode, 1, 1);
      // Get a pointer to the linear screen-memory
      VIDEO = VBE_GetVideoPtr (mode);

      // this should never occur if you test the linearity!
      if ( !VIDEO ) error ("LFB invalid");

      // We also need the ModeInformationBlock!

      VBE_Mode_Information (mode, &ModeInfo);


      for ( y=0; y<ModeInfo.YResolution; y++ )
      for ( x=0; x<ModeInfo.XResolution; x++ )
        VIDEO[ModeInfo.BytesPerScanline*y+x]=x^y;
    }

    void Test_16Bit (void)
    {
      int mode;
      int x, y, i;
      VBE_ModeInfoBlock ModeInfo;
      short rtab[256];
      short gtab[256];
      short btab[256];

      // Test 16-bit modes:
      mode = VBE_FindMode (320,240,16);
      if ( mode==-1 ) error( "640x480x16 not found");
      if ( !VBE_IsModeLinear(mode)) error ("Mode is not linear");

      // Set the video-mode
      VBE_SetMode (mode, 1, 1);
      // Get a pointer to the linear screen-memory
      short *VIDEO = (short *) VBE_GetVideoPtr (mode);

      // this should never occur if you test the linearity!
      if ( !VIDEO ) error ("LFB invalid");

      // We also need the ModeInformationBlock!

      VBE_Mode_Information (mode, &ModeInfo);

      // Calculate Pseudo Color Lookup-Tables
      for ( i=0; i<256; i++ ) {
        rtab[i]=(i>>(8-ModeInfo.RedMaskSize))<<ModeInfo.RedFieldPosition;
        gtab[i]=(i>>(8-ModeInfo.GreenMaskSize))<<ModeInfo.GreenFieldPosition;
        btab[i]=(i>>(8-ModeInfo.BlueMaskSize))<<ModeInfo.BlueFieldPosition;
      }

      for ( y=0; y<ModeInfo.YResolution; y++ )
      for ( x=0; x<ModeInfo.XResolution; x++ )
      {
        char r =(float)(127.0+127.0*sin((float)x/10.0));
        char g =(float)(127.0+127.0*sin((float)y/10.0));
        char b =(float)(127.0+127.0*cos((float)(x+y)/10.0));
        VIDEO[((ModeInfo.BytesPerScanline)/2*y+x)]=(rtab[r]|btab[b]|gtab[g]);
      }
      getch();

      // Set TextMode
      VBE_SetMode (3, 0, 1);
    }

    void main (void)
    {
      // VESA VBE 2.0 Interface test
      VBE_Init();

      Test_8Bit ();
      getch();
      Test_16Bit ();
      VBE_SetMode (3, 0, 1);
      VBE_Done();
    }





















