home *** CD-ROM | disk | FTP | other *** search
- #include "os.h"
- #ifdef OS_DOS
- /****************************************************************************
- * VBE 2.0 Linear Framebuffer Utilities
- * Base Code by By Kendall Bennett and Brian Hook
- * Modified for use by Matt Howard
- *
- * Filename: VESA.CPP
- * Language: ANSI C + C++
- * Environment: Watcom C/C++ 10.0a with DOS4GW
- * Description: Utilities to use SuperVGA VESA modes
- * Also allows burst copies to the screen
- * For simplicity, this program only supports 256 color
- * SuperVGA video modes that support a linear framebuffer.
- ****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <conio.h>
- #include <dos.h>
- #include "dpmiserv.h"
- #include "vesa.h"
-
- /*---------------------- Macros and type definitions ----------------------*/
- #pragma pack(1)
-
- /* SuperVGA information block */
- typedef struct {
- char VESASignature[4]; /* 'VESA' 4 byte signature */
- short VESAVersion; /* VBE version number */
- long OemStringPtr; /* Pointer to OEM string */
- long Capabilities; /* Capabilities of video card */
- long VideoModePtr; /* Pointer to supported modes */
- short TotalMemory; /* Number of 64kb memory blocks */
-
- /* VBE 2.0 extensions */
- short OemSoftwareRev; /* OEM Software revision number */
- long OemVendorNamePtr; /* Pointer to Vendor Name string */
- long OemProductNamePtr; /* Pointer to Product Name string */
- long OemProductRevPtr; /* Pointer to Product Revision str */
- char reserved[222]; /* Pad to 256 byte block size */
- char OemDATA[256]; /* Scratch pad for OEM data */
- } VBE_vgaInfo;
-
- /* SuperVGA mode information block */
- typedef struct {
- short ModeAttributes; /* Mode attributes */
- char WinAAttributes; /* Window A attributes */
- char WinBAttributes; /* Window B attributes */
- short WinGranularity; /* Window granularity in k */
- short WinSize; /* Window size in k */
- short WinASegment; /* Window A segment */
- short WinBSegment; /* Window B segment */
- long WinFuncPtr; /* Pointer to window function */
- short BytesPerScanLine; /* Bytes per scanline */
- short XResolution; /* Horizontal resolution */
- short YResolution; /* Vertical resolution */
- char XCharSize; /* Character cell width */
- char YCharSize; /* Character cell height */
- char NumberOfPlanes; /* Number of memory planes */
- char BitsPerPixel; /* Bits per pixel */
- char NumberOfBanks; /* Number of CGA style banks */
- char MemoryModel; /* Memory model type */
- char BankSize; /* Size of CGA style banks */
- char NumberOfImagePages; /* Number of images pages */
- char res1; /* Reserved */
- char RedMaskSize; /* Size of direct color red mask */
- char RedFieldPosition; /* Bit posn of lsb of red mask */
- char GreenMaskSize; /* Size of direct color green mask */
- char GreenFieldPosition; /* Bit posn of lsb of green mask */
- char BlueMaskSize; /* Size of direct color blue mask */
- char BlueFieldPosition; /* Bit posn of lsb of blue mask */
- char RsvdMaskSize; /* Size of direct color res mask */
- char RsvdFieldPosition; /* Bit posn of lsb of res mask */
- char DirectColorModeInfo; /* Direct color mode attributes */
-
- /* VBE 2.0 extensions */
- long PhysBasePtr; /* Physical address for linear buf */
- long OffScreenMemOffset; /* Pointer to start of offscreen mem*/
- short OffScreenMemSize; /* Amount of offscreen mem in 1K's */
- char res2[206]; /* Pad to 256 byte block size */
- } VBE_modeInfo;
- #define vbeMemPK 4 /* Packed Pixel memory model */
- #define vbeUseLFB 0x4000 /* Enable linear framebuffer mode */
-
- /* Flags for the mode attributes returned by VBE_getModeInfo. If
- * vbeMdNonBanked is set to 1 and vbeMdLinear is also set to 1, then only
- * the linear framebuffer mode is available. */
-
- #define vbeMdAvailable 0x0001 /* Video mode is available */
- #define vbeMdColorMode 0x0008 /* Mode is a color video mode */
- #define vbeMdGraphMode 0x0010 /* Mode is a graphics mode */
- #define vbeMdNonBanked 0x0040 /* Banked mode is not supported */
- #define vbeMdLinear 0x0080 /* Linear mode supported */
-
- /* Inline assembler block fill/move routines */
- void LfbMemset(int sel,int off,int c,int n);
- #pragma aux LfbMemset = \
- "push es" \
- "mov es,ax" \
- "shr ecx,2" \
- "xor eax,eax" \
- "mov al,bl" \
- "shl ebx,8" \
- "or ax,bx" \
- "mov ebx,eax" \
- "shl ebx,16" \
- "or eax,ebx" \
- "rep stosd" \
- "pop es" \
- parm [eax] [edi] [ebx] [ecx];
-
- void LfbMemcpy(int sel,int off,void *src,int n);
- #pragma aux LfbMemcpy = \
- "push es" \
- "mov es,ax" \
- "shr ecx,2" \
- "rep movsd" \
- "pop es" \
- parm [eax] [edi] [esi] [ecx];
-
- /* Map a real mode pointer into address space */
- #define LfbMapRealPointer(p) (void*)(((unsigned)(p) >> 12) + ((p) & 0xFFFF))
-
- /* Get the current timer tick count */
- #define LfbGetTicks() *((long*)0x46C)
-
- #pragma pack()
-
- /*---------------------------- Global Variables ---------------------------*/
- int VESABuf_len = 1024; /* Length of VESABuf */
- int VESABuf_sel = 0; /* Selector for VESABuf */
- int VESABuf_rseg; /* Real mode segment of VESABuf */
- short VESA_modeList[50]; /* List of available VBE modes */
- int VESA_xres,VESA_yres; /* Video mode resolution */
- int VESA_bytesperline; /* Bytes per scanline for mode */
- long VESA_imageSize; /* Length of the video image */
- char far * VESA_LFBPtr; /* Pointer to linear framebuffer */
-
- /*-------------------------- VBE Interface routines -----------------------*/
-
- static void ExitVBEBuf(void)
- {
- DPMI_freeRealSeg(VESABuf_sel);
- }
-
- void VBE_initRMBuf(void)
- /****************************************************************************
- * Function: VBE_initRMBuf
- * Description: Initialises the VBE transfer buffer in real mode memory.
- * This routine is called by the VESAVBE module every time
- * it needs to use the transfer buffer, so we simply allocate
- * it once and then return.
- ****************************************************************************/
- {
- if (!VESABuf_sel) {
- DPMI_allocRealSeg(VESABuf_len, &VESABuf_sel, &VESABuf_rseg);
- atexit(ExitVBEBuf);
- }
- }
-
- void VBE_callESDI(RMREGS *regs, void *buffer, int size)
- /****************************************************************************
- * Function: VBE_callESDI
- * Parameters: regs - Registers to load when calling VBE
- * buffer - Buffer to copy VBE info block to
- * size - Size of buffer to fill
- * Description: Calls the VESA VBE and passes in a buffer for the VBE to
- * store information in, which is then copied into the users
- * buffer space. This works in protected mode as the buffer
- * passed to the VESA VBE is allocated in conventional
- * memory, and is then copied into the users memory block.
- ****************************************************************************/
- {
- RMSREGS sregs;
-
- VBE_initRMBuf();
- 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);
- }
-
- int VBE_detect(void)
- /****************************************************************************
- * Function: VBE_detect
- * Parameters: vgaInfo - Place to store the VGA information block
- * Returns: VBE version number, or 0 if not detected.
- * Description: Detects if a VESA VBE is out there and functioning
- * correctly. If we detect a VBE interface we return the
- * VGAInfoBlock returned by the VBE and the VBE version number.
- ****************************************************************************/
- {
- RMREGS regs;
- short *p1,*p2;
- VBE_vgaInfo vgaInfo;
- /* Put 'VBE2' into the signature area so that the VBE 2.0 BIOS knows
- * that we have passed a 512 byte extended block to it, and wish
- * the extended information to be filled in.
- */
- strncpy(vgaInfo.VESASignature,"VBE2",4);
- /* Get the SuperVGA Information block */
- regs.x.ax = 0x4F00;
- VBE_callESDI(®s, &vgaInfo, sizeof(VBE_vgaInfo));
- if (regs.x.ax != 0x004F)
- return 0;
- if (strncmp(vgaInfo.VESASignature,"VESA",4) != 0)
- return 0;
- /* Now that we have detected a VBE interface, copy the list of available
- * video modes into our local buffer. We *must* copy this mode list, since
- * the VBE will build the mode list in the VBE_vgaInfo buffer that we have
- * passed, so the next call to the VBE will trash the list of modes. */
- p1 = (short *)LfbMapRealPointer(vgaInfo.VideoModePtr);
- p2 = VESA_modeList;
- while (*p1 != -1)
- *p2++ = *p1++;
- *p2 = -1;
- return vgaInfo.VESAVersion;
- }
-
- int VBE_getModeInfo(int mode,VBE_modeInfo *modeInfo)
- /****************************************************************************
- * Function: VBE_getModeInfo
- * Parameters: mode - VBE mode to get information for
- * modeInfo - Place to store VBE mode information
- * Returns: 1 on success, 0 if function failed.
- * Description: Obtains information about a specific video mode from the
- * VBE. You should use this function to find the video mode
- * you wish to set, as the new VBE 2.0 mode numbers may be
- * completely arbitrary.
- ****************************************************************************/
- {
- RMREGS regs;
-
- regs.x.ax = 0x4F01; /* Get mode information */
- regs.x.cx = mode;
- VBE_callESDI(®s, modeInfo, sizeof(VBE_modeInfo));
- if (regs.x.ax != 0x004F)
- return 0;
- if ((modeInfo->ModeAttributes & vbeMdAvailable) == 0)
- return 0;
- return 1;
- }
-
- void VBE_setVideoMode(int mode)
- /****************************************************************************
- * Function: VBE_setVideoMode
- * Parameters: mode - VBE mode number to initialise
- ****************************************************************************/
- {
- RMREGS regs;
- regs.x.ax = 0x4F02;
- regs.x.bx = mode;
- DPMI_int86(0x10,®s,®s);
- }
-
- /*-------------------- Application specific routines ----------------------*/
- void far *GetPtrToLFB(long physAddr)
- /****************************************************************************
- * Function: GetPtrToLFB
- * Parameters: physAddr - Physical memory address of linear framebuffer
- * Returns: Far pointer to the linear framebuffer memory
- ****************************************************************************/
- {
- int sel;
- long linAddr,limit = (4096 * 1024) - 1;
-
- sel = DPMI_allocSelector();
- linAddr = DPMI_mapPhysicalToLinear(physAddr,limit);
- DPMI_setSelectorBase(sel,linAddr);
- DPMI_setSelectorLimit(sel,limit);
- return MK_FP(sel,0);
- }
-
- void AvailableModes(void)
- /****************************************************************************
- * Function: AvailableModes
- * Description: Display a list of available LFB mode resolutions.
- ****************************************************************************/
- {
- short *p;
- VBE_modeInfo modeInfo;
-
- printf("Usage: LFBPROF <xres> <yres>\n\n");
- printf("Available 256 color video modes:\n");
- for (p = VESA_modeList; *p != -1; p++) {
- if (VBE_getModeInfo(*p, &modeInfo)) {
- /* Filter out only 8 bit linear framebuffer modes */
- if ((modeInfo.ModeAttributes & vbeMdLinear) == 0)
- continue;
- if (modeInfo.MemoryModel != vbeMemPK
- || modeInfo.BitsPerPixel != 8
- || modeInfo.NumberOfPlanes != 1)
- continue;
- printf(" %4d x %4d %d bits per pixel\n",
- modeInfo.XResolution, modeInfo.YResolution,
- modeInfo.BitsPerPixel);
- }
- }
- exit(1);
- }
-
- short VESA_InitGraphics(int x,int y)
- /****************************************************************************
- * Function: InitGraphics
- * Parameters: x,y - Requested video mode resolution
- * Description: Initialise the specified video mode. We search through
- * the list of available video modes for one that matches
- * the resolution and color depth are are looking for.
- ****************************************************************************/
- {
- short *p;
- VBE_modeInfo modeInfo;
-
- for (p = VESA_modeList; *p != -1; p++) {
- if (VBE_getModeInfo(*p, &modeInfo)) {
- /* Filter out only 8 bit linear framebuffer modes */
- printf("Cur Mode X Res: %d Y Res: %d\n", modeInfo.XResolution, modeInfo.YResolution);
- if ((modeInfo.ModeAttributes & vbeMdLinear) == 0)
- continue;
- if (modeInfo.MemoryModel != vbeMemPK
- || modeInfo.BitsPerPixel != 8
- || modeInfo.NumberOfPlanes != 1)
- continue;
- if (modeInfo.XResolution != x || modeInfo.YResolution != y)
- continue;
- VESA_xres = x;
- VESA_yres = y;
- VESA_bytesperline = modeInfo.BytesPerScanLine;
- VESA_imageSize = VESA_bytesperline * VESA_yres;
- VBE_setVideoMode(*p | vbeUseLFB);
- VESA_LFBPtr = (char __far *)GetPtrToLFB(modeInfo.PhysBasePtr);
- return 0;
- }
- }
- printf("Valid video mode not found\n");
- return 1;
- }
-
- void VESA_EndGraphics(void)
- /****************************************************************************
- * Function: EndGraphics
- * Description: Restores text mode.
- ****************************************************************************/
- {
- RMREGS regs;
- regs.x.ax = 0x3;
- DPMI_int86(0x10, ®s, ®s);
- }
-
- void VESA_ScreenCopy(long offset, void * src, long ncopy)
- /****************************************************************************
- * Function: VESA_ScreenCopy
- * Description: Copies a block of memory to a location on the screen
- ****************************************************************************/
- {
- LfbMemcpy(FP_SEG(VESA_LFBPtr), offset, src, ncopy);
- }
- #endif