www.pudn.com > BUILD Engine 08012001.zip > ves2.h


// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
// This file has been modified from Ken Silverman's original release

#ifndef _INCLUDE_VES2_H_
#define _INCLUDE_VES2_H_

#if (!defined PLATFORM_DOS)
#error Do not include this file. It is for the DOS target only.
#endif

#include 
#include 
#include 
#include 
#include 

#include "build.h"
#include "pragmas.h"

#pragma pack(push,1);

typedef struct
{
	char VESASignature[4];
	short VESAVersion;
	long OemStringPtr, Capabilities, VideoModePtr;
	short TotalMemory, OemSoftwareRev;
	long OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr;
	char reserved[222], OemDATA[256];
} VBE_vgaInfo;

typedef struct
{
	short ModeAttributes;
	char WinAAtributes, WinBAttributes;
	short WinGranularity, WinSize, WinASegment, WinBSegment;
	long WinFuncPtr;
	short BytesPerScanLine, XResolution, YResolution;
	char XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel;
	char NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages;
	char res1;
	char RedMaskSize, RedFieldPosition;
	char GreenMaskSize, GreenFieldPosition;
	char BlueMaskSize, BlueFieldPosition;
	char RsvdMaskSize, RsvdFieldPosition, DirectColorModeInfo;
	long PhysBasePtr, OffScreenMemOffset;
	short OffScreenMemSize;
	char res2[206];
} VBE_modeInfo;

struct _RMWORDREGS { unsigned short ax, bx, cx, dx, si, di, cflag; };
struct _RMBYTEREGS { unsigned char al, ah, bl, bh, cl, ch, dl, dh; };
typedef union { struct _RMWORDREGS x; struct _RMBYTEREGS h; } RMREGS;
typedef struct { unsigned short es, cs, ss, ds; } RMSREGS;

typedef struct
{
	long edi, esi, ebp, reserved, ebx, edx, ecx, eax;
	short flags, es, ds, fs, gs, ip, cs, sp, ss;
} _RMREGS;

#pragma pack(pop);

long VESABuf_sel = 0, VESABuf_rseg;
short modelist[256];
char *screen = NULL, vesachecked = 0;
long xres, yres, bytesperline, frameplace, imageSize, maxpages;
long buffermode, origbuffermode, linearmode;
long setactiveentry = 0, setvisualentry = 0, setpaletteentry = 0;
char permanentupdate = 0, vgacompatible;
short visualpagelookup[64][2];
long activepagelookup[64];
static long ves2lastx[MAXYDIM];
static long davesapageshift;
static VBE_vgaInfo vgaInfo;
long globlinplace;
static long backlinaddress = 0;  //Save address for free operation (0x801)

void faketimerhandler(void);

void qlimitrate(void);
#pragma aux qlimitrate =\
	"mov dx, 0x3da",\
	"wait1: in al, dx",\
	"test al, 1",\
	"jnz wait1",\
	modify exact [eax edx]\

void backupsegs(void);
short ods, oes, oss;
#pragma aux backupsegs =\
	"mov ods, ds",\
	"mov oes, es",\
	"mov oss, ss",\
	modify [eax]\

void restoresegs(void);
#pragma aux restoresegs =\
	"mov ds, ods",\
	"mov es, oes",\
	"mov ss, oss",\
	modify [eax]\

/*   //64-bit copybufbyte
#pragma aux copybufbyte =\
	"cmp ecx, 8",\
	"jae longcopy",\
	"test cl, 1",\
	"jz shortskip1",\
	"movsb",\
	"shortskip1: shr ecx, 2",\
	"jnc shortskip2",\
	"movsw",\
	"shortskip2: rep movsd",\
	"jmp endit",\
	"longcopy: test edi, 1",\
	"jz skip1",\
	"movsb",\
	"dec ecx",\
	"skip1: test edi, 2",\
	"jz skip2",\
	"movsw",\
	"sub ecx, 2",\
	"skip2: test edi, 4",\
	"jz skip3",\
	"movsd",\
	"sub ecx, 4",\
	"skip3: mov ebx, ecx",\
	"shr ecx, 3",\
	"jz skip4",\
	"begloop: fld qword ptr [esi]",\
	"fstp qword ptr [edi]",\
	"add esi, 8",\
	"add edi, 8",\
	"dec ecx",\
	"jnz begloop",\
	"skip4: test bl, 4",\
	"jz skip5",\
	"movsd",\
	"skip5: test bl, 2",\
	"jz skip6",\
	"movsw",\
	"skip6: test bl, 1",\
	"jz endit",\
	"movsb",\
	"endit:",\
	parm [esi][edi][ecx]\
	modify [ebx]\
*/


void vesasetactive(long i1, long i2, long i3, long i4);
#pragma aux vesasetactive =\
	"call dword ptr [setactiveentry]",\
	parm [eax][ebx][ecx][edx]\

void vesasetvisual(long i1, long i2, long i3, long i4);
#pragma aux vesasetvisual =\
	"call dword ptr [setvisualentry]",\
	parm [eax][ebx][ecx][edx]\

long vesasetpalette(long i1, long i2, long i3, long i4, long i5, char *i6);
#pragma aux vesasetpalette =\
	"call dword ptr [setpaletteentry]",\
	parm [eax][ebx][ecx][edx][esi][edi]\

long DPMI_int86(long intno, RMREGS *in, RMREGS *out)
{
	_RMREGS rmregs;
	union REGS r;
	struct SREGS sr;

	memset(&rmregs,0,sizeof(rmregs));
	rmregs.eax = in->x.ax; rmregs.ebx = in->x.bx;
	rmregs.ecx = in->x.cx; rmregs.edx = in->x.dx;
	rmregs.esi = in->x.si; rmregs.edi = in->x.di;

	segread(&sr);
	r.w.ax = 0x300; r.h.bl = intno; r.h.bh = 0; r.w.cx = 0; sr.es = sr.ds;
	r.x.edi = (unsigned)&rmregs;
	backupsegs(); int386x(0x31,&r,&r,&sr); restoresegs();

	out->x.ax = rmregs.eax; out->x.bx = rmregs.ebx;
	out->x.cx = rmregs.ecx; out->x.dx = rmregs.edx;
	out->x.si = rmregs.esi; out->x.di = rmregs.edi;
	out->x.cflag = rmregs.flags&1;
	return(out->x.ax);
}

long DPMI_int86x(long intno, RMREGS *in, RMREGS *out, RMSREGS *sregs)
{
	_RMREGS rmregs;
	union REGS r;
	struct SREGS sr;

	memset(&rmregs, 0, sizeof(rmregs));
	rmregs.eax = in->x.ax; rmregs.ebx = in->x.bx;
	rmregs.ecx = in->x.cx; rmregs.edx = in->x.dx;
	rmregs.esi = in->x.si; rmregs.edi = in->x.di;
	rmregs.es = sregs->es;
	rmregs.ds = sregs->ds;

	segread(&sr);
	r.w.ax = 0x300; r.h.bl = intno; r.h.bh = 0; r.w.cx = 0; sr.es = sr.ds;
	r.x.edi = (unsigned)&rmregs;
	backupsegs(); int386x(0x31,&r,&r,&sr); restoresegs();

	out->x.ax = rmregs.eax; out->x.bx = rmregs.ebx;
	out->x.cx = rmregs.ecx; out->x.dx = rmregs.edx;
	out->x.si = rmregs.esi; out->x.di = rmregs.edi;
	sregs->es = rmregs.es; sregs->cs = rmregs.cs;
	sregs->ss = rmregs.ss; sregs->ds = rmregs.ds;
	out->x.cflag = rmregs.flags&1;
	return(out->x.ax);
}

static void ExitVBEBuf(void)
{
	union REGS r;
	r.w.ax = 0x101; r.w.dx = VESABuf_sel; //DPMI free real seg
	backupsegs(); int386(0x31,&r,&r); restoresegs();
}

void VBE_callESDI(RMREGS *regs, void *buffer, long size)
{
	RMSREGS sregs;
	union REGS r;

	if (!VESABuf_sel)  //Init Real mode buffer
	{
		r.w.ax = 0x100; r.w.bx = 1024>>4;
		backupsegs(); int386(0x31,&r,&r); restoresegs();
		if (r.w.cflag) { printf("DPMI_allocRealSeg failed!\n"); exit(0); }
		VESABuf_sel = r.w.dx;
		VESABuf_rseg = r.w.ax;
		atexit(ExitVBEBuf);
	}
	sregs.es = VESABuf_rseg;
	regs->x.di = 0;
	_fmemcpy(MK_FP(VESABuf_sel,0),buffer,size);
	DPMI_int86x(0x10,regs,regs,&sregs);
	_fmemcpy(buffer,MK_FP(VESABuf_sel,0),size);
}

long VBE_getModeInfo(long mode, VBE_modeInfo *modeInfo)
{
	RMREGS regs;

	regs.x.ax = 0x4f01;
	regs.x.cx = mode;
	VBE_callESDI(®s, modeInfo, sizeof(VBE_modeInfo));
	if (regs.x.ax != 0x004f) return(0);
	if ((modeInfo->ModeAttributes&1) == 0) return(0); //1 is vbeMdAvailable
	return(1);
}

GetPtrToLFB(long physAddr)
{
	#define LIMIT (4096*1024)-1
	long sel;
	union REGS r;

	r.w.ax = 0; r.w.cx = 1;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_allocSelector() failed!\n"); exit(0); }
	sel = r.w.ax;
	r.w.ax = 9; r.w.bx = sel; r.w.cx = 0x8092;
	backupsegs(); int386(0x31,&r,&r); restoresegs();

	r.w.ax = 0x800; r.w.bx = physAddr >> 16; r.w.cx = physAddr & 0xffff;
	r.w.si = LIMIT>>16; r.w.di = LIMIT&0xffff;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_mapPhysicalToLinear() failed!\n"); exit(0); }
	backlinaddress = globlinplace = ((long)r.w.bx<<16)+r.w.cx;

	r.w.ax = 7; r.w.bx = sel;
	r.w.cx = globlinplace>>16; r.w.dx = globlinplace&0xffff;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_setSelectorBase() failed!\n"); exit(0); }

	r.w.ax = 8; r.w.bx = sel;
	r.w.cx = LIMIT>>16; r.w.dx = LIMIT&0xffff;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_setSelectorLimit() failed!\n"); exit(0); }
}

void getvalidvesamodes(void)
{
	long i, j, k;
	short *p, *p2;
	VBE_modeInfo modeInfo;
	RMREGS regs;

	if (vesachecked) return;
	vesachecked = 1;

	validmodecnt = 0;
	modelist[0] = -1;

	strncpy(vgaInfo.VESASignature,"VBE2",4);
	regs.x.ax = 0x4f00;
	VBE_callESDI(®s,&vgaInfo,sizeof(VBE_vgaInfo));
	if ((regs.x.ax != 0x004f) || (strncmp(vgaInfo.VESASignature,"VESA",4)))
		return;

	//if (vgaInfo.VESAVersion < 0x200) return;

		//LfbMapRealPointer
	p = (short *)(((vgaInfo.VideoModePtr&0xffff0000)>>12)+((vgaInfo.VideoModePtr)&0xffff));
	p2 = modelist;
	while (*p != -1) *p2++ = *p++;
	*p2 = -1;

	for(p=modelist;*p!=-1;p++)
	{
		regs.x.ax = 0x4f01; regs.x.cx = *p;
		VBE_callESDI(®s,&modeInfo,sizeof(VBE_modeInfo));
		if (regs.x.ax != 0x004f) continue;
		if (!(modeInfo.ModeAttributes&1)) continue; //1 is vbeMdAvailable
		if (modeInfo.MemoryModel != 4) continue;    //4 is vbeMemPK
		if (modeInfo.BitsPerPixel != 8) continue;
		if (modeInfo.NumberOfPlanes != 1) continue;

		validmode[validmodecnt] = *p;
		validmodexdim[validmodecnt] = modeInfo.XResolution;
		validmodeydim[validmodecnt] = modeInfo.YResolution;
		validmodecnt++;
	}

	for(i=1;i= 2))
			{
				buffermode = 0;
				imageSize = 65536;
				frameplace = 0xa0000;
			}
			else
			{
				buffermode = 1;
				imageSize = bytesperline*yres;
				frameplace = FP_OFF(screen);
				maxpages = 1;
			}
		}

		origbuffermode = buffermode;

		j = 0;
		for(i=0;i= y2)
						{
							while (y1 < y2-1)
							{
								y1++; if ((y1&31) == 0) faketimerhandler();
									//x,y1
								i = p+ylookup[y1]+ves2lastx[y1];
								copybufbyte((void *)i,(void *)(i+delta),x-ves2lastx[y1]);
							}
							y1 = ny1;
						}
						else
						{
							while (y1 < ny1)
							{
								y1++; if ((y1&31) == 0) faketimerhandler();
									//x-1,y1
								i = p+ylookup[y1]+ves2lastx[y1];
								copybufbyte((void *)i,(void *)(i+delta),x-ves2lastx[y1]);
							}
							while (y1 > ny1) ves2lastx[y1--] = x;
						}
						while (y2 > ny2)
						{
							y2--; if ((y2&31) == 0) faketimerhandler();
								//x-1,y2
							i = p+ylookup[y2]+ves2lastx[y2];
							copybufbyte((void *)i,(void *)(i+delta),x-ves2lastx[y2]);
						}
						while (y2 < ny2) ves2lastx[y2++] = x;
					}
					else
					{
						while (y1 < y2-1)
						{
							y1++; if ((y1&31) == 0) faketimerhandler();
								//x-1,y1
							i = p+ylookup[y1]+ves2lastx[y1];
							copybufbyte((void *)i,(void *)(i+delta),x-ves2lastx[y1]);
						}
						if (x == cx2) break;
						y1 = startumost[x+1]; y2 = y1;
					}
				}
				while (y1 < y2-1)
				{
					y1++; if ((y1&31) == 0) faketimerhandler();
						//cx2+1,y1
					i = p+ylookup[y1]+ves2lastx[y1];
					copybufbyte((void *)i,(void *)(i+delta),cx2+1-ves2lastx[y1]);
				}
			}
			else
			{
				p += ylookup[cy1]+cx1;
				delta = activepagelookup[dapagenum&0x7fffffff]-FP_OFF(screen);
				for(y=cy1;y<=cy2;y++)
				{
					copybufbyte((void *)p,(void *)(p+delta),dx);
					p += ylookup[1];
					if ((y&31) == 0) faketimerhandler();
				}
			}
		}
		else
		{
			p = ylookup[cy1]+cx1;
			for(y=cy1;y<=cy2;y++)
			{
				if ((p>>16) != curpag)
				{
					curpag = (p>>16);

					setvesapage(curpag<>16);
					setvesapage(curpag<= 0) qlimitrate();
				vesasetvisual(0x4f07,0L,i>>2,i>>18);
			}
			else
				{ vesasetvisual(0x4f07,0x80,i>>2,i>>18); }

		}
		else
		{
			regs.x.ax = 0x4f07;
			regs.x.cx = visualpagelookup[dapagenum&0x7fffffff][0]; //X-coordinate
			regs.x.dx = visualpagelookup[dapagenum&0x7fffffff][1]; //Y-coordinate
			if (vgacompatible)
			{
				regs.x.bx = 0;
				if (dapagenum >= 0) qlimitrate();
				DPMI_int86(0x10,®s,®s);
			}
			else
				{ regs.x.bx = 0x80; DPMI_int86(0x10,®s,®s); }
		}
		if (dapagenum >= 0) faketimerhandler();
	}
}

void uninitvesa(void)
{
	if (backlinaddress)
	{
		union REGS r;
		r.w.ax = 0x801;
		r.w.bx = (backlinaddress >> 16);
		r.w.cx = (backlinaddress & 0xffff);
		backupsegs(); int386(0x31,&r,&r); restoresegs();
		if (r.x.cflag) { printf("Free Physical Address failed!\n"); }
		backlinaddress = 0;
	}
	VESABuf_sel = 0;
	vesachecked = 0;
}

#if 0  // doesn't appear to be used anymore. --ryan.
#pragma aux setpalettequick =\
	"mov edx, 0x3c8",\
	"out dx, al",\
	"inc edx",\
	"lea ecx, [ecx+ecx*2]",\
	"cld",\
	"rep outsb",\
	parm [eax][ecx][esi]\
	modify exact [ecx edx esi]
#endif

int VBE_setPalette(long start, long num, char *dapal)
{
	RMREGS regs;
	long i, j, k;
	char palquick[768];

	if (stereomode == 1)
	{
		if ((unsigned)((blackband&255)-start) < (unsigned)num)
		{
			dapal[(((blackband&255)-start)<<2)+0] = 0;
			dapal[(((blackband&255)-start)<<2)+1] = 0;
			dapal[(((blackband&255)-start)<<2)+2] = 0;
		}
		if ((unsigned)((whiteband&255)-start) < (unsigned)num)
		{
			dapal[(((whiteband&255)-start)<<2)+0] = 255;
			dapal[(((whiteband&255)-start)<<2)+1] = 255;
			dapal[(((whiteband&255)-start)<<2)+2] = 255;
		}
	}
	if ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
	{
		j = 0; k = (start<<2);
		for(i=0;i>1);i>0;i--)
		{
			koutp(0x3c9,(long) dapal[2]);
			while (kinp(0x3da)&1); while (!(kinp(0x3da)&1));
										  koutp(0x3c9,(long) dapal[1]); koutp(0x3c9,(long) dapal[0]);
			koutp(0x3c9,(long) dapal[6]); koutp(0x3c9,(long) dapal[5]); koutp(0x3c9,(long) dapal[4]);
			dapal += 8;
		}
		if (num&1)
		{
			koutp(0x3c9,(long) dapal[2]);
			while (kinp(0x3da)&1); while (!(kinp(0x3da)&1));
										  koutp(0x3c9,(long) dapal[1]); koutp(0x3c9,(long) dapal[0]);
		}
		return(1);
	}

	if (setpaletteentry)
	{
		i = (vesasetpalette(0x4f09,(vgaInfo.Capabilities&4)<<5,
								  num,start,0L,dapal)&65535);
	}
	else
	{
		regs.x.ax = 0x4f09; regs.h.bl = ((vgaInfo.Capabilities&4)<<5);
		regs.x.cx = num; regs.x.dx = start;
		VBE_callESDI(®s,dapal,sizeof(dapal)*num);
		i = regs.x.ax;
	}
	if (i != 0x004f) return(0);
	return(1);
}

VBE_getPalette(long start, long num, char *dapal)
{
	RMREGS regs;
	long i;

	if ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
	{
		koutp(0x3c7,start);
		for(i=num;i>0;i--)
		{
			dapal[2] = (char) kinp(0x3c9);
			dapal[1] = (char) kinp(0x3c9);
			dapal[0] = (char) kinp(0x3c9);
			dapal += 4;
		}
		return(1);
	}

	regs.x.ax = 0x4f09; regs.h.bl = 1;
	regs.x.cx = num; regs.x.dx = start;
	VBE_callESDI(®s,dapal,sizeof(dapal)*num);
	i = regs.x.ax;
	if (i != 0x004f) return(0);
	return(1);
}

#endif   // _INCLUDE_VES2_H_

// end of ves2.h ...