Listing 1: VBE wrapper functions
#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 */