home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / RAYCAST.ZIP / VESA.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-14  |  15.8 KB  |  362 lines

  1. #include "os.h"
  2. #ifdef OS_DOS
  3. /****************************************************************************
  4. *                   VBE 2.0 Linear Framebuffer Utilities
  5. *                    Base Code by By Kendall Bennett and Brian Hook
  6. *                    Modified for use by Matt Howard
  7. *
  8. * Filename:     VESA.CPP
  9. * Language:     ANSI C + C++
  10. * Environment:  Watcom C/C++ 10.0a with DOS4GW
  11. * Description:  Utilities to use SuperVGA VESA modes
  12. *               Also allows burst copies to the screen
  13. *               For simplicity, this program only supports 256 color
  14. *               SuperVGA video modes that support a linear framebuffer.
  15. ****************************************************************************/
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <conio.h>
  21. #include <dos.h>
  22. #include "dpmiserv.h"
  23. #include "vesa.h"
  24.  
  25. /*---------------------- Macros and type definitions ----------------------*/
  26. #pragma pack(1)
  27.  
  28. /* SuperVGA information block */
  29. typedef struct {
  30.     char    VESASignature[4];       /* 'VESA' 4 byte signature          */
  31.     short   VESAVersion;            /* VBE version number               */
  32.     long    OemStringPtr;           /* Pointer to OEM string            */
  33.     long    Capabilities;           /* Capabilities of video card       */
  34.     long    VideoModePtr;           /* Pointer to supported modes       */
  35.     short   TotalMemory;            /* Number of 64kb memory blocks     */
  36.  
  37.     /* VBE 2.0 extensions */
  38.     short   OemSoftwareRev;         /* OEM Software revision number     */
  39.     long    OemVendorNamePtr;       /* Pointer to Vendor Name string    */
  40.     long    OemProductNamePtr;      /* Pointer to Product Name string   */
  41.     long    OemProductRevPtr;       /* Pointer to Product Revision str  */
  42.     char    reserved[222];          /* Pad to 256 byte block size       */
  43.     char    OemDATA[256];           /* Scratch pad for OEM data         */
  44.     } VBE_vgaInfo;
  45.  
  46. /* SuperVGA mode information block */
  47. typedef struct {
  48.     short   ModeAttributes;         /* Mode attributes                  */
  49.     char    WinAAttributes;         /* Window A attributes              */
  50.     char    WinBAttributes;         /* Window B attributes              */
  51.     short   WinGranularity;         /* Window granularity in k          */
  52.     short   WinSize;                /* Window size in k                 */
  53.     short   WinASegment;            /* Window A segment                 */
  54.     short   WinBSegment;            /* Window B segment                 */
  55.     long    WinFuncPtr;             /* Pointer to window function       */
  56.     short   BytesPerScanLine;       /* Bytes per scanline               */
  57.     short   XResolution;            /* Horizontal resolution            */
  58.     short   YResolution;            /* Vertical resolution              */
  59.     char    XCharSize;              /* Character cell width             */
  60.     char    YCharSize;              /* Character cell height            */
  61.     char    NumberOfPlanes;         /* Number of memory planes          */
  62.     char    BitsPerPixel;           /* Bits per pixel                   */
  63.     char    NumberOfBanks;          /* Number of CGA style banks        */
  64.     char    MemoryModel;            /* Memory model type                */
  65.     char    BankSize;               /* Size of CGA style banks          */
  66.     char    NumberOfImagePages;     /* Number of images pages           */
  67.     char    res1;                   /* Reserved                         */
  68.     char    RedMaskSize;            /* Size of direct color red mask    */
  69.     char    RedFieldPosition;       /* Bit posn of lsb of red mask      */
  70.     char    GreenMaskSize;          /* Size of direct color green mask  */
  71.     char    GreenFieldPosition;     /* Bit posn of lsb of green mask    */
  72.     char    BlueMaskSize;           /* Size of direct color blue mask   */
  73.     char    BlueFieldPosition;      /* Bit posn of lsb of blue mask     */
  74.     char    RsvdMaskSize;           /* Size of direct color res mask    */
  75.     char    RsvdFieldPosition;      /* Bit posn of lsb of res mask      */
  76.     char    DirectColorModeInfo;    /* Direct color mode attributes     */
  77.  
  78.     /* VBE 2.0 extensions */
  79.     long    PhysBasePtr;            /* Physical address for linear buf  */
  80.     long    OffScreenMemOffset;     /* Pointer to start of offscreen mem*/
  81.     short   OffScreenMemSize;       /* Amount of offscreen mem in 1K's  */
  82.     char    res2[206];              /* Pad to 256 byte block size       */
  83.     } VBE_modeInfo;
  84. #define vbeMemPK        4           /* Packed Pixel memory model        */
  85. #define vbeUseLFB       0x4000      /* Enable linear framebuffer mode   */
  86.  
  87. /* Flags for the mode attributes returned by VBE_getModeInfo. If
  88.  * vbeMdNonBanked is set to 1 and vbeMdLinear is also set to 1, then only
  89.  * the linear framebuffer mode is available. */
  90.  
  91. #define vbeMdAvailable  0x0001      /* Video mode is available          */
  92. #define vbeMdColorMode  0x0008      /* Mode is a color video mode       */
  93. #define vbeMdGraphMode  0x0010      /* Mode is a graphics mode          */
  94. #define vbeMdNonBanked  0x0040      /* Banked mode is not supported     */
  95. #define vbeMdLinear     0x0080      /* Linear mode supported            */
  96.  
  97. /* Inline assembler block fill/move routines */
  98. void LfbMemset(int sel,int off,int c,int n);
  99. #pragma aux LfbMemset =             \
  100.     "push   es"                     \
  101.     "mov    es,ax"                  \
  102.     "shr    ecx,2"                  \
  103.     "xor    eax,eax"                \
  104.     "mov    al,bl"                  \
  105.     "shl    ebx,8"                  \
  106.     "or     ax,bx"                  \
  107.     "mov    ebx,eax"                \
  108.     "shl    ebx,16"                 \
  109.     "or     eax,ebx"                \
  110.     "rep    stosd"                  \
  111.     "pop    es"                     \
  112.     parm [eax] [edi] [ebx] [ecx];
  113.  
  114. void LfbMemcpy(int sel,int off,void *src,int n);
  115. #pragma aux LfbMemcpy =             \
  116.     "push   es"                     \
  117.     "mov    es,ax"                  \
  118.     "shr    ecx,2"                  \
  119.     "rep    movsd"                  \
  120.     "pop    es"                     \
  121.     parm [eax] [edi] [esi] [ecx];
  122.  
  123. /* Map a real mode pointer into address space */
  124. #define LfbMapRealPointer(p)    (void*)(((unsigned)(p) >> 12) + ((p) & 0xFFFF))
  125.  
  126. /* Get the current timer tick count */
  127. #define LfbGetTicks()       *((long*)0x46C)
  128.  
  129. #pragma pack()
  130.  
  131. /*---------------------------- Global Variables ---------------------------*/
  132. int     VESABuf_len = 1024;         /* Length of VESABuf                */
  133. int     VESABuf_sel = 0;            /* Selector for VESABuf             */
  134. int     VESABuf_rseg;               /* Real mode segment of VESABuf     */
  135. short   VESA_modeList[50];               /* List of available VBE modes      */
  136. int     VESA_xres,VESA_yres;                  /* Video mode resolution            */
  137. int     VESA_bytesperline;               /* Bytes per scanline for mode      */
  138. long    VESA_imageSize;                  /* Length of the video image        */
  139. char    far * VESA_LFBPtr;                /* Pointer to linear framebuffer    */
  140.  
  141. /*-------------------------- VBE Interface routines -----------------------*/
  142.  
  143. static void ExitVBEBuf(void)
  144. {
  145.     DPMI_freeRealSeg(VESABuf_sel);
  146. }
  147.  
  148. void VBE_initRMBuf(void)
  149. /****************************************************************************
  150. * Function:     VBE_initRMBuf
  151. * Description:  Initialises the VBE transfer buffer in real mode memory.
  152. *               This routine is called by the VESAVBE module every time
  153. *               it needs to use the transfer buffer, so we simply allocate
  154. *               it once and then return.
  155. ****************************************************************************/
  156. {
  157.     if (!VESABuf_sel) {
  158.         DPMI_allocRealSeg(VESABuf_len, &VESABuf_sel, &VESABuf_rseg);
  159.         atexit(ExitVBEBuf);
  160.         }
  161. }
  162.  
  163. void VBE_callESDI(RMREGS *regs, void *buffer, int size)
  164. /****************************************************************************
  165. * Function:     VBE_callESDI
  166. * Parameters:   regs    - Registers to load when calling VBE
  167. *               buffer  - Buffer to copy VBE info block to
  168. *               size    - Size of buffer to fill
  169. * Description:  Calls the VESA VBE and passes in a buffer for the VBE to
  170. *               store information in, which is then copied into the users
  171. *               buffer space. This works in protected mode as the buffer
  172. *               passed to the VESA VBE is allocated in conventional
  173. *               memory, and is then copied into the users memory block.
  174. ****************************************************************************/
  175. {
  176.     RMSREGS sregs;
  177.  
  178.     VBE_initRMBuf();
  179.     sregs.es = VESABuf_rseg;
  180.     regs->x.di = 0;
  181.     _fmemcpy(MK_FP(VESABuf_sel,0),buffer,size);
  182.     DPMI_int86x(0x10, regs, regs, &sregs);
  183.     _fmemcpy(buffer,MK_FP(VESABuf_sel,0),size);
  184. }
  185.  
  186. int VBE_detect(void)
  187. /****************************************************************************
  188. * Function:     VBE_detect
  189. * Parameters:   vgaInfo - Place to store the VGA information block
  190. * Returns:      VBE version number, or 0 if not detected.
  191. * Description:  Detects if a VESA VBE is out there and functioning
  192. *               correctly. If we detect a VBE interface we return the
  193. *               VGAInfoBlock returned by the VBE and the VBE version number.
  194. ****************************************************************************/
  195. {
  196.     RMREGS      regs;
  197.     short       *p1,*p2;
  198.     VBE_vgaInfo vgaInfo;
  199.     /* Put 'VBE2' into the signature area so that the VBE 2.0 BIOS knows
  200.      * that we have passed a 512 byte extended block to it, and wish
  201.      * the extended information to be filled in.
  202.      */
  203.     strncpy(vgaInfo.VESASignature,"VBE2",4);
  204.     /* Get the SuperVGA Information block */
  205.     regs.x.ax = 0x4F00;
  206.     VBE_callESDI(®s, &vgaInfo, sizeof(VBE_vgaInfo));
  207.     if (regs.x.ax != 0x004F)
  208.         return 0;
  209.     if (strncmp(vgaInfo.VESASignature,"VESA",4) != 0)
  210.         return 0;
  211.     /* Now that we have detected a VBE interface, copy the list of available
  212.      * video modes into our local buffer. We *must* copy this mode list, since
  213.      * the VBE will build the mode list in the VBE_vgaInfo buffer that we have
  214.      * passed, so the next call to the VBE will trash the list of modes. */
  215.     p1 = (short *)LfbMapRealPointer(vgaInfo.VideoModePtr);
  216.     p2 = VESA_modeList;
  217.     while (*p1 != -1)
  218.         *p2++ = *p1++;
  219.     *p2 = -1;
  220.     return vgaInfo.VESAVersion;
  221. }
  222.  
  223. int VBE_getModeInfo(int mode,VBE_modeInfo *modeInfo)
  224. /****************************************************************************
  225. * Function:     VBE_getModeInfo
  226. * Parameters:   mode        - VBE mode to get information for
  227. *               modeInfo    - Place to store VBE mode information
  228. * Returns:      1 on success, 0 if function failed.
  229. * Description:  Obtains information about a specific video mode from the
  230. *               VBE. You should use this function to find the video mode
  231. *               you wish to set, as the new VBE 2.0 mode numbers may be
  232. *               completely arbitrary.
  233. ****************************************************************************/
  234. {
  235.     RMREGS  regs;
  236.  
  237.     regs.x.ax = 0x4F01;             /* Get mode information         */
  238.     regs.x.cx = mode;
  239.     VBE_callESDI(®s, modeInfo, sizeof(VBE_modeInfo));
  240.     if (regs.x.ax != 0x004F)
  241.         return 0;
  242.     if ((modeInfo->ModeAttributes & vbeMdAvailable) == 0)
  243.         return 0;
  244.     return 1;
  245. }
  246.  
  247. void VBE_setVideoMode(int mode)
  248. /****************************************************************************
  249. * Function:     VBE_setVideoMode
  250. * Parameters:   mode    - VBE mode number to initialise
  251. ****************************************************************************/
  252. {
  253.     RMREGS  regs;
  254.     regs.x.ax = 0x4F02;
  255.     regs.x.bx = mode;
  256.     DPMI_int86(0x10,®s,®s);
  257. }
  258.  
  259. /*-------------------- Application specific routines ----------------------*/
  260. void far *GetPtrToLFB(long physAddr)
  261. /****************************************************************************
  262. * Function:     GetPtrToLFB
  263. * Parameters:   physAddr    - Physical memory address of linear framebuffer
  264. * Returns:      Far pointer to the linear framebuffer memory
  265. ****************************************************************************/
  266. {
  267.     int     sel;
  268.     long    linAddr,limit = (4096 * 1024) - 1;
  269.  
  270.     sel = DPMI_allocSelector();
  271.     linAddr = DPMI_mapPhysicalToLinear(physAddr,limit);
  272.     DPMI_setSelectorBase(sel,linAddr);
  273.     DPMI_setSelectorLimit(sel,limit);
  274.     return MK_FP(sel,0);
  275. }
  276.  
  277. void AvailableModes(void)
  278. /****************************************************************************
  279. * Function:     AvailableModes
  280. * Description:  Display a list of available LFB mode resolutions.
  281. ****************************************************************************/
  282. {
  283.     short           *p;
  284.     VBE_modeInfo    modeInfo;
  285.  
  286.     printf("Usage: LFBPROF <xres> <yres>\n\n");
  287.     printf("Available 256 color video modes:\n");
  288.     for (p = VESA_modeList; *p != -1; p++) {
  289.         if (VBE_getModeInfo(*p, &modeInfo)) {
  290.             /* Filter out only 8 bit linear framebuffer modes */
  291.             if ((modeInfo.ModeAttributes & vbeMdLinear) == 0)
  292.                 continue;
  293.             if (modeInfo.MemoryModel != vbeMemPK
  294.                 || modeInfo.BitsPerPixel != 8
  295.                 || modeInfo.NumberOfPlanes != 1)
  296.                 continue;
  297.             printf("    %4d x %4d %d bits per pixel\n",
  298.                 modeInfo.XResolution, modeInfo.YResolution,
  299.                 modeInfo.BitsPerPixel);
  300.             }
  301.         }
  302.     exit(1);
  303. }
  304.  
  305. short VESA_InitGraphics(int x,int y)
  306. /****************************************************************************
  307. * Function:     InitGraphics
  308. * Parameters:   x,y - Requested video mode resolution
  309. * Description:  Initialise the specified video mode. We search through
  310. *               the list of available video modes for one that matches
  311. *               the resolution and color depth are are looking for.
  312. ****************************************************************************/
  313. {
  314.     short           *p;
  315.     VBE_modeInfo    modeInfo;
  316.  
  317.     for (p = VESA_modeList; *p != -1; p++) {
  318.         if (VBE_getModeInfo(*p, &modeInfo)) {
  319.             /* Filter out only 8 bit linear framebuffer modes */
  320.             printf("Cur Mode X Res: %d Y Res: %d\n", modeInfo.XResolution, modeInfo.YResolution);
  321.             if ((modeInfo.ModeAttributes & vbeMdLinear) == 0)
  322.                 continue;
  323.             if (modeInfo.MemoryModel != vbeMemPK
  324.                 || modeInfo.BitsPerPixel != 8
  325.                 || modeInfo.NumberOfPlanes != 1)
  326.                 continue;
  327.             if (modeInfo.XResolution != x || modeInfo.YResolution != y)
  328.                 continue;
  329.             VESA_xres = x;
  330.             VESA_yres = y;
  331.             VESA_bytesperline = modeInfo.BytesPerScanLine;
  332.             VESA_imageSize = VESA_bytesperline * VESA_yres;
  333.             VBE_setVideoMode(*p | vbeUseLFB);
  334.             VESA_LFBPtr = (char __far *)GetPtrToLFB(modeInfo.PhysBasePtr);
  335.             return 0;
  336.             }
  337.         }
  338.     printf("Valid video mode not found\n");
  339.     return 1;
  340. }
  341.  
  342. void VESA_EndGraphics(void)
  343. /****************************************************************************
  344. * Function:     EndGraphics
  345. * Description:  Restores text mode.
  346. ****************************************************************************/
  347. {
  348.     RMREGS  regs;
  349.     regs.x.ax = 0x3;
  350.     DPMI_int86(0x10, ®s, ®s);
  351. }
  352.  
  353. void VESA_ScreenCopy(long offset, void * src, long ncopy)
  354. /****************************************************************************
  355. * Function:     VESA_ScreenCopy
  356. * Description:  Copies a block of memory to a location on the screen
  357. ****************************************************************************/
  358. {
  359.    LfbMemcpy(FP_SEG(VESA_LFBPtr), offset, src, ncopy);
  360. }
  361. #endif
  362.