home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c070 / 4.ddi / TOOLS.4 / TCTSRC1.EXE / SCNEWDEV.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-31  |  15.9 KB  |  496 lines

  1. /**
  2. *
  3. * Name        scnewdev -- Select and reset video display device and
  4. *                choose the number of text lines on screen
  5. *
  6. * Synopsis    new_mode = scnewdev(mode,num_rows);
  7. *
  8. *        int new_mode    Error code returned:
  9. *                -1 if requested mode or font are not
  10. *                      supported;
  11. *                actual mode set if no error.
  12. *        int mode    New mode value,
  13. *                or -1 to use existing mode and device.
  14. *        int num_rows    New maximum number of rows on current
  15. *                display device (25, 30, 43, or 50).
  16. *
  17. * Description    This function selects and resets a video adapter and
  18. *        selects the 25- or 30-line or (if possible) the 43- or
  19. *        50-line built-in font.    It also selects the proper
  20. *        print-screen routine and sets the global variable
  21. *        b_device (declared in BSCREENS.H).
  22. *
  23. *        The permitted values for mode are
  24. *
  25. *         Mode   Device    Description
  26. *         ----  --------   ------------------------------------------
  27. *           0   SC_COLOR   40 x 25 Black and White
  28. *           1   SC_COLOR   40 x 25 Color burst enabled
  29. *           2   SC_COLOR   80 x 25 Black and White
  30. *           3   SC_COLOR   80 x 25 Color burst enabled
  31. *           4   SC_COLOR   320 x 200 Color burst enabled
  32. *           5   SC_COLOR   320 x 200 Black and White
  33. *           6   SC_COLOR   640 x 200 Black and White
  34. *           7   SC_MONO    Monochrome Adapter or EGA + Monochrome
  35. *                Display or VGA
  36. *           8   SC_COLOR   160 x 200 Color         (PCjr only)
  37. *           9   SC_COLOR   320 x 200 Color         (PCjr only)
  38. *          10   SC_COLOR   640 x 200 Color         (PCjr only)
  39. *          13   SC_COLOR   320 x 200 Color       (EGA or VGA only)
  40. *          14   SC_COLOR   640 x 200 Color       (EGA or VGA only)
  41. *          15   SC_MONO    640 x 350 Monochrome (EGA or VGA only)
  42. *          16   SC_COLOR   640 x 350 Color       (EGA or VGA only)
  43. *          17   SC_COLOR   640 x 480 Color      (VGA or MCGA only)
  44. *          18   SC_COLOR   640 x 480 Color          (VGA only)
  45. *          19   SC_COLOR   320 x 200 Color      (VGA or MCGA only)
  46. *
  47. *        An error occurs if the mode is not supported by the
  48. *        installed hardware or if the requested font is not
  49. *        supported by the requested device.  In this case no
  50. *        action occurs and -1 is returned as the value of the
  51. *        function.
  52. *
  53. * Method    This routine first checks for the presence of the
  54. *        required device and validates the mode and font
  55. *        requested.  If the device is present and the mode and
  56. *        font are supportable, SCNEWDEV then sets the BIOS
  57. *        equipment word to select the new device.  If the new
  58. *        device is an Enhanced Graphics Adapter, the BIOS cursor
  59. *        compensation bit is set according to the font.    Then the
  60. *        new device is reset, clearing the screen.  Page 0 is
  61. *        selected as active (currently displayed) and current
  62. *        (selected for output via Blaise C TOOLS screen I/O
  63. *        routines).  The standard underline cursor is left at the
  64. *        upper left corner of each page.  If 43 or more lines are
  65. *        requested, the proper font is selected.
  66. *
  67. * Returns    new_mode       Error code returned:
  68. *                -1 if requested mode or font are not
  69. *                      supported;
  70. *                actual mode set if no error.
  71. *        b_device       Adapter used (SC_COLOR or SC_MONO).
  72. *
  73. * Version    6.00  (C)Copyright Blaise Computing Inc. 1986-1989
  74. *
  75. **/
  76.  
  77. #include <dos.h>
  78.  
  79. #include <bscreens.h>
  80.  
  81. int b_vidcpy(int,int);              /* Internal (see below)          */
  82.  
  83. #define  FROM_BIOS    0          /* Direction flags for copying  */
  84. #define  TO_BIOS    1          /* BIOS video state variables.  */
  85.  
  86. #define  VIDEO_FIELD  0x0030          /* The bits to be modified in   */
  87.                       /* the BIOS equipment word.     */
  88. #define  MONO_FLAG    0x0030
  89. #define  COLOR_80     0x0020
  90. #define  COLOR_40     0x0010
  91.  
  92. int b_vidcpy(int,int);              /* Internal (see below)          */
  93.  
  94. #define  FROM_BIOS    0          /* Direction flags for copying  */
  95. #define  TO_BIOS    1          /* BIOS video state variables.  */
  96.  
  97.                   /* Address of BIOS equipment word.      */
  98. #define  EQUIP_LOC     (uttofar(0x0040,0x0010,unsigned int))
  99.  
  100.                   /* Address of BIOS INFO byte.          */
  101. #define  INFO_LOC     (uttofar(0x0040,0x0087,unsigned char))
  102.  
  103. int scnewdev(mode,num_rows)
  104. int mode,num_rows;
  105. {
  106.     int   old_dev,old_mode,old_act_page,old_cols;
  107.     int   device;
  108.     union REGS inregs,outregs;
  109.  
  110.     int  our_word;              /* Our copy of equipment word.  */
  111.     int  old_flag,new_flag;          /* Old and new values of video  */
  112.                       /* device bit field.          */
  113.  
  114.     char old_info;              /* Our copy of former INFO byte */
  115.     char new_info;
  116.  
  117.     /* Note current state of BIOS.                      */
  118.  
  119.     old_dev = scmode(&old_mode,&old_cols,&old_act_page);
  120.  
  121.     /* Check validity of mode and font requested              */
  122.  
  123.     scequip();                  /* Sense hardware settings.     */
  124.  
  125.     if (mode == -1)
  126.     mode = old_mode;          /* Use existing mode          */
  127.     switch (mode)
  128.     {                      /* Determine requested device.  */
  129.  
  130.                       /* PCjr color modes:          */
  131.     case 8:
  132.     case 9:
  133.     case 10:
  134.         if (b_pcmodel != IBM_JR)
  135.         return -1;
  136.                       /* CGA color modes:          */
  137.     case 4:
  138.     case 5:
  139.     case 6:
  140.         if (num_rows != 25)
  141.         return -1;
  142.     case 0:
  143.     case 1:
  144.     case 2:
  145.     case 3:
  146.                       /* This is a color mode,          */
  147.                       /* so check for color device.   */
  148.         if (   b_cga != SC_COLOR  && b_pcmodel != IBM_JR
  149.         && b_ega != SC_COLOR  && b_pgc       != SC_COLOR
  150.         && b_vga == SC_ABSENT && b_mcga    == SC_ABSENT)
  151.         return -1;          /* Color/Graphics Adapter       */
  152.                       /* functions are not available. */
  153.  
  154.         device   = SC_COLOR;
  155.         new_flag = COLOR_80;
  156.         break;
  157.  
  158.                       /* EGA-only color modes:          */
  159.     case 13:
  160.     case 14:
  161.         if (num_rows != 25)
  162.         return -1;
  163.     case 16:
  164.         if (   num_rows > 43
  165.         || (b_ega != SC_COLOR && b_vga == SC_ABSENT))
  166.         return -1;
  167.         device   = SC_COLOR;
  168.         new_flag = COLOR_80;
  169.         break;
  170.  
  171.                       /* Monochrome modes:          */
  172.     case 15:
  173.         if (   num_rows > 43
  174.         || (b_ega != SC_MONO && b_vga == SC_ABSENT))
  175.         return -1;
  176.     case 7:
  177.                    /* This is a monochrome mode,      */
  178.                    /* so check for monochrome device. */
  179.         if (b_mdpa != SC_MONO && b_ega != SC_MONO && b_vga == SC_ABSENT)
  180.         return -1;          /* Monochrome Adapter functions */
  181.                       /* are not available.          */
  182.  
  183.         new_flag = MONO_FLAG;     /* Monochrome functions found.  */
  184.         device   = SC_MONO;
  185.         break;
  186.  
  187.                       /* VGA/MCGA modes:          */
  188.     case 18:
  189.         if (b_vga == SC_ABSENT)
  190.         return -1;
  191.     case 17:
  192.         if (   (num_rows != 30 && num_rows != 60)
  193.         || (b_vga == SC_ABSENT && b_mcga == SC_ABSENT))
  194.         return -1;
  195.         device   = SC_COLOR;
  196.         new_flag = COLOR_80;
  197.         break;
  198.  
  199.     case 19:
  200.         if (   num_rows != 25
  201.         || (b_vga == SC_ABSENT && b_mcga == SC_ABSENT))
  202.         return -1;
  203.         device   = SC_COLOR;
  204.         new_flag = COLOR_80;
  205.         break;
  206.  
  207.     default:
  208.         return -1;              /* Unknown mode.              */
  209.     }
  210.  
  211.     if (device == b_mdpa && mode != 7)
  212.     return -1;
  213.     if (   (device == b_cga || device == b_pgc)
  214.     && mode > 6)
  215.     return -1;
  216.  
  217.     switch (num_rows)
  218.     {
  219.     case 25:              /* 25-line mode:              */
  220.         break;              /* no further checking needed.  */
  221.  
  222.     case 30:              /* 30-line and 60-line require  */
  223.     case 60:              /* mode 17 or 18.           */
  224.         if (mode != 17 && mode != 18)
  225.         return -1;
  226.         break;
  227.  
  228.     case 43:              /* 43-line mode:          */
  229.         if (   device == b_mdpa      /*   can't run on MDPA      */
  230.         || device == b_cga      /*   or on CGA          */
  231.         || device == b_pgc      /*   or on PGC in CGA mode  */
  232.         || b_mcga != SC_ABSENT      /*   or if MCGA present;    */
  233.         || (   device == b_ega      /*   if on EGA          */
  234.             && device == SC_COLOR /*     in color mode,       */
  235.             && b_sw_ega != 0x9      /*     must have ECD in     */
  236.             && b_sw_ega != 0x3))  /*     high-res mode.       */
  237.         return -1;
  238.         break;
  239.  
  240.     case 50:              /* 50-line mode requires          */
  241.                       /* VGA or MCGA.              */
  242.         if (   device == b_mdpa
  243.         || device == b_cga
  244.         || device == b_ega
  245.         || (b_vga == SC_ABSENT && b_mcga == SC_ABSENT))
  246.         return -1;
  247.         break;
  248.  
  249.     default:
  250.         return -1;              /* Unknown number of lines.     */
  251.     }
  252.  
  253.     /* Validation complete:  now switch devices if necessary          */
  254.  
  255.     /* Record current BIOS variables in case we ever need to change   */
  256.     /* back to the old device.                          */
  257.  
  258.     if (b_vidcpy(FROM_BIOS,old_dev))
  259.     return -1;
  260.  
  261.     /* If we are switching VGA from color to monochrome or vice       */
  262.     /* versa, note the change in our global variables.              */
  263.  
  264.     if (   device != b_mdpa && device != b_cga && device != b_ega
  265.     && device != b_pgc)
  266.     {
  267.     if (b_vga == old_dev)
  268.         b_vga = device;
  269.     }
  270.  
  271.     /* For 43-line text modes on VGA, set scan lines to 350.          */
  272.     /* However, this works only if VGA is the former device.          */
  273.  
  274.     if (   device == b_vga
  275.     && device == old_dev
  276.     && ((0 <= mode && mode <= 3) || mode == 7))
  277.     {
  278.     inregs.h.ah = 0x12;             /* Alternate select.     */
  279.     inregs.h.bl = 0x30;             /* Scan lines.          */
  280.     inregs.h.al = (unsigned char)
  281.               (num_rows == 43 ? 1    /* 350 scan lines.       */
  282.                       : 2);  /* 400 scan lines.       */
  283.     int86(SC_BIOS_INT,&inregs,&outregs);
  284.     }
  285.  
  286.     /* The BIOS keeps track of the color vs. monochrome distinction   */
  287.     /* by two bits in the equipment word, so we must poke those bits  */
  288.     /* to signal the change in device.                      */
  289.  
  290.     int86(17,&inregs,&outregs);       /* Retrieve equipment word.     */
  291.     our_word = outregs.x.ax;
  292.  
  293.     old_flag = (our_word & VIDEO_FIELD);
  294.     if (new_flag != old_flag          /* There is a change.          */
  295.         && (old_flag != COLOR_40 || new_flag != COLOR_80))
  296.                       /* (Skip the change if 40-col   */
  297.                       /*   mode is set and we're      */
  298.                       /*   setting color.)          */
  299.     {
  300.                       /* Install modified equipment   */
  301.                       /* word.                  */
  302.     utpokeb(EQUIP_LOC,
  303.         (unsigned char) ((our_word & ~VIDEO_FIELD) | new_flag));
  304.     }
  305.     b_device = device;
  306.  
  307.     /* Handle cursor compensation bit:                      */
  308.     /* The EGA BIOS adjusts the cursor type based on the lower bit of */
  309.     /* the variable called INFO.  When the bit is 0, cursor types are */
  310.     /* automatically adjusted to fit in 14 scan lines; when the bit   */
  311.     /* is 1, cursor types are used as requested.  The BIOS does not   */
  312.     /* maintain this bit.  Therefore we set this bit when in 43-line  */
  313.     /* mode and clear it for 25-line mode.                  */
  314.  
  315.     if (b_ega == device || b_vga == device || b_mcga == device)
  316.     {
  317.                          /* Fetch INFO byte.  */
  318.     old_info = utpeekb(INFO_LOC);
  319.  
  320.     new_info = old_info;
  321.     if (num_rows >= 43)
  322.         new_info |= 1;          /* Set compensation bit          */
  323.                       /* (turn compensation off).     */
  324.     else
  325.         new_info &= (~1);          /* Clear compensation bit       */
  326.                       /* (turn compensation on).      */
  327.  
  328.     if (new_info != old_info)     /* If there is a change,          */
  329.                       /* install the new INFO byte.   */
  330.         utpokeb(INFO_LOC,new_info);
  331.     }
  332.  
  333.     /* Reset new device                           */
  334.  
  335.     inregs.h.ah = 0;
  336.     inregs.h.al = (unsigned char) mode;
  337.     int86(SC_BIOS_INT,&inregs,&outregs);
  338.  
  339.     /* For 43-line text modes on VGA, set scan lines to 350, unless   */
  340.     /* we were able to do so before resetting the mode.  Then reset   */
  341.     /* the mode again.                              */
  342.  
  343.     if (   device == b_vga && device != old_dev
  344.     && ((0 <= mode && mode <= 3) || mode == 7)
  345.     && scrows() != num_rows)
  346.     {
  347.     inregs.h.ah = 0x12;             /* Alternate select.     */
  348.     inregs.h.bl = 0x30;             /* Scan lines.          */
  349.     inregs.h.al = (unsigned char)
  350.               (num_rows == 43 ? 1    /* 350 scan lines.       */
  351.                       : 2);  /* 400 scan lines.       */
  352.     int86(SC_BIOS_INT,&inregs,&outregs);
  353.  
  354.     inregs.h.ah = 0;             /* Reset device again.   */
  355.     inregs.h.al = (unsigned char) mode;
  356.     int86(SC_BIOS_INT,&inregs,&outregs);
  357.     }
  358.  
  359.     /* Load small font if necessary.                      */
  360.  
  361.     if (num_rows >= 43)
  362.     {
  363.     if (mode > 3 && mode != 7)
  364.         inregs.x.ax = 0x1123;     /* Graphics mode.           */
  365.     else
  366.         inregs.x.ax = 0x1112;     /* Text mode.              */
  367.     inregs.h.bl = 0;
  368.     inregs.h.dl = (unsigned char) num_rows;
  369.     int86(SC_BIOS_INT,&inregs,&outregs);
  370.  
  371.     inregs.h.ah = 0x12;          /* Select alternate print screen*/
  372.     inregs.h.bl = 0x20;          /* routine.              */
  373.     int86(SC_BIOS_INT,&inregs,&outregs);
  374.     }
  375.  
  376.     scpage(0);
  377.  
  378.     /* Record new BIOS variables in case SCCHGDEV ever wants to       */
  379.     /* change to the new device.                      */
  380.  
  381.     b_vidcpy(FROM_BIOS,device);
  382.  
  383.     return mode;
  384. }
  385.  
  386. /**
  387. *
  388. * Name        b_vidcpy -- Copy BIOS video state variables.
  389. *
  390. * Synopsis    ercode = b_vidcpy(dir,device);
  391. *
  392. *        int ercode      Result code:
  393. *                   1 if dir or device invalid or if
  394. *                     table information is unavailable;
  395. *                   0 if ok.
  396. *        int dir       Direction:
  397. *                   FROM_BIOS means from BIOS to table,
  398. *                   TO_BIOS   means from table to BIOS.
  399. *        int device      SC_MONO or SC_COLOR to denote which
  400. *                  entry of the b_adap_state table to use.
  401. *
  402. * Description    This function copies the four blocks of BIOS video state
  403. *        variables to or from the table called b_adap_state
  404. *        (defined above).
  405. *
  406. *        If dir is TO_BIOS, the b_adap_state table entry is
  407. *        checked for valid data; if it is marked as invalid, then
  408. *        1 is returned as an error code.
  409. *
  410. *        An error is also reported if dir or device is invalid.
  411. *
  412. * Returns    ercode          Result code:
  413. *                   1 if dir or device invalid or if
  414. *                     table information is unavailable;
  415. *                   0 if ok.
  416. *
  417. **/
  418.  
  419.     /* Internal structure for preserving BIOS video variables          */
  420.  
  421. VIDEO_STATE b_adap_state[2] = {0};    /* One entry for SC_MONO, one   */
  422.                       /* for SC_COLOR.              */
  423.  
  424. int b_vidcpy(dir,device)
  425. int dir,device;
  426. {
  427.     int i;
  428.     int were_on;          /* Flag indicating whether interrupts   */
  429.                   /* were on before we turned them off.   */
  430.  
  431.     /* There are four blocks of BIOS variables that describe the      */
  432.     /* state of an adapter.  Here are tables to help us copy them     */
  433.     /* into the b_adap_state array:                      */
  434.  
  435.     static char *save_area[2][4] =    /* Pointers to the sections of  */
  436.     {                      /* the VIDEO_STATE structures   */
  437.                       /* in the b_adap_state table    */
  438.     {       b_adap_state[0].pc_area,
  439.            b_adap_state[0].video_area,
  440.      (char *) &b_adap_state[0].save_ptr,
  441.           &b_adap_state[0].prtsc_status},
  442.  
  443.     {       b_adap_state[1].pc_area,
  444.            b_adap_state[1].video_area,
  445.      (char *) &b_adap_state[1].save_ptr,
  446.           &b_adap_state[1].prtsc_status}
  447.     };
  448.     static int save_size[4] =          /* Sizes of the four sections   */
  449.     {                      /* of a VIDEO_STATE structure   */
  450.     sizeof(b_adap_state[0].pc_area),
  451.     sizeof(b_adap_state[0].video_area),
  452.     sizeof(b_adap_state[0].save_ptr),
  453.     sizeof(b_adap_state[0].prtsc_status)
  454.     };
  455.     static char far *bios_ptr[4] =    /* Addresses of the four blocks */
  456.     {                      /* of BIOS variables          */
  457.     uttofar(0x0040,0x0049,char),
  458.     uttofar(0x0040,0x0084,char),
  459.     uttofar(0x0040,0x00a8,char),
  460.     uttofar(0x0040,0x0100,char)
  461.     };
  462.  
  463.     if (   (dir    != FROM_BIOS && dir      != TO_BIOS)
  464.     || (device != SC_COLOR    && device != SC_MONO))
  465.     return 1;              /* Invalid code.              */
  466.  
  467.     if (dir == TO_BIOS && !b_adap_state[device].known)
  468.     return 1;              /* Requested table info isn't   */
  469.                       /* valid.               */
  470.  
  471.     were_on = utintoff();          /* Turn interrupts off.          */
  472.  
  473.     for (i = 0; i < 4; i++)          /* For each of the four blocks, */
  474.     {
  475.     if (dir == FROM_BIOS)          /* Copy the block of data       */
  476.         utmovmem(bios_ptr[i],              /* from BIOS*/
  477.              (char far *) save_area[device][i],
  478.              save_size[i]);
  479.     else
  480.         utmovmem((char far *) save_area[device][i],    /* to BIOS */
  481.              bios_ptr[i],
  482.              save_size[i]);
  483.     }
  484.  
  485.     if (were_on)
  486.     utinton();              /* Turn interrupts back on.     */
  487.  
  488.     if (dir == FROM_BIOS)
  489.     {
  490.     b_adap_state[device].curpage = b_curpage;
  491.     b_adap_state[device].known   = 1;/* Flag table info as valid. */
  492.     }
  493.  
  494.     return 0;                  /* Success.              */
  495. }
  496.