home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / misc_programming / SRC / SVGAKIT / HELLOVBE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-23  |  14.8 KB  |  389 lines

  1. /****************************************************************************
  2. *
  3. *                               Hello VBE!
  4. *
  5. *                   Copyright (C) 1994 SciTech Software
  6. *                           All rights reserved.
  7. *
  8. * Language:     ANSI C
  9. * Environment:  IBM PC (MSDOS) 16 bit Real Mode
  10. * Author:       Kendall Bennett, SciTech Software
  11. *
  12. * Description:  Simple 'Hello World' program to initialise a user
  13. *               specified 256 color graphics mode, and display a simple
  14. *               moire pattern. Tested with VBE 1.2 and above.
  15. *
  16. *               This code does not have any hard-coded VBE mode numbers,
  17. *               but will use the VBE 2.0 aware method of searching for
  18. *               available video modes, so will work with any new extended
  19. *               video modes defined by a particular OEM VBE 2.0 version.
  20. *
  21. *               For brevity we dont check for failure conditions returned
  22. *               by the VBE (but we shouldn't get any).
  23. *
  24. * $Id: hellovbe.c 1.1 1994/08/22 12:27:00 kjb release $
  25. *
  26. ****************************************************************************/
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <dos.h>
  31. #include <conio.h>
  32.  
  33. /* Uncomment the following to enable direct bank switching, rather than
  34.  * using the Int 10h software interrupt (requires Borland C++ inline
  35.  * assembler).
  36.  */
  37.  
  38. /* #define  DIRECT_BANKING */
  39.  
  40. /*---------------------- Macro and type definitions -----------------------*/
  41.  
  42. /* SuperVGA information block */
  43.  
  44. typedef struct {
  45.     char    VESASignature[4];       /* 'VESA' 4 byte signature          */
  46.     short   VESAVersion;            /* VBE version number               */
  47.     char    _far *OEMStringPtr;     /* Pointer to OEM string            */
  48.     long    Capabilities;           /* Capabilities of video card       */
  49.     short   _far *VideoModePtr;     /* Pointer to supported modes       */
  50.     short   TotalMemory;            /* Number of 64kb memory blocks     */
  51.     char    reserved[236];          /* Pad to 256 byte block size       */
  52.     } VgaInfoBlock;
  53.  
  54. /* SuperVGA mode information block */
  55.  
  56. typedef struct {
  57.     short   ModeAttributes;         /* Mode attributes                  */
  58.     char    WinAAttributes;         /* Window A attributes              */
  59.     char    WinBAttributes;         /* Window B attributes              */
  60.     short   WinGranularity;         /* Window granularity in k          */
  61.     short   WinSize;                /* Window size in k                 */
  62.     short   WinASegment;            /* Window A segment                 */
  63.     short   WinBSegment;            /* Window B segment                 */
  64.     void    _far *WinFuncPtr;       /* Pointer to window function       */
  65.     short   BytesPerScanLine;       /* Bytes per scanline               */
  66.     short   XResolution;            /* Horizontal resolution            */
  67.     short   YResolution;            /* Vertical resolution              */
  68.     char    XCharSize;              /* Character cell width             */
  69.     char    YCharSize;              /* Character cell height            */
  70.     char    NumberOfPlanes;         /* Number of memory planes          */
  71.     char    BitsPerPixel;           /* Bits per pixel                   */
  72.     char    NumberOfBanks;          /* Number of CGA style banks        */
  73.     char    MemoryModel;            /* Memory model type                */
  74.     char    BankSize;               /* Size of CGA style banks          */
  75.     char    NumberOfImagePages;     /* Number of images pages           */
  76.     char    res1;                   /* Reserved                         */
  77.     char    RedMaskSize;            /* Size of direct color red mask    */
  78.     char    RedFieldPosition;       /* Bit posn of lsb of red mask      */
  79.     char    GreenMaskSize;          /* Size of direct color green mask  */
  80.     char    GreenFieldPosition;     /* Bit posn of lsb of green mask    */
  81.     char    BlueMaskSize;           /* Size of direct color blue mask   */
  82.     char    BlueFieldPosition;      /* Bit posn of lsb of blue mask     */
  83.     char    RsvdMaskSize;           /* Size of direct color res mask    */
  84.     char    RsvdFieldPosition;      /* Bit posn of lsb of res mask      */
  85.     char    DirectColorModeInfo;    /* Direct color mode attributes     */
  86.     char    res2[216];              /* Pad to 256 byte block size       */
  87.     } ModeInfoBlock;
  88.  
  89. typedef enum {
  90.     memPL       = 3,                /* Planar memory model              */
  91.     memPK       = 4,                /* Packed pixel memory model        */
  92.     memRGB      = 6,                /* Direct color RGB memory model    */
  93.     memYUV      = 7,                /* Direct color YUV memory model    */
  94.     } memModels;
  95.  
  96. /*--------------------------- Global Variables ----------------------------*/
  97.  
  98. int     xres,yres;                  /* Resolution of video mode used    */
  99. int     bytesperline;               /* Logical CRT scanline length      */
  100. int     curBank;                    /* Current read/write bank          */
  101. int     bankShift;                  /* Bank granularity adjust factor   */
  102. int     oldMode;                    /* Old video mode number            */
  103. void    _far (*bankSwitch)(void);   /* Direct bank switching function   */
  104. char    _far *screenPtr;            /* Pointer to start of video memory */
  105.  
  106. /*------------------------ VBE Interface Functions ------------------------*/
  107.  
  108. /* Get SuperVGA information, returning true if VBE found */
  109.  
  110. int getVgaInfo(VgaInfoBlock *vgaInfo)
  111. {
  112.     union REGS regs;
  113.     struct SREGS sregs;
  114.     regs.x.ax = 0x4F00;
  115.     regs.x.di = FP_OFF(vgaInfo);
  116.     sregs.es = FP_SEG(vgaInfo);
  117.     int86x(0x10, ®s, ®s, &sregs);
  118.     return (regs.x.ax == 0x4F);
  119. }
  120.  
  121. /* Get video mode information given a VBE mode number. We return 0 if
  122.  * if the mode is not available, or if it is not a 256 color packed
  123.  * pixel mode.
  124.  */
  125.  
  126. int getModeInfo(int mode, ModeInfoBlock *modeInfo)
  127. {
  128.     union REGS regs;
  129.     struct SREGS sregs;
  130.     if (mode < 0x100) return 0;     /* Ignore non-VBE modes             */
  131.     regs.x.ax = 0x4F01;
  132.     regs.x.cx = mode;
  133.     regs.x.di = FP_OFF(modeInfo);
  134.     sregs.es = FP_SEG(modeInfo);
  135.     int86x(0x10, ®s, ®s, &sregs);
  136.     if (regs.x.ax != 0x4F) return 0;
  137.     if ((modeInfo->ModeAttributes & 0x1) && modeInfo->MemoryModel == memPK
  138.             && modeInfo->BitsPerPixel == 8 && modeInfo->NumberOfPlanes == 1)
  139.         return 1;
  140.     return 0;
  141. }
  142.  
  143. /* Set a VBE video mode */
  144.  
  145. void setVBEMode(int mode)
  146. {
  147.     union REGS regs;
  148.     regs.x.ax = 0x4F02; regs.x.bx = mode;
  149.     int86(0x10,®s,®s);
  150. }
  151.  
  152. /* Return the current VBE video mode */
  153.  
  154. int getVBEMode(void)
  155. {
  156.     union REGS regs;
  157.     regs.x.ax = 0x4F03;
  158.     int86(0x10,®s,®s);
  159.     return regs.x.bx;
  160. }
  161.  
  162. /* Set new read/write bank. We must set both Window A and Window B, as
  163.  * many VBE's have these set as separately available read and write
  164.  * windows. We also use a simple (but very effective) optimisation of
  165.  * checking if the requested bank is currently active.
  166.  */
  167.  
  168. void setBank(int bank)
  169. {
  170.     union REGS  regs;
  171.     if (bank == curBank) return;    /* Bank is already active           */
  172.     curBank = bank;                 /* Save current bank number         */
  173.     bank <<= bankShift;             /* Adjust to window granularity     */
  174. #ifdef  DIRECT_BANKING
  175. asm {   mov bx,0;
  176.         mov dx,bank; }
  177.     bankSwitch();
  178. asm {   mov bx,1;
  179.         mov dx,bank; }
  180.     bankSwitch();
  181. #else
  182.     regs.x.ax = 0x4F05; regs.x.bx = 0;  regs.x.dx = bank;
  183.     int86(0x10, ®s, ®s);
  184.     regs.x.ax = 0x4F05; regs.x.bx = 1;  regs.x.dx = bank;
  185.     int86(0x10, ®s, ®s);
  186. #endif
  187. }
  188.  
  189. /*-------------------------- Application Functions ------------------------*/
  190.  
  191. /* Plot a pixel at location (x,y) in specified color (8 bit modes only) */
  192.  
  193. void putPixel(int x,int y,int color)
  194. {
  195.     long addr = (long)y * bytesperline + x;
  196.     setBank(addr >> 16);
  197.     *(screenPtr + (addr & 0xFFFF)) = color;
  198. }
  199.  
  200. /* Draw a line from (x1,y1) to (x2,y2) in specified color */
  201.  
  202. void line(int x1,int y1,int x2,int y2,int color)
  203. {
  204.     int     d;                      /* Decision variable                */
  205.     int     dx,dy;                  /* Dx and Dy values for the line    */
  206.     int     Eincr,NEincr;           /* Decision variable increments     */
  207.     int     yincr;                  /* Increment for y values           */
  208.     int     t;                      /* Counters etc.                    */
  209.  
  210. #define ABS(a)   ((a) >= 0 ? (a) : -(a))
  211.  
  212.     dx = ABS(x2 - x1);
  213.     dy = ABS(y2 - y1);
  214.     if (dy <= dx) {
  215.         /* We have a line with a slope between -1 and 1
  216.          *
  217.          * Ensure that we are always scan converting the line from left to
  218.          * right to ensure that we produce the same line from P1 to P0 as the
  219.          * line from P0 to P1.
  220.          */
  221.         if (x2 < x1) {
  222.             t = x2; x2 = x1; x1 = t;    /* Swap X coordinates           */
  223.             t = y2; y2 = y1; y1 = t;    /* Swap Y coordinates           */
  224.             }
  225.         if (y2 > y1)
  226.             yincr = 1;
  227.         else
  228.             yincr = -1;
  229.         d = 2*dy - dx;              /* Initial decision variable value  */
  230.         Eincr = 2*dy;               /* Increment to move to E pixel     */
  231.         NEincr = 2*(dy - dx);       /* Increment to move to NE pixel    */
  232.         putPixel(x1,y1,color);      /* Draw the first point at (x1,y1)  */
  233.  
  234.         /* Incrementally determine the positions of the remaining pixels
  235.          */
  236.         for (x1++; x1 <= x2; x1++) {
  237.             if (d < 0)
  238.                 d += Eincr;         /* Choose the Eastern Pixel         */
  239.             else {
  240.                 d += NEincr;        /* Choose the North Eastern Pixel   */
  241.                 y1 += yincr;        /* (or SE pixel for dx/dy < 0!)     */
  242.                 }
  243.             putPixel(x1,y1,color);  /* Draw the point                   */
  244.             }
  245.         }
  246.     else {
  247.         /* We have a line with a slope between -1 and 1 (ie: includes
  248.          * vertical lines). We must swap our x and y coordinates for this.
  249.          *
  250.          * Ensure that we are always scan converting the line from left to
  251.          * right to ensure that we produce the same line from P1 to P0 as the
  252.          * line from P0 to P1.
  253.          */
  254.         if (y2 < y1) {
  255.             t = x2; x2 = x1; x1 = t;    /* Swap X coordinates           */
  256.             t = y2; y2 = y1; y1 = t;    /* Swap Y coordinates           */
  257.             }
  258.         if (x2 > x1)
  259.             yincr = 1;
  260.         else
  261.             yincr = -1;
  262.         d = 2*dx - dy;              /* Initial decision variable value  */
  263.         Eincr = 2*dx;               /* Increment to move to E pixel     */
  264.         NEincr = 2*(dx - dy);       /* Increment to move to NE pixel    */
  265.         putPixel(x1,y1,color);      /* Draw the first point at (x1,y1)  */
  266.  
  267.         /* Incrementally determine the positions of the remaining pixels
  268.          */
  269.         for (y1++; y1 <= y2; y1++) {
  270.             if (d < 0)
  271.                 d += Eincr;         /* Choose the Eastern Pixel         */
  272.             else {
  273.                 d += NEincr;        /* Choose the North Eastern Pixel   */
  274.                 x1 += yincr;        /* (or SE pixel for dx/dy < 0!)     */
  275.                 }
  276.             putPixel(x1,y1,color);  /* Draw the point                   */
  277.             }
  278.         }
  279. }
  280.  
  281. /* Draw a simple moire pattern of lines on the display */
  282.  
  283. void drawMoire(void)
  284. {
  285.     int     i;
  286.  
  287.     for (i = 0; i < xres; i += 5) {
  288.         line(xres/2,yres/2,i,0,i % 0xFF);
  289.         line(xres/2,yres/2,i,yres,(i+1) % 0xFF);
  290.         }
  291.     for (i = 0; i < yres; i += 5) {
  292.         line(xres/2,yres/2,0,i,(i+2) % 0xFF);
  293.         line(xres/2,yres/2,xres,i,(i+3) % 0xFF);
  294.         }
  295.     line(0,0,xres-1,0,15);
  296.     line(0,0,0,yres-1,15);
  297.     line(xres-1,0,xres-1,yres-1,15);
  298.     line(0,yres-1,xres-1,yres-1,15);
  299. }
  300.  
  301. /* Display a list of available resolutions. Be careful with calls to
  302.  * function 00h to get SuperVGA mode information. Many VBE's build the
  303.  * list of video modes directly in this information block, so if you
  304.  * are using a common buffer (which we aren't here, but in protected
  305.  * mode you will), then you will need to make a local copy of this list
  306.  * of available modes.
  307.  */
  308.  
  309. void availableModes(void)
  310. {
  311.     short           *p;
  312.     VgaInfoBlock    vgaInfo;
  313.     ModeInfoBlock   modeInfo;
  314.  
  315.     if (!getVgaInfo(&vgaInfo)) {
  316.         printf("No VESA VBE detected\n");
  317.         exit(1);
  318.         }
  319.     printf("VESA VBE Version %d.%d detected (%s)\n\n",
  320.         vgaInfo.VESAVersion >> 8, vgaInfo.VESAVersion & 0xF,
  321.         vgaInfo.OEMStringPtr);
  322.     printf("Available 256 color video modes:\n");
  323.     for (p = vgaInfo.VideoModePtr; *p != -1; p++) {
  324.         if (getModeInfo(*p, &modeInfo)) {
  325.             printf("    %4d x %4d %d bits per pixel\n",
  326.                 modeInfo.XResolution, modeInfo.YResolution,
  327.                 modeInfo.BitsPerPixel);
  328.             }
  329.         }
  330.     printf("\nUsage: hellovbe <xres> <yres>\n");
  331.     exit(1);
  332. }
  333.  
  334. /* Initialise the specified video mode. Notice how we determine a shift
  335.  * factor for adjusting the Window granularity for bank switching. This
  336.  * is much faster than doing it with a multiply (especially with direct
  337.  * banking enabled).
  338.  */
  339.  
  340. void initGraphics(int x,int y)
  341. {
  342.     short           *p;
  343.     VgaInfoBlock    vgaInfo;
  344.     ModeInfoBlock   modeInfo;
  345.  
  346.     if (!getVgaInfo(&vgaInfo)) {
  347.         printf("No VESA VBE detected\n");
  348.         exit(1);
  349.         }
  350.     for (p = vgaInfo.VideoModePtr; *p != -1; p++) {
  351.         if (getModeInfo(*p, &modeInfo) && modeInfo.XResolution == x
  352.                 && modeInfo.YResolution == y) {
  353.             xres = x;   yres = y;
  354.             bytesperline = modeInfo.BytesPerScanLine;
  355.             bankShift = 0;
  356.             while ((64 >> bankShift) != modeInfo.WinGranularity)
  357.                 bankShift++;
  358.             bankSwitch = modeInfo.WinFuncPtr;
  359.             curBank = -1;
  360.             screenPtr = MK_FP(0xA000,0);
  361.             oldMode = getVBEMode();
  362.             setVBEMode(*p);
  363.             return;
  364.             }
  365.         }
  366.     printf("Valid video mode not found\n");
  367.     exit(1);
  368. }
  369.  
  370. /* Main routine. Expects the x & y resolution of the desired video mode
  371.  * to be passed on the command line. Will print out a list of available
  372.  * video modes if no command line is present.
  373.  */
  374.  
  375. void main(int argc,char *argv[])
  376. {
  377.     int x,y;
  378.  
  379.     if (argc != 3)
  380.         availableModes();       /* Display list of available modes      */
  381.  
  382.     x = atoi(argv[1]);          /* Get requested resolution             */
  383.     y = atoi(argv[2]);
  384.     initGraphics(x,y);          /* Start requested video mode           */
  385.     drawMoire();                /* Draw a moire pattern                 */
  386.     getch();                    /* Wait for keypress                    */
  387.     setVBEMode(oldMode);        /* Restore previous mode                */
  388. }
  389.