delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/05/16/14:34:39

From: Cory Bloyd <bloydcg AT cs DOT purdue DOT edu>
Newsgroups: comp.os.msdos.djgpp
Subject: Trying to find VESA mode numbers
Date: Fri, 16 May 1997 11:43:10 -0500
Organization: Dept of Computer Sciences, Purdue University
Lines: 120
Message-ID: <337C8E9E.1D80@cs.purdue.edu>
Reply-To: bloydcg AT cs DOT purdue DOT edu
NNTP-Posting-Host: govora.cs.purdue.edu
Mime-Version: 1.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

Call me stubborn, but I still insist on writing my own libraries even
though such wonders as Allegro exist.  And now I'm paying for it.
 I'm trying to create a run-of-the-mill VESA mode finding function to
match screen dimension requests with actual mode numbers.  
Unfortunately, the vbeInfo.VideoModePtr doesn't seem to be pointing
at anything resembling a list of video modes.
 I know that my vbeinfo structure is correct because I've checked it
against several reliable sources.  I'm pretty sure my VBE_detect()
function is correct because again it is taken from several sources and
it checks for the "VESA" Signature and always finds it.
 Below is the code I'm using.  Much of it is practically a direct rip
from Allegro.  Which is why I'm baffled that Allegro works on my system
but this doesn't.

Running setMode(anything,anything,anything) I get a list of completely
random hex numbers which by chance eventually contains a 0xffff to end
the program.

#define MASK_LINEAR(addr)     (addr & 0x000FFFFF)
#define RM_TO_LINEAR(addr)    ((((addr) & 0xFFFF0000) >> 12) + ((addr) &
0xFFFF))
#define RM_OFFSET(addr)       (MASK_LINEAR(addr) & 0xFFFF)
#define RM_SEGMENT(addr)      ((MASK_LINEAR(addr) & 0xFFFF0000) >> 4)

unsigned short FindMode(int x, int y, int bpp)
{
 extern VideoInfo vidInfo;
 VBE_ModeInfo *modeinfo;
 unsigned short mode;
 long modePtr;
 
 modePtr = RM_TO_LINEAR(vidInfo.vbeInfo.VideoModePtr);
 mode = _farpeekw(_dos_ds, modePtr);

 while(mode != 0xffff)
 {
  printf("\nMode: %x", mode);
  if (VBE_getmodeinfo(mode, modeinfo) != 0)
  {
   if (modeinfo->XResolution == x && modeinfo->YResolution == y 
    && modeinfo->BitsPerPixel == bpp) return mode;   
   printf(" XREZ: %u YREZ: %u BPP: %u", modeinfo->XResolution, 
    modeinfo->YResolution, modeinfo->BitsPerPixel);
  }
  modePtr += 2;
  mode = _farpeekw(_dos_ds, modePtr);
 }
 return 0;
}

int setMode(int x, int y, int bpp)
{
 extern VideoInfo vidInfo;

 if (!(VBE_detect(&vidInfo.vbeInfo)))
  {printf("Get VESA vga info failed.\n"); return(1);}

 if(!(vidInfo.mode = FindMode(x,y,bpp)))
  {printf("VESA mode not found.\n"); return(2);}
 if(VBE_Set_Mode(vidInfo.mode))
  {printf("VESA set mode failed.\n"); return(3);}

 if (!(VBE_getmodeinfo(vidInfo.mode, &vidInfo.modeInfo))) 
  {printf("Get VESA mode info failed.\n"); return(4);}
 if (!(vidInfo.modeInfo.ModeAttributes & 0x10))
  {printf("Linear frame buffer not supported for VESA mode.\n");
return(5);}
 if (!(vidInfo.page = (char *)VBE_get_linear_address(vidInfo.modeInfo,
vidInfo.vbeInfo)))
  {printf("VESA Address mapping failed.\n"); return(6); }
 
 vidInfo.bitsPerPixel = vidInfo.modeInfo.BitsPerPixel;
 vidInfo.bytesPerPixel = (vidInfo.bitsPerPixel+7)>>3; //fix if use 1 or
4 bit
 vidInfo.xrez = vidInfo.modeInfo.XResolution;
 vidInfo.yrez = vidInfo.modeInfo.YResolution;
 vidInfo.pageSize = vidInfo.bytesPerPixel * vidInfo.xrez * vidInfo.yrez;
 vidInfo.buffer = (char *)malloc(vidInfo.pageSize);

 //Get video selector
 vidInfo.selector = __dpmi_allocate_ldt_descriptors(1);

 return(0);
};


int VBE_detect(VBE_VbeInfo *vbeinfo) {
  __dpmi_regs regs;
  int c;

  for (c=0; c<sizeof(VBE_VbeInfo); c++)
      _farpokeb(_dos_ds, MASK_LINEAR(__tb)+c, 0);

  regs.x.ax = 0x4F00;
  regs.x.di = RM_OFFSET(__tb);
  regs.x.es = RM_SEGMENT(__tb);
  dosmemput(vbeinfo,sizeof(VBE_VbeInfo),__tb);
  __dpmi_int(0x10, &regs);
  if(regs.h.ah) return 0;
  dosmemget(MASK_LINEAR(__tb), sizeof(VBE_VbeInfo), vbeinfo);
  if(strncmp(vbeinfo->VESASignature,"VESA",4) != 0) return 0;
  else return vbeinfo->VESAVersion;
}

int VBE_getmodeinfo(unsigned short mode, VBE_ModeInfo *modeinfo) {
 __dpmi_regs regs;
 int c;
 
 for (c=0; c<sizeof(VBE_ModeInfo); c++)
      _farpokeb(_dos_ds, MASK_LINEAR(__tb)+c, 0);

  regs.x.ax = 0x4F01;
  regs.x.cx = mode;
  regs.x.di = RM_OFFSET(__tb);
  regs.x.es = RM_SEGMENT(__tb);
  __dpmi_int(0x10, &regs);
  if(regs.h.ah) return 0;
  dosmemget(MASK_LINEAR(__tb), sizeof(VBE_ModeInfo), modeinfo);
  return 1;
}

- Raw text -


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