delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2002/10/25/11:15:25

From: trapforcannedmeatproduct AT hotmail DOT com (R. Charles Henry)
Newsgroups: comp.os.msdos.djgpp
Subject: Trying to use VESA under Windows XP
Date: 25 Oct 2002 08:06:45 -0700
Organization: http://groups.google.com/
Lines: 468
Message-ID: <8ed56b42.0210250706.4d2222c6@posting.google.com>
NNTP-Posting-Host: 194.164.77.251
X-Trace: posting.google.com 1035558405 6944 127.0.0.1 (25 Oct 2002 15:06:45 GMT)
X-Complaints-To: groups-abuse AT google DOT com
NNTP-Posting-Date: 25 Oct 2002 15:06:45 GMT
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

Having a bit of trouble trying to use VESA under Windows XP.

I've compiled the code below which is mainly taken from:

"Guide: VESA graphics modes"
http://www.delorie.com/djgpp/doc/ug/graphics/vesa.html

using DJGPP v2.03

The executable produced  runs fine on Win 95 (not tried 98), 
showing a uniform field of random pixels across the whole display.

On XP, however, the display becomes garbled, the pixel fields 
split into several bands at 640 x 480, higher modes do nothing.
(Monitor flashes up an 'invalid signal' warning at 1024 x 768).

Does anyone have any tips? I don't have a lot of experience with 
C or DJGPP and am a little puzzled.

I appreciate any help that might be forthcoming.

Here's my code, which I was using to try and figure things out..


/* assembled from "Guide: VESA graphics modes" at:  */
/* http://www.delorie.com/djgpp/doc/ug/graphics/vesa.html */










#include <stdio.h>
#include <dos.h>
#include <math.h>
#include <pc.h>
#include <keys.h>
#include <sys/farptr.h>
#include <go32.h>
#include <dpmi.h>
#define SCREEN_WIDTH        640
#define SCREEN_HEIGHT       480
#define NUM_COLORS          256

int i;
int x;
int y;
int color;

/* make sure that a VESA driver is present, and retrieve a copy of the
VESA information structure */

   typedef struct VESA_INFO
   { 
      unsigned char  VESASignature[4]     __attribute__ ((packed));
      unsigned short VESAVersion          __attribute__ ((packed));
      unsigned long  OEMStringPtr         __attribute__ ((packed));
      unsigned char  Capabilities[4]      __attribute__ ((packed));
      unsigned long  VideoModePtr         __attribute__ ((packed));
      unsigned short TotalMemory          __attribute__ ((packed));
      unsigned short OemSoftwareRev       __attribute__ ((packed));
      unsigned long  OemVendorNamePtr     __attribute__ ((packed));
      unsigned long  OemProductNamePtr    __attribute__ ((packed));
      unsigned long  OemProductRevPtr     __attribute__ ((packed));
      unsigned char  Reserved[222]        __attribute__ ((packed));
      unsigned char  OemData[256]         __attribute__ ((packed));
   } VESA_INFO;



/* call VESA function 0x4F00 to fill it with information about the
current driver. */
/*Because VESA was designed as a real mode API for use by 16 bit
programs, */
/*this data must be transferred via a buffer in conventional memory
with the */
/*dosmemput() and dosmemget() functions: see the DPMI chapter for
details of this. */
/*The function below will copy the VESA driver information into a
global VESA_INFO */
/*structure, returning zero on success or -1 if anything goes wrong
(ie. no driver is available). */



 VESA_INFO vesa_info;


   int get_vesa_info()
   {
      __dpmi_regs r;
      long dosbuf;
      int c;

      /* use the conventional memory transfer buffer */
      dosbuf = __tb & 0xFFFFF;

      /* initialize the buffer to zero */
      for (c=0; c<sizeof(VESA_INFO); c++)
	 _farpokeb(_dos_ds, dosbuf+c, 0);

      dosmemput("VBE2", 4, dosbuf);

      /* call the VESA function */
      r.x.ax = 0x4F00;
      r.x.di = dosbuf & 0xF;
      r.x.es = (dosbuf>>4) & 0xFFFF;
      __dpmi_int(0x10, &r);

      /* quit if there was an error */
      if (r.h.ah)
	 return -1;

      /* copy the resulting data into our structure */
      dosmemget(dosbuf, sizeof(VESA_INFO), &vesa_info);

      /* check that we got the right magic marker value */
      if (strncmp(vesa_info.VESASignature, "VESA", 4) != 0)
	 return -1;

      /* it worked! */
      return 0;
   }










/*Information about a particular mode can be obtained in a similar way
to the main VESA information block,
 but using function 0x4F01 with a different structure, eg: */

   typedef struct MODE_INFO
   {
      unsigned short ModeAttributes       __attribute__ ((packed));
      unsigned char  WinAAttributes       __attribute__ ((packed));
      unsigned char  WinBAttributes       __attribute__ ((packed));
      unsigned short WinGranularity       __attribute__ ((packed));
      unsigned short WinSize              __attribute__ ((packed));
      unsigned short WinASegment          __attribute__ ((packed));
      unsigned short WinBSegment          __attribute__ ((packed));
      unsigned long  WinFuncPtr           __attribute__ ((packed));
      unsigned short BytesPerScanLine     __attribute__ ((packed));
      unsigned short XResolution          __attribute__ ((packed));
      unsigned short YResolution          __attribute__ ((packed));
      unsigned char  XCharSize            __attribute__ ((packed));
      unsigned char  YCharSize            __attribute__ ((packed));
      unsigned char  NumberOfPlanes       __attribute__ ((packed));
      unsigned char  BitsPerPixel         __attribute__ ((packed));
      unsigned char  NumberOfBanks        __attribute__ ((packed));
      unsigned char  MemoryModel          __attribute__ ((packed));
      unsigned char  BankSize             __attribute__ ((packed));
      unsigned char  NumberOfImagePages   __attribute__ ((packed));
      unsigned char  Reserved_page        __attribute__ ((packed));
      unsigned char  RedMaskSize          __attribute__ ((packed));
      unsigned char  RedMaskPos           __attribute__ ((packed));
      unsigned char  GreenMaskSize        __attribute__ ((packed));
      unsigned char  GreenMaskPos         __attribute__ ((packed));
      unsigned char  BlueMaskSize         __attribute__ ((packed));
      unsigned char  BlueMaskPos          __attribute__ ((packed));
      unsigned char  ReservedMaskSize     __attribute__ ((packed));
      unsigned char  ReservedMaskPos      __attribute__ ((packed));
      unsigned char  DirectColorModeInfo  __attribute__ ((packed));
      unsigned long  PhysBasePtr          __attribute__ ((packed));
      unsigned long  OffScreenMemOffset   __attribute__ ((packed));
      unsigned short OffScreenMemSize     __attribute__ ((packed));
      unsigned char  Reserved[206]        __attribute__ ((packed));
   } MODE_INFO;


   MODE_INFO mode_info;


   int get_mode_info(int mode)
   {
      __dpmi_regs r;
      long dosbuf;
      int c;

      /* use the conventional memory transfer buffer */
      dosbuf = __tb & 0xFFFFF;

      /* initialize the buffer to zero */
      for (c=0; c<sizeof(MODE_INFO); c++)
	 _farpokeb(_dos_ds, dosbuf+c, 0);

      /* call the VESA function */
      r.x.ax = 0x4F01;
      r.x.di = dosbuf & 0xF;
      r.x.es = (dosbuf>>4) & 0xFFFF;
      r.x.cx = mode;
      __dpmi_int(0x10, &r);

      /* quit if there was an error */
      if (r.h.ah)
	 return -1;

      /* copy the resulting data into our structure */
      dosmemget(dosbuf, sizeof(MODE_INFO), &mode_info);

      /* it worked! */
      return 0;
   }

















/*
information can easily be obtained from the main VESA information
block.
This contains a list of all the possible modes that are supported by
the driver,
so you can write a little routine that will loop through all these
modes,
retrieving information about each one in turn until it finds the one
that
you are looking for. For example:
*/







   int find_vesa_mode(int w, int h)
   {
      int mode_list[256];
      int number_of_modes;
      long mode_ptr;
      int c;

      /* check that the VESA driver exists, and get information about
it */
      if (get_vesa_info() != 0)
	 return 0;

      /* convert the mode list pointer from seg:offset to a linear
address */
      mode_ptr = ((vesa_info.VideoModePtr & 0xFFFF0000) >> 12) + 
		  (vesa_info.VideoModePtr & 0xFFFF);

      number_of_modes = 0;

      /* read the list of available modes */
      while (_farpeekw(_dos_ds, mode_ptr) != 0xFFFF) {
	 mode_list[number_of_modes] = _farpeekw(_dos_ds, mode_ptr);
	 number_of_modes++;
	 mode_ptr += 2;
      }

      /* scan through the list of modes looking for the one that we
want */
      for (c=0; c<number_of_modes; c++) {

	 /* get information about this mode */
	 if (get_mode_info(mode_list[c]) != 0)
	    continue;

	 /* check the flags field to make sure this is a color graphics mode,
	  * and that it is supported by the current hardware */
	 if ((mode_info.ModeAttributes & 0x19) != 0x19)
	    continue;

	 /* check that this mode is the right size */
	 if ((mode_info.XResolution != w) || (mode_info.YResolution != h))
	    continue;

	 /* check that there is only one color plane */
	 if (mode_info.NumberOfPlanes != 1)
	    continue;

	 /* check that it is a packed-pixel mode (other values are used for
	  * different memory layouts, eg. 6 for a truecolor resolution) */
	 if (mode_info.MemoryModel != 4)
	    continue;

	 /* check that this is an 8-bit (256 color) mode */
	 if (mode_info.BitsPerPixel != 8)
	    continue;

	 /* if it passed all those checks, this must be the mode we want! */
	 return mode_list[c];
      }

      /* oh dear, there was no mode matching the one we wanted! */
      return 0; 
   }











/* ready to actually select a VESA graphics mode and start
drawing things onto the screen. This is done by calling function
0x4F02 with a
mode number in the BX register, eg: */


   int set_vesa_mode(int w, int h)
   {
      __dpmi_regs r;
      int mode_number;

      /* find the number for this mode */
      mode_number = find_vesa_mode(w, h);
      if (!mode_number)
	 return -1;

      /* call the VESA mode set function */
      r.x.ax = 0x4F02;
      r.x.bx = mode_number;
      __dpmi_int(0x10, &r);
      if (r.h.ah)
	 return -1;

      /* it worked! */
      return 0;
   }









/* The SVGA video memory is located at physical address 0xA0000, the
same as in mode 13h,
but there is one small problem with this: there simply isn't enough
room for it all
to fit there! The original DOS memory map only included space for 64k
of video memory
between 0xA0000 and 0xB0000, which is fine for a 320x200 resolution
but nowhere near
enough for a 640x480 screen (that takes up 300k of framebuffer space,
and higher
resolutions need even more). The SVGA hardware designers solved this
problem by
using a banked memory architecture, where the 64k VGA memory region is
treated as
a sliding window onto the larger expanse of real video memory inside
your card.
To access an arbitrary location on the SVGA screen you must first call
VESA function
0x4F05 to tell it which bank you want to use, and then write to a
memory location
within that bank. You can set the bank with the function: */





   void set_vesa_bank(int bank_number)
   {
      __dpmi_regs r;

      r.x.ax = 0x4F05;
      r.x.bx = 0;
      r.x.dx = bank_number;
      __dpmi_int(0x10, &r);
   }

/* Using this, a simple putpixel function can be implemented as: */

   void putpixel_vesa_640x480(int x, int y, int color)
   {
      int address = y*640+x;
      int bank_size = mode_info.WinGranularity*640;
      int bank_number = address/bank_size;
      int bank_offset = address%bank_size;

      set_vesa_bank(bank_number);

      _farpokeb(_dos_ds, 0xA0000+bank_offset, color);
   }













main()
{
printf("Test routine for figuring out VESA graphics in Win 9x/XP, 640
by 480 res and up.\n");
printf("Compiling using DJGPP v2.03\n");
printf("\nPress a key to begin.\n\n");
getkey();
if (get_vesa_info() == -1)
   {
   printf("\nFailed to get VESA info.\nPress a key to exit.\n");
   getkey();
   exit(-1);
   }
   else
   {
   if (get_vesa_info() == 0)
      {
      printf("\nFound VESA info.\nPress a key to continue.\n");
      getkey();
      if (find_vesa_mode(640, 480) != 0)
         {
         printf("\nFound 640 by 480 mode.\nPress a key for
demo...\n");
         printf("\nYou should see a uniform field of pixels, and an
exit text message.\n");
         printf("\nIf no exit message appears, just hit any key to get
out....\n");
         getkey();
         set_vesa_mode(640, 480);
         for(i=0;i<10000;i++)
            {
            x=rand()%SCREEN_HEIGHT;
            y=rand()%SCREEN_WIDTH;
            color=rand()%NUM_COLORS;
            putpixel_vesa_640x480(x,y,color);
            }
         printf("\nOK. Press a key to exit\n");
         getkey();
         exit(-1);
         }
         else
         {
         printf("\nFailed to find 640 by 480 mode.\nPress a key to
exit.\n");
         getkey();
         exit(-1);
         }
      }
   }
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019