#include <string.h>
#include <dos.h>
#include "vbe.h" /* exports and data types */
/*------------------ local data -------------------*/
static VbeInfo_t _VbeInfo;
static ModeInfo_t _ModeInfo;
static int _Width; /* scan line width in bytes */
static long _Window; /* memory window size in bytes */
static int _Segment; /* mem window segment */
/*--------------- exported functions ---------------*/
int VbeGetVbeInfo(VbeInfo_t far *p)
/* fetches the vbe info block; returns 0 if no vbe. */
{
union REGS r={0x4f00,0,0,0,0,FP_OFF(p)};
struct SREGS s={FP_SEG(p)};
if(!p) return 0;
_fmemset(p,0,sizeof(VbeInfo_t));
_fmemcpy(p->VbeSignature,"VBE2",4);
int86x(0x10,&r,&r,&s);
if(_fmemcmp(p->VbeSignature,"VESA",4)) return 0;
return r.x.ax==0x4f;
}
int VbeGetModeInfo(int mode,ModeInfo_t far *p)
/* fetches the mode info block for the specified mode
number; returns 0 if mode unsupported by vbe. */
{
union REGS r={0x4f01,0,mode,0,0,FP_OFF(p)};
struct SREGS s={FP_SEG(p)};
if(!p) return 0;
_fmemset(p,0,sizeof(ModeInfo_t));
int86x(0x10,&r,&r,&s);
return r.x.ax==0x4f;
}
int VbeSetMode(int mode)
/* initializes the requested video mode; returns 0 if
there's no vbe or the mode is unavailable. */
{
union REGS r={0x4f02,mode};
if(!VbeGetVbeInfo(&_VbeInfo)) return 0;
if(mode>=0x100) /* svga mode */
{
if(!VbeGetModeInfo(mode,&_ModeInfo) ||
!(_ModeInfo.ModeAttributes&1)) return 0;
_Width=_ModeInfo.BytesPerScanLine;
_Window=1024L*_ModeInfo.WinSize; /* convert to bytes */
_Segment=_ModeInfo.WinASegment;
}
int86(0x10,&r,&r);
return r.x.ax==0x4f;
}
void VbeSetPalette(const char far *p,int start,int n)
/* loads the dac palette registers; uses bios on vbe
versions before 2.0 */
{
if(_VbeInfo.VbeVersion<0x200) /* use bios */
{
union REGS r={0x1012,start,n,FP_OFF(p)};
struct SREGS s={FP_SEG(p)};
int86x(0x10,&r,&r,&s);
}
else /* use vbe */
{
union REGS r={0x4f09,0,n,start,0,FP_OFF(p)};
struct SREGS s={FP_SEG(p)};
int86x(0x10,&r,&r,&s);
}
}
void VbeSetWindow(int window,int position)
/* repositions the indicates memory window to the new
position (in WinGranularity units). */
{
union REGS r={0x4f05,window,0,position};
int86(0x10,&r,&r);
}
void VbeWrite(int x,int y,int bytes,const char far *buffer)
/* copies the contents of the buffer (<64k) to display,
starting at pixel (x,y). */
{
long absolute=x+(long)y*_Width; /* absolute offset */
long position=absolute/_Window; /* of window */
long offset=absolute%_Window; /* of window */
char far *vram=MK_FP(_Segment,0); /* to window */
VbeSetWindow(0,(int)position);
if(offset+bytes>_Window) /* data overruns window */
{
int n=(int)(_Window-offset); /* bytes left */
_fmemcpy(vram+offset,buffer,n); /* display 1st part */
VbeSetWindow(0,(int)++position); /* move window */
_fmemcpy(vram,buffer+n,bytes-n); /* display rest */
}
else _fmemcpy(vram+offset,buffer,bytes);/* no overrun */
}
/* End of File */