home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 259_01 / scrio.c < prev    next >
Text File  |  1988-02-25  |  19KB  |  573 lines

  1.  
  2. /***************************************************************************/
  3. /* SCRIO    - Routines which directly access the video screen           */
  4. /*                                       */
  5. /*                                       */
  6. /*                                       */
  7. /***************************************************************************/
  8. /*                 Modification Log                   */
  9. /***************************************************************************/
  10. /* Version   Date   Programmer     -----------  Description  --------------- */
  11. /*                                       */
  12. /* V01.00   112787  Bob Withers  Program intially complete.           */
  13. /*                                       */
  14. /*                                       */
  15. /***************************************************************************/
  16.  
  17. #include <stdlib.h>
  18. #include <stddef.h>
  19. #include <dos.h>
  20. #include <string.h>
  21. #include "win.h"
  22.  
  23. #define MAXDIM(array)           (sizeof(array) / sizeof(array[0]))
  24.  
  25. #define SCR_BYTES_PER_ROW       160
  26. #define CGA_MODE_SEL           0x3d8
  27. #define CGA_ENABLE           0x29
  28. #define CGA_DISABLE           0x21
  29.  
  30. #define BIOS_VID_INT           0x10
  31. #define BIOS_VID_SET_CRTMODE       0
  32. #define BIOS_VID_SET_CURSORTYPE    1
  33. #define BIOS_VID_SET_CURSORPOS       2
  34. #define BIOS_VID_GET_CURSORPOS       3
  35. #define BIOS_VID_SCROLL_UP       6
  36. #define BIOS_VID_SCROLL_DOWN       7
  37. #define BIOS_VID_WRITE_CHATTR       9
  38. #define BIOS_VID_GET_CRTMODE       15
  39.  
  40.  
  41. struct sBoxType
  42. {
  43.     BYTE        cUpperLeft;
  44.     BYTE        cLowerLeft;
  45.     BYTE        cUpperRight;
  46.     BYTE        cLowerRight;
  47.     BYTE        cLeft;
  48.     BYTE        cRight;
  49.     BYTE        cTop;
  50.     BYTE        cBottom;
  51. };
  52. typedef struct sBoxType BOXTYPE;
  53.  
  54.  
  55. unsigned        uScrSeg     = 0xb800;
  56. unsigned        uCsrType    = 0x0107;
  57. short            nCurrActivePage = 0;
  58. short            nVideoCard    = VIDEO_CGA;
  59. short            nScrCols    = 80;
  60.  
  61.  
  62. /***************************************************************************/
  63. /*  ScrCvtAttr      - Test for a monochrome video card and convert the       */
  64. /*            requested attribute to black & white as best we can    */
  65. /*            and still honor the callers request.           */
  66. /*  Parms:                                   */
  67. /*    nAttr      - The passed color attribute.                */
  68. /*                                       */
  69. /*  Return Value:   A converted black & white attribute if the current       */
  70. /*            video mode is monochrome.                   */
  71. /***************************************************************************/
  72.  
  73. static short near pascal ScrCvtAttr(nAttr)
  74. register short      nAttr;
  75. {
  76.     short     nRev, nClr, nBlink, nIntensity;
  77.  
  78.     if (VIDEO_MONO != nVideoCard)
  79.     return(nAttr);
  80.     nIntensity = nAttr & 0x40;
  81.     nBlink     = nAttr & 0x80;
  82.     nRev       = nAttr & 0x70;
  83.     nClr       = nAttr & 0x07;
  84.     if (REV_BLACK == nRev)
  85.     nClr = WHITE;
  86.     else
  87.     {
  88.     nRev = REV_WHITE;
  89.     nClr = BLACK;
  90.     }
  91.     return(nRev | nClr | nBlink | nIntensity);
  92. }
  93.  
  94.  
  95. /***************************************************************************/
  96. /*  ScrEnableVideoCGA - Test the current video equipment for a snowy CGA   */
  97. /*            card.  If running on a CGA enable/disable the       */
  98. /*            video signal based on the passed parameter which   */
  99. /*            MUST be one of the predefined constants CGA_ENABLE */
  100. /*            or CGA_DISABLE.  If the current video equipment is */
  101. /*            not a CGA, the routine returns without taking any  */
  102. /*            action.                        */
  103. /*  Parms:                                   */
  104. /*    nStatus          - Enable or disable the CGA video signal           */
  105. /*                CGA_ENABLE or CGA_DISABLE               */
  106. /*                                       */
  107. /*  Return Value:    None                           */
  108. /***************************************************************************/
  109.  
  110. static void pascal ScrEnableVideoCGA(nStatus)
  111. short        nStatus;
  112. {
  113.     if (VIDEO_CGA == nVideoCard)
  114.     outp(CGA_MODE_SEL, nStatus);
  115.     return;
  116. }
  117.  
  118.  
  119. /***************************************************************************/
  120. /*  ScrGetRectSize - This routine will calculate and return the number of  */
  121. /*             bytes required to store a screen image which is nWidth*/
  122. /*             columns by nHeight rows.                   */
  123. /*  Parms:                                   */
  124. /*    nWidth       - Column width of the screen rectangle           */
  125. /*    nHeight       - Number of rows in the screen rectangle           */
  126. /*                                       */
  127. /*  Return Value:    Size in bytes required to store the screen rectangle  */
  128. /***************************************************************************/
  129.  
  130. short pascal ScrGetRectSize(nWidth, nHeight)
  131. short        nWidth, nHeight;
  132. {
  133.     return(nWidth * nHeight * 2);
  134. }
  135.  
  136.  
  137. /***************************************************************************/
  138. /*  ScrClearRect - This routine will clear a screen rectangle to the       */
  139. /*           color attribute passed.                   */
  140. /*  Parms:                                   */
  141. /*    nRow     - Row of the screen rectangle                   */
  142. /*    nCol     - Column of the screen rectangle               */
  143. /*    nWidth     - Width in columns of the screen rectangle           */
  144. /*    nHeight     - Number of rows in the screen rectangle           */
  145. /*    nAttr     - Color attribute used to clear screen rectangle       */
  146. /*                                       */
  147. /*  Return Value:  None                            */
  148. /***************************************************************************/
  149.  
  150. void pascal ScrClearRect(nRow, nCol, nWidth, nHeight, nAttr)
  151. short             nRow, nCol, nWidth, nHeight, nAttr;
  152. {
  153.     auto     union REGS     r;
  154.  
  155.     nAttr  = ScrCvtAttr(nAttr);
  156.     r.h.ah = (BYTE) BIOS_VID_SCROLL_UP;
  157.     r.h.al = 0;
  158.     r.h.bh = (BYTE) nAttr;
  159.     r.h.ch = (BYTE) (nRow - 1);
  160.     r.h.cl = (BYTE) (nCol - 1);
  161.     r.h.dh = (BYTE) (nRow + nHeight - 2);
  162.     r.h.dl = (BYTE) (nCol + nWidth - 2);
  163.     int86(BIOS_VID_INT, &r, &r);
  164.     return;
  165. }
  166.  
  167.  
  168. /***************************************************************************/
  169. /*  ScrSaveRect - This routine will save a screen rectangle in a caller    */
  170. /*          supplied buffer area.  nRow, nCol define the row and       */
  171. /*          column of the upper left corner of the rectangle.       */
  172. /*  Parms:                                   */
  173. /*    nRow    - Row of the screen rectangle                   */
  174. /*    nCol    - Column of the screen rectangle               */
  175. /*    nWidth    - Width in columns of the screen rectangle           */
  176. /*    nHeight    - Number of rows in the screen rectangle           */
  177. /*    pBuf    - Buffer used to store the saved screen rectangle       */
  178. /*                                       */
  179. /*  Return Value:  None                            */
  180. /***************************************************************************/
  181.  
  182. void pascal ScrSaveRect(nRow, nCol, nWidth, nHeight, pBuf)
  183. short       nRow, nCol, nWidth, nHeight;
  184. char      *pBuf;
  185. {
  186.     register unsigned        uNumRows;
  187.     register unsigned        uColLen;
  188.     auto     unsigned        uScrOfs;
  189.     auto     unsigned        uBufSeg, uBufOfs;
  190.     auto     char far       *fpBuf;
  191.  
  192.     uColLen = nWidth * 2;
  193.     uScrOfs = ((nRow - 1) * SCR_BYTES_PER_ROW) + (nCol - 1) * 2;
  194.     fpBuf   = (char far *) pBuf;
  195.     uBufSeg = FP_SEG(fpBuf);
  196.     uBufOfs = FP_OFF(fpBuf);
  197.     ScrEnableVideoCGA(CGA_DISABLE);
  198.     for (uNumRows = nHeight; uNumRows > 0; --uNumRows)
  199.     {
  200.     movedata(uScrSeg, uScrOfs, uBufSeg, uBufOfs, uColLen);
  201.     uScrOfs += SCR_BYTES_PER_ROW;
  202.     uBufOfs += uColLen;
  203.     }
  204.     ScrEnableVideoCGA(CGA_ENABLE);
  205.     return;
  206. }
  207.  
  208.  
  209. /***************************************************************************/
  210. /*  ScrRestoreRect - This routine will restore a screen rectangle from       */
  211. /*             a previously saved caller buffer.    nRow and nCol       */
  212. /*             define the upper left corner of the rectangle on       */
  213. /*             the screen and are not required to be the same       */
  214. /*             coordinates used in the save call.  nWidth and       */
  215. /*             nHeight should remain unchanged from the save call    */
  216. /*             but are not required to do so.               */
  217. /*  Parms:                                   */
  218. /*    nRow    - Row of the screen rectangle                   */
  219. /*    nCol    - Column of the screen rectangle               */
  220. /*    nWidth    - Width in columns of the screen rectangle           */
  221. /*    nHeight    - Number of rows in the screen rectangle           */
  222. /*    pBuf    - Buffer used to restore the saved screen rectangle       */
  223. /*                                       */
  224. /*  Return Value:  None                            */
  225. /***************************************************************************/
  226.  
  227. void pascal ScrRestoreRect(nRow, nCol, nWidth, nHeight, pBuf)
  228. short       nRow, nCol, nWidth, nHeight;
  229. char      *pBuf;
  230. {
  231.     register unsigned        uNumRows;
  232.     register unsigned        uColLen;
  233.     auto     unsigned        uScrOfs;
  234.     auto     unsigned        uBufSeg, uBufOfs;
  235.     auto     char far       *fpBuf;
  236.  
  237.     uColLen = nWidth * 2;
  238.     uScrOfs = ((nRow - 1) * SCR_BYTES_PER_ROW) + (nCol - 1) * 2;
  239.     fpBuf   = (char far *) pBuf;
  240.     uBufSeg = FP_SEG(fpBuf);
  241.     uBufOfs = FP_OFF(fpBuf);
  242.     ScrEnableVideoCGA(CGA_DISABLE);
  243.     for (uNumRows = nHeight; uNumRows > 0; --uNumRows)
  244.     {
  245.     movedata(uBufSeg, uBufOfs, uScrSeg, uScrOfs, uColLen);
  246.     uScrOfs += SCR_BYTES_PER_ROW;
  247.     uBufOfs += uColLen;
  248.     }
  249.     ScrEnableVideoCGA(CGA_ENABLE);
  250.     return;
  251. }
  252.  
  253.  
  254. /***************************************************************************/
  255. /*  ScrScrollRectUp   - Scrolls a screen rectangle up the requested number */
  256. /*            of lines.                       */
  257. /*  Parms:                                   */
  258. /*    nRow    - Row of the screen rectangle                   */
  259. /*    nCol    - Column of the screen rectangle               */
  260. /*    nWidth    - Width in columns of the screen rectangle           */
  261. /*    nHeight    - Number of rows in the screen rectangle           */
  262. /*    nNoRows    - Number of rows to scroll                   */
  263. /*    nAttr    - Color attribute to fill blank line on bottom           */
  264. /*                                       */
  265. /*  Return Value:  None                            */
  266. /***************************************************************************/
  267.  
  268. void pascal ScrScrollRectUp(nRow, nCol, nWidth, nHeight, nNoRows, nAttr)
  269. short     nRow, nCol, nWidth, nHeight, nNoRows, nAttr;
  270. {
  271.     auto     union REGS      r;
  272.  
  273.     nAttr  = ScrCvtAttr(nAttr);
  274.     r.h.ah = BIOS_VID_SCROLL_UP;
  275.     r.h.al = (BYTE) nNoRows;
  276.     r.h.bh = (BYTE) nAttr;
  277.     r.h.ch = (BYTE) (nRow - 1);
  278.     r.h.cl = (BYTE) (nCol - 1);
  279.     r.h.dh = (BYTE) (nRow + nHeight - 2);
  280.     r.h.dl = (BYTE) (nCol + nWidth - 2);
  281.     int86(BIOS_VID_INT, &r, &r);
  282.     return;
  283. }
  284.  
  285.  
  286. /***************************************************************************/
  287. /*  ScrScrollRectDown - Scrolls a screen rectangle up the requested number */
  288. /*            of lines.                       */
  289. /*  Parms:                                   */
  290. /*    nRow    - Row of the screen rectangle                   */
  291. /*    nCol    - Column of the screen rectangle               */
  292. /*    nWidth    - Width in columns of the screen rectangle           */
  293. /*    nHeight    - Number of rows in the screen rectangle           */
  294. /*    nNoRows    - Number of rows to scroll                   */
  295. /*    nAttr    - Color attribute to fill blank lines on top           */
  296. /*                                       */
  297. /*  Return Value:  None                            */
  298. /***************************************************************************/
  299.  
  300. void pascal ScrScrollRectDown(nRow, nCol, nWidth, nHeight, nNoRows, nAttr)
  301. short     nRow, nCol, nWidth, nHeight, nNoRows, nAttr;
  302. {
  303.     auto     union REGS      r;
  304.  
  305.     nAttr  = ScrCvtAttr(nAttr);
  306.     r.h.ah = BIOS_VID_SCROLL_DOWN;
  307.     r.h.al = (BYTE) nNoRows;
  308.     r.h.bh = (BYTE) nAttr;
  309.     r.h.ch = (BYTE) (nRow - 1);
  310.     r.h.cl = (BYTE) (nCol - 1);
  311.     r.h.dh = (BYTE) (nRow + nHeight - 2);
  312.     r.h.dl = (BYTE) (nCol + nWidth - 2);
  313.     int86(BIOS_VID_INT, &r, &r);
  314.     return;
  315. }
  316.  
  317.  
  318. /***************************************************************************/
  319. /*  ScrSetCursorPos - This routine will position the cursor to an absolute */
  320. /*              screen coordinate using the BIOS video services.       */
  321. /*  Parms:                                   */
  322. /*    nRow        - Absolute screen row                   */
  323. /*    nCol        - Absolute screen column                   */
  324. /*                                       */
  325. /*  Return Value      None                           */
  326. /***************************************************************************/
  327.  
  328. void pascal ScrSetCursorPos(nRow, nCol)
  329. short        nRow, nCol;
  330. {
  331.     auto     union REGS     r;
  332.  
  333.     r.h.ah = BIOS_VID_SET_CURSORPOS;
  334.     r.h.dh = (BYTE) (nRow - 1);
  335.     r.h.dl = (BYTE) (nCol - 1);
  336.     r.h.bh = (BYTE) nCurrActivePage;
  337.     int86(BIOS_VID_INT, &r, &r);
  338.     return;
  339. }
  340.  
  341.  
  342. /***************************************************************************/
  343. /*  ScrGetCursorPos - This routine will return the current absolute       */
  344. /*              cursor position.                       */
  345. /*  Parms:                                   */
  346. /*    nRow        - Pointer to location to save current row           */
  347. /*    nCol        - Pointer to location to save current column       */
  348. /*                                       */
  349. /*  Return Value:     None                           */
  350. /***************************************************************************/
  351.  
  352. void pascal ScrGetCursorPos(nRow, nCol)
  353. short        *nRow, *nCol;
  354. {
  355.     auto     union REGS     r;
  356.  
  357.     r.h.ah = BIOS_VID_GET_CURSORPOS;
  358.     r.h.bh = (BYTE) nCurrActivePage;
  359.     int86(BIOS_VID_INT, &r, &r);
  360.     *nRow  = r.h.dh + 1;
  361.     *nCol  = r.h.dl + 1;
  362.     return;
  363. }
  364.  
  365.  
  366. /***************************************************************************/
  367. /*  ScrCusrosOn     - Enables the screen cursor.               */
  368. /*                                       */
  369. /*  Parms:          None                           */
  370. /*                                       */
  371. /*  Return Value:     None                           */
  372. /***************************************************************************/
  373.  
  374. void pascal ScrCursorOn()
  375. {
  376.     auto     union REGS     r;
  377.  
  378.     r.h.ah = BIOS_VID_SET_CURSORTYPE;
  379.     r.x.cx = uCsrType;
  380.     int86(BIOS_VID_INT, &r, &r);
  381.     return;
  382. }
  383.  
  384.  
  385. /***************************************************************************/
  386. /*  ScrCusrosOff    - Disables the screen cursor.               */
  387. /*                                       */
  388. /*  Parms:          None                           */
  389. /*                                       */
  390. /*  Return Value:     None                           */
  391. /***************************************************************************/
  392.  
  393. void pascal ScrCursorOff()
  394. {
  395.     auto     union REGS     r;
  396.  
  397.     r.h.ah = BIOS_VID_SET_CURSORTYPE;
  398.     r.x.cx = 0x0f00;
  399.     int86(BIOS_VID_INT, &r, &r);
  400.     return;
  401. }
  402.  
  403.  
  404. /***************************************************************************/
  405. /*  ScrTextOut - This function uses the BIOS write character and attribute */
  406. /*         service routine to display a string within a window.  The */
  407. /*         passed nCount is used to limit a string from overflowing  */
  408. /*         a window boundry.                       */
  409. /*  Parms:                                   */
  410. /*    pStr     - Pointer to the string to be displayed               */
  411. /*    nAttr    - Color attribute used to display string            */
  412. /*    nCount   - Maximum number of characters to dispalay           */
  413. /*                                       */
  414. /*  Return Value: None                               */
  415. /***************************************************************************/
  416.  
  417. void pascal ScrTextOut(pStr, nAttr, nCount)
  418. register char    *pStr;
  419. short         nAttr, nCount;
  420. {
  421.     register short        i;
  422.     auto     short        nRow, nCol;
  423.     auto     union REGS     r, r1;
  424.  
  425.     ScrGetCursorPos(&nRow, &nCol);
  426.     nAttr  = ScrCvtAttr(nAttr);
  427.     r.h.ah = BIOS_VID_WRITE_CHATTR;
  428.     r.h.bh = (BYTE) nCurrActivePage;
  429.     r.h.bl = (BYTE) nAttr;
  430.     r.x.cx = 1;
  431.     while (*pStr && nCount-- > 0)
  432.     {
  433.     ScrSetCursorPos(nRow, nCol++);
  434.     r.h.al = *pStr++;
  435.     int86(BIOS_VID_INT, &r, &r1);
  436.     }
  437.     return;
  438. }
  439.  
  440.  
  441. /***************************************************************************/
  442. /*  ScrDrawRect - This routine is used to draw borders around a screen       */
  443. /*          window.  The passed parameters define the rectangle       */
  444. /*          being used by the window as well as the border color       */
  445. /*          and type.                           */
  446. /*  Parms:                                   */
  447. /*    nRow    - Top row of screen border                   */
  448. /*    nCol    - Left column of screen border                   */
  449. /*    nWidth    - Column width of the window                   */
  450. /*    nHeight    - Number of rows in the window                   */
  451. /*    nColor    - Color attribute for the window border            */
  452. /*    nType    - Type of border to be displayed               */
  453. /*                                       */
  454. /*  Return Value: None                               */
  455. /***************************************************************************/
  456.  
  457. void pascal ScrDrawRect(nRow, nCol, nWidth, nHeight, nColor, nType)
  458. short        nRow, nCol, nWidth, nHeight, nColor, nType;
  459. {
  460.     register short       i;
  461.     auto     union REGS    r, r1;
  462.     static   BOXTYPE       BoxTypes[] =
  463.     {
  464.     {  32,    32,  32,  32,  32,  32,  32,  32 }, /* NO_BOX           */
  465.     { 213, 212, 184, 190, 179, 179, 205, 205 }, /* DBL_LINE_TOP_BOTTOM */
  466.     { 214, 211, 183, 189, 186, 186, 196, 196 }, /* DBL_LINE_SIDES       */
  467.     { 201, 200, 187, 188, 186, 186, 205, 205 }, /* DBL_LINE_ALL_SIDES  */
  468.     { 218, 192, 191, 217, 179, 179, 196, 196 }, /* SNGL_LINE_ALL_SIDES */
  469.     { 219, 219, 219, 219, 219, 219, 223, 220 }  /* GRAPHIC BOX     */
  470.     };
  471.  
  472.     if (nType < 0 || nType >= MAXDIM(BoxTypes))
  473.     return;
  474.     if (nWidth < 2 || nHeight < 2)
  475.     return;
  476.     nColor = ScrCvtAttr(nColor);
  477.  
  478.     /* Draw upper left corner */
  479.     ScrSetCursorPos(nRow, nCol);
  480.     r.h.ah = (BYTE) BIOS_VID_WRITE_CHATTR;
  481.     r.h.al = (BYTE) BoxTypes[nType].cUpperLeft;
  482.     r.h.bh = (BYTE) nCurrActivePage;
  483.     r.h.bl = (BYTE) nColor;
  484.     r.x.cx = 1;
  485.     int86(BIOS_VID_INT, &r, &r1);
  486.  
  487.     /* Draw upper right corner */
  488.     ScrSetCursorPos(nRow, nCol + nWidth - 1);
  489.     r.h.al = (BYTE) BoxTypes[nType].cUpperRight;
  490.     int86(BIOS_VID_INT, &r, &r1);
  491.  
  492.     /* Draw lower left corner */
  493.     ScrSetCursorPos(nRow + nHeight - 1, nCol);
  494.     r.h.al = (BYTE) BoxTypes[nType].cLowerLeft;
  495.     int86(BIOS_VID_INT, &r, &r1);
  496.  
  497.     /* Draw lower right corner */
  498.     ScrSetCursorPos(nRow + nHeight - 1, nCol + nWidth - 1);
  499.     r.h.al = (BYTE) BoxTypes[nType].cLowerRight;
  500.     int86(BIOS_VID_INT, &r, &r1);
  501.  
  502.     if (nHeight > 2)
  503.     {
  504.     /* Draw left side line */
  505.     r.h.al = (BYTE) BoxTypes[nType].cLeft;
  506.     for (i = 1; i <= nHeight - 2; ++i)
  507.     {
  508.         ScrSetCursorPos(nRow + i, nCol);
  509.         int86(BIOS_VID_INT, &r, &r1);
  510.     }
  511.  
  512.     /* Draw right side line */
  513.     r.h.al = (BYTE) BoxTypes[nType].cRight;
  514.     for (i = 1; i <= nHeight - 2; ++i)
  515.     {
  516.         ScrSetCursorPos(nRow + i, nCol + nWidth - 1);
  517.         int86(BIOS_VID_INT, &r, &r1);
  518.     }
  519.     }
  520.  
  521.     if (nWidth > 2)
  522.     {
  523.     /* Draw top line */
  524.     ScrSetCursorPos(nRow, nCol + 1);
  525.     r.h.al = (BYTE) BoxTypes[nType].cTop;
  526.     r.x.cx = nWidth - 2;
  527.     int86(BIOS_VID_INT, &r, &r1);
  528.  
  529.     /* Draw bottom line */
  530.     ScrSetCursorPos(nRow + nHeight - 1, nCol + 1);
  531.     r.h.al = BoxTypes[nType].cBottom;
  532.     int86(BIOS_VID_INT, &r, &r1);
  533.     }
  534.  
  535.     return;
  536. }
  537.  
  538.  
  539. /***************************************************************************/
  540. /*  ScrInitialize - Determine type of video card and init global data.       */
  541. /*                                       */
  542. /*  Parms:        None                           */
  543. /*                                       */
  544. /*  Return Value:   None                           */
  545. /***************************************************************************/
  546.  
  547. void pascal ScrInitialize()
  548. {
  549.     auto     union REGS     r;
  550.  
  551.     r.h.ah = BIOS_VID_GET_CURSORPOS;
  552.     r.h.bh = (BYTE) nCurrActivePage;
  553.     int86(BIOS_VID_INT, &r, &r);
  554.     uCsrType = r.x.cx;
  555.  
  556.     r.h.ah = BIOS_VID_GET_CRTMODE;
  557.     int86(BIOS_VID_INT, &r, &r);
  558.     nScrCols        = r.h.ah;
  559.     nCurrActivePage = r.h.bh;
  560.     if (7 == r.h.al)
  561.     {
  562.     uScrSeg    = 0xb000;
  563.     nVideoCard = VIDEO_MONO;
  564.     return;
  565.     }
  566.     r.h.ah = BIOS_VID_SET_CRTMODE;
  567.     r.h.al = 3;
  568.     int86(BIOS_VID_INT, &r, &r);
  569.     uScrSeg    = 0xb800;
  570.     nVideoCard = VIDEO_CGA;
  571.     return;
  572. }
  573.