На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 9 / Соображения по установке и проверка наличия Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Соображения по установке и проверка наличия

Возможности EGA зависят от типа монитора и объема памяти на плате EGA. Тип монитора определяет, какой видеорежим использовать для графики или текста, а объем памяти EGA определяет число доступных цветов и страниц. Для Ваших программ очень важно узнать, имеется ли в персональном компьютере в наличии EGA, до того, как Вы попытаетесь ее использовать, а также тип применяемого монитора и объем доступной памяти. Это делает программа, приведенная в листинге 9-1. Для указания на структуру с информацией по EGA вызывается функция get_ega_info(&info). Байт 0х40:0х87 преобразует информацию о конфигурации EGA, памяти и мониторе. Этот байт является одним из байтов состояния, которые EGA BIOS содержит для внутреннего использования и обеспечения программ необходимой им информацией.


Мы интересуемся битами 5 и 6, которые показывают полную память EGA; битом 3, который показывает, является ли EGA активным дисплеем; и битом 1, который указывает тип используемого монитора.


Функция также вызывает один из новых вызовов BIOS EGA, альтернативную функцию 10, которая возвращает информацию EGA. EGA вызывается помещением 0х12 в регистр АН и 0х10 в регистр BL, а также использованием прерывания 10h. Вызов EGA BIOS содержит следующую информацию:


                           Возвращаемая информация о EGA

             Результат:  Int 0x10
             Вызывается: AH = 0х12
                         для выбора альтернативных функций EGA
                         BL = 0x10
                         Альтернативная функция для информации EGA
             Возвращает: BH =  0 = Цветной монитор
                               1 = Монохромный монитор
                         BL =  Расшифрованная память EGA:
                               0 = 64К
                               1 = 128К
                               2 = 192К
                               3 = 256К
                         СН =  Биты признаков
                         CL =  Установки переключателей платы EGA

Так как BIOS персонального компьютера не использует видеофункцию 0х12, этот вызов может быть использован в качестве проверки наличия EGA. BIOS персонального компьютера спокойно отклонит неизвестное ей прерывание 10h и не изменит состояния регистров. Таким образом, если выходящие регистры не изменяются вызовом или входящие регистры не соответствуют данным о байте информации EGA, значит EGA отсутствует. Если EGA имеется в наличии, то тип используемого монитора определяется считыванием положения установочных переключателей. Вы предполагаете, что пользователь правильно установил переключатели и их положение соответствует типу монитора.


После обнаружения EGA функция проведет тестирование системы на наличие карты VGA. Большинство регистров EGA только записываемые, в то время как в VGA они являются считываемыми/записываемыми. Регистр устанавливается в определенное значение и затем делается попытка считать это значение. Если считанный байт не соответствует записанному, то имеющаяся карта - EGA, в противном случае - VGA. Используемый регистр является регистром маски бита, который далее будет детально рассмотрен.


Программа EGACHECK.C, приведенная в листинге 9-1, выполняет проверку активной карты EGA. (В системе может присутствовать другая дисплейная карта. Если активна другая карта, то бит 3 байта 0х40:0х87 будет иметь значение 1). Если обнаружена активная карта EGA, то сохраняется информация об установке.


Макрокоманда PEEK_BYTE(seg,off), представленная в листинге 9-1, позволяет выбирать байт из любого места памяти персонального компьютера. Макрокоманда работает путем сдвига значения сегмента влево на одно слово (16 бит) с последующим логическим сложением бита смещения для формирования длинного прерывания. Это прерывание затем сбрасывается в указатель far.


                         Листинг 9-1. Программа EGACHECK.C

         ----------------------------------------------------------------

         /* egacheck.c */
         /* Проверяет наличие карты EGA или VGA */
         /* При нахождении одной из них, информация сохраняется */
         #include 
         #include 
         #include 

         #define PEEK_BYTE(seg,off) \
              (*(char far *) ( (long)(seg)<<16 | (off) ) )

         struct Ega_info     /* для хранения информации о EGA */
         {
           char card ;       /* для хранения типа карты */
           char monitor ;    /* для хранения типа монитора */
           int memory ;      /* объем памяти: 64, 128, 192, 256К */
           char high_res_graphics ;
           char text_mode ;
         }  ;

         int get_ega_info(struct Ega_info *) ;

         main()
         {
         struct Ega_info info ;

         if(get_ega_info(&info))   /* тест на наличие EGA */
          {
          if(info.card == 'E')
            {
            printf("\n\nИспользуется EGA.") ;
            printf("\nПодключена к") ;
            switch(info.monit)
            {
              case 'C': puts(" цветному монитору") ;
                        break ;
              case 'M': puts(" монохромному монитору") ;
                        break ;
              case 'H': puts("усовершенствованному цветному монитору");
                        break ;
              default:  break ;  /* не определен */
            }
            printf("n\%iK байт памяти EGA.", info.memory);
            }
            else
               printf("\n\nИспользуется VGA.") ;
            printf("\nРежим %#2i - графика с высоким разрешением.",
                  (int)info.high_res_graphics) ;
            printf("\nРежим %#2i - текстовый режим.\n\n",
                  (int)info.text_mode) ;
          }
         else
          puts("\nНет активного EGA.") ;
         }                               /* конец main() */


         int get_ega_info(info)
         struct Ega_info *info ;

         /* Эта функция проверяет, есть ли в системе активный EGA */
         {
         union REGS regs ;
         int i, test_mask = 1 ;
         /* Принять байт информации EGA из области данных BIOS */
            char bios_info = PEEK_BYTE(0x40,0x87) ;

            /* Бит 3 показывает, активный EGA или нет
             * если нет, то проверить наличие */
            if(bios_info & 0x8)
               return (0) ; /* если бит 3 = 1, EGA не активный */

            regs.h.ah = 0x12 ; /* альтернативная функция BIOS EGA */
            regs.h.bl = 0x10 ; /* получить информацию */
            regs.h.bh = 0xFF ; /* не возможное значение */
            int86(0x10, ®s, ®s) ; /* видео вызов EGA BIOS */

         /* bios_info биты 5 + 6 и BL(расшифрованная память EGA) и */
         /* bios_info бит 1 и ВН должны быть равны для EGA */
         if((regs.h.bl != ((bios_info & 0x60) >> 5 || /* память */
            (regs.h.bh != ((bios_info & 0x2) >> 1  || /* монитор */
            (regs.h.bh == 0xFF))            /* ВН должен изменить*/
           /* EGA есть, сохранить тип монитора */
           /* Код тип монитора:
                'C' для цветного,
                'M' для монохромного,
                'H' для hercules */
          switch(regs.h.cl) /* cl имеет установку переключателей EGA */
          {
             case 0: /* первоначально моно, EGA цветной 40х25 */
             case 6: /* моно второй, EGA цветной 40х25 */
                    info->monitor = 'C' ;
                    info->high_res_graphics = 0xD ;
                    info->text_mode = 0x1 ;
                    break ;
             case 1:  /* первоначально моно, EGA цветной 80х25 */
             case 2:  /* то же, что 1 */
             case 7:  /* моно второй, EGA цветной 80х25 */
             case 8:  /* то же, что 7 */
                    info->monitor = 'C' ;
                    info->high_res_graphics = 0xE ;
                    info->text_mode = 0x3 ;
                    break ;
             case 3: /* первоначально моно, EGA с высоким разрешением */
             case 9: /* сначала EGA с высоким разрешением, потом моно */
                    info->monitor = 'H' ;
                    info->high_res_graphics = 0x10 ;
                    info->text_mode = 0x3 ;
                    break ;
             case 4:  /* сначала 40 цветной, EGA моно */
             case 5:  /* сначала 80 цветной, EGA моно */
             case 10: /* сначала EGA моно, затем 40 цветной */
             case 11: /* сначала EGA моно, затем 80 цветной */
                    info->monitor = 'M' ;
                    info->high_res_graphics = 0xF ;
                    info->text_mode = 0x7 ;
                    break ;
             default: /* зарезервированные установки переключателей */
             return (0) ;
          }
          info->memory = 64 * (regs.h.bl + 1) ;

          /* Различить EGA и VGA: */
          /* Это выполняется посредством записи значения в только
             считываемый регистр в EGA, но считываемый/записываемый
             в VGA */
         outp(0x3CE, 8) ;         /* маска бита EGA/VGA */
         outp(0x3CF, test_mask) ; /* направить значение теста */
         outp(0x3CE, 8) ;         /* снова маска бита */
         if(inp(0x3CF) == test_mask)
            {
            info->card = 'V' ;    /* регистр можно считать */
            if(info->monitor != 'M')
               {
               info->high_res_graphics = 0x12 ;
               info->text_mode = 0x3 ;
               }
            /* Если подключено к монохромному, то значения уже
             * установлены.
             */
            }
         else
            info->card = 'E' ; /* EGA */
         outp(0x3CE, 8) ;      /* сбросить маску бита */
         outp(0x3CF, 0xFF) ;
         /* В этой системе активен EGA/VGA, вернуть память */
         return(info->memory) ;
         }
         ---------------------------------------------------------------

В новый заглавный файл, названный ega.h, должны быть добавлены прототип функции get_ega_info() и скелет структуры Ega_info. Эти функция и скелет будут использованы в последующих примерах.


Теперь мы знаем, какой режим надо использовать для графики и можем изобразить что-нибудь на дисплее. EGA BIOS, также как и BIOS персонального компьютера имеет вызов Write Dot (писать точку). Этот вызов работает медленно, но очень полезен во всех графических картах IBM. Вот некоторые характеристики вызова EGA BIOS Write Dot:


             Write Dot

             Результат:  Int 0x10

             Вызывается: AН =  0хС для выбора функции Write Dot
                         BH =  Страница
                         DX =  Номер строки
                         СХ =  Номер столбца
                         AL =  Значение цвета

             Возвращает: Ничего

Обратите внимание на добавление в ВН номера страницы. Если Вы преобразуете старое программное обеспечение для работы с EGA, то убедитесь, что номер страницы находится в ВН перед вызовом прерывания 10h. Программы, написанные для монохромного адаптера или CGA в графическом режиме, наиболее чувствительны к этому недостатку.


Вызов BIOS для переключения в графический режим точно такой же, как и функция 0 прерывания 10h персонального компьютера. Тем не менее, BIOS не выполняет проверку на предмет того, не повредит ли выбранный Вами режим Ваш монитор. Монохромный монитор, подключенный к EGA, может быть поврежден сигналом режима цветного текста или графики, поэтому важно проверить совместимость монитора и режима работы. В программе 9-1 функция get_ega_info(&info) используется для проверки монитора и нахождения безопасного в использовании режима работы с высокой разрешающей способностью. Программа, представленная в листинге 9-2, демонстрирует использование функции set_crt_mode() для установки графического режима и использование dot(), которая применяет функцию BIOS Write Dot. Эта программа начертит серию параллельных диагональных линий.


                         Листинг 9-2. Программа DIAGONAL.C
         ---------------------------------------------------------------

         /* diagonal.c */
         /* Демонстрирует графический режим с высоким разрешением */
         #include 
         #include 
         #include 

         void set_crt_mode( char ) ;   /* добавить это в "ega.h" */
         void dot( int, int, int, int ) ;

         main()
         {
           registr i,j ;
           struct Ega_info info ;
           if(get_ega_info(&info))
              set_crt_mode(info.high_res_graphics);
           else
              return(1) ;

           for(j = 0; j <= 500; j += 5)
           for(i = 0; i <= 100; ++i)
               dot(i,i+j,13,0) ;
           getch() ;   /* ожидать символ, который надо изобразить */
           set_crt_mode(info.text_mode) ;
           return(0) ;
         }

         /*==========================================================*/
         void dot(row,col,color,page)
         int row, col, color, page;
         {
            union REGS regs ;
            regs.x.dx = row ;
            regs.x.cx = col ;
            regs.h.al = (char)color ;
            regs.h.ah = (char)0xC ;      /* Вызов Write Dot */
            regs.h.bh = (char)page ;
            int86(0x10, ®s, ®s) ;
         }

         /*==========================================================*/
         void set_crt_mode(mode)
         char mode ;
         {
           union REGS regs ;
           regs.h.al = mode ;         /* al = установить режим */
           regs.h.ah = (char)0 ;      /* Функция "установить режим" */
           int86(0x10, ®s, ®s); /*Выполнить прерывание BIOS 10h*/
         }
         /*==========================================================*/

         ---------------------------------------------------------------

Как только Вы увидите, как медленно работает функция BIOS Write Dot, то, вероятно, спросите, можно ли ускорить ее работу. Реализация этого требует обхода EGA BIOS и помещения элементов изображения непосредственно в память EGA. Тем не менее, сначала Вы должны понять, каким образом организована память EGA, и то, как можно ею управлять.


НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz