// "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 ...