[Назад] [Содеожание] [Дальше]

Программирование видеоадаптеров.

© Александр Фролов, Григорий Фролов
Том 21, М.: Диалог-МИФИ, 1993.

7. Видеоадаптеры SVGA

  • Видеопамять SVGA
  • Стандарт VESA
  • Управление монитором
  • Сразу после появления видеоадаптера VGA многие фирмы начали выпуск новых моделей видеоадаптеров, обеспечивающих отображение большего количества цветов и большую разрешающую способность. Такие видеоадаптеры получили общее название Super VGA или SVGA.

    Подавляющее большинство видеоадаптеров SVGA обеспечивают полную совместимость с VGA на уровне регистров. Поэтому все программное обеспечение, разработанное для видеоадаптера VGA, работает с видеоадаптерами SVGA без дополнительных изменений.

    Естественно, чтобы расширить возможности видеоадаптера VGA, пришлось дополнить его новыми регистрами. Видеоадаптеры SVGA имеют значительно больше регистров, чем простые видеоадаптеры VGA. Чтобы видеоадаптер SVGA смог проявить все свои возможности, необходимо, чтобы программное обеспечение правильно использовало все регистры видеоадаптера.

    К сожалению, SVGA не является стандартом, наподобие EGA или VGA. Различные модели видеоадаптера SVGA обладают различным набором регистров, расположенных по разным адресам и выполняющих различные функции. Это значительно затрудняет создание программ, использующих все возможности SVGA, так как такая программа должна правильно определить тип вашего видеоадаптера и работать с ним соответствующим образом.

    Ассоциация VESA разработала стандарт на функции BIOS, позволяющие управлять видеоадаптерами SVGA. Текущая версия стандарта VESA не позволяет реализовать все возможности современных видеоадаптеров, например, отображать геометрические фигуры с использованием аппаратных возможностей акселераторов. Мы опишем стандарт VESA и приведем несколько примеров программирования видеоадаптеров SVGA при помощи функций BIOS.

    Самые широкие возможности для использования видеоадаптеров SVGA предоставляет операционная система Windows. В ней используются специальные драйверы, выполняющие всю работу по программированию видеоадаптеров на аппаратном уровне. Обычно драйверы разрабатываются самой фирмой создавшей видеоадаптер. Поэтому кропотливая работа с регистрами адаптера скрыта от программистов, разрабатывающих программы Windows. Они имеют дело с хорошо документированными высокоуровневыми функциями графического интерфейса.

    Видеопамять SVGA

    Видеоадаптеры SVGA превосходят VGA по разрешению экрана и количеству одновременно отображаемых цветов.

    Лучшие режимы VGA

    Типичные режимы SVGA

    640 x 480; 16 цветов

    800 x 600; 256, 64 К, 16,7 М цветов

    320 x 200; 256 цветов

    1024 x 768; 256, 64 К, 16,7 М цветов

    1280 x 1024; 256, 64 К, 16,7 М цветов

    Чтобы иметь возможность отображать большое количество цветов при большой разрешающей способности, видеоадаптер SVGA должен иметь значительно больше видеопамяти, чем адаптер VGA. Например, для реализации режима с разрешением 1024 x 768 пикселов и возможностью одновременного отображения 64 К цветов необходима видеопамять объемом 1,6 Мбайт.

    Для доступа центрального процессора к видеопамяти обычно резервируется адресное пространство размером всего 64 Кбайт. Как же процессор получает доступ к видеопамяти, объем которой для некоторых режимов достигает 4 Мбайт? Существует несколько различных подходов к решению этой проблемы, которые могут комбинироваться.

    Слоеный пирог

    В большинстве стандартных режимов адаптеров EGA и VGA видеопамять организована из четырех слоев. По каждому адресу расположены сразу четыре байта. Благодаря специальным схемам видеоадаптер может получить доступ к отдельным слоям памяти.

    Простейший путь втиснуть в адресное пространство объемом 64 Кбайт больше памяти лежит в увеличении количества слоев видеопамяти. Действительно у некоторых моделей видеоадаптера SVGA видеопамять организована в 8 и даже в 16 слоев. Каждый байт видеопамяти определяет 8 пикселов. Восемь слоев памяти позволяют закодировать 256 возможных цветов для пиксела, а шестнадцать слоев - 65536 различных цветов.

    Однако увеличение числа слоев влечет за собой усложнение аппаратуры видеоадаптера и ее удаление от стандарта адаптера VGA, регистры которого рассчитаны только на четыре слоя памяти.

    Увидеть весь мир через замочную скважину

    Многие современные видеоадаптеры применяют давно известный прием, ранее использовавшийся для подключения к компьютеру дополнительной памяти. Центральный процессор получает доступ к видеопамяти через небольшое окно. Это окно может иметь небольшой размер - до 64 Кбайт и располагаться в адресном пространстве процессора. Обычно окно занимает адресное пространство A000:0000h - A000:FFFFh, то есть расположено также как и для стандартных цветных режимов видеоадаптеров EGA, VGA и SVGA. Процессор компьютера может перемещать это окно по всей видеопамяти адаптера получая доступ к разным ее участкам.

    Таким образом, процессор может одновременно получить доступ только к части видеопамяти. Чтобы обратиться к другому участку видеопамяти, необходимо переместить окно доступа. Обычно для этого достаточно записать в определенный регистр видеоадаптера SVGA положение окна относительно начала видеопамяти.

    Доступ к видеопамяти через небольшое окно создает определенные трудности для программного обеспечения. Теперь чтобы отобразить на экране монитора пиксел вы должны не только вычислить положение соответствующей ячейки видеопамяти, но также определить смещение для окна доступа.

    Одновременно усложняются процедуры, отображающие на экране линии и другие геометрические фигуры. Возможно, что выводимое на экран изображение не помещается в одно окно. Процедура должна будет соответственно перемещать окно по видеопамяти.

    Усложняются процедуры копирования изображения из одной позиции экрана в другую. Они должны учитывать, что при копировании может понадобиться перемещать окно доступа к видеопамяти.

    Чтобы немного помочь программистам в решении этих и многих других задач, некоторые реализации видеоадаптеров SVGA отводят для доступа к видеопамяти не одно, а два окна. Обычно они обозначаются как окно A и окно B. В некоторых моделях видеоадаптеров через одно окно можно только записывать данные в видеопамять, а через другое только читать из видеопамяти.

    Больше цветов больше бит

    Многие режимы видеоадаптера SVGA позволяют одновременно отображать на экране больше чем 256 различных цветов. Естественно что для этого каждый пиксел должен быть представлен большим количеством бит.

    Количество различных цветов

    Количество бит для кодировки пиксела

    256

    8

    32768

    15

    65536

    16

    16777216

    24

    4294967296

    32

    Рассмотрим 256-цветный режим видеоадаптера VGA. Каждый пиксел экрана представлен 8 битами данных видеопамяти. Видеоадаптер VGA содержит таблицу цветов (набор из 256 регистров ЦАП), которые согласно значениям, записанным в ней преобразует 8 битные данные видеопамяти в три 6-битных сигнала. Эти три сигнала поступают на три ЦАП и вырабатывающие красную, зеленую и синюю компоненты, определяющие цвет пиксела. Благодаря применению таблицы цветов вы можете выбрать для одновременного отображения на экране монитора любые 256 цветов из 262144 возможных.

    Видеоадаптеры SVGA для каждого пиксела используют больше чем 8 бит. Обычно пиксел определяется 15, 16 или 24 битами. Естественно, что в этом случае использование таблицы цветов адаптера VGA затруднено. Например, для режима 65536 цветов (16 бит на пиксел) требуется увеличить размер таблицы цветов до 65536 18-битных регистров. Если адаптер SVGA кодирует пиксел 24 битами, то придется увеличивать размерность таблицы цветов с 18 до 24 или выше.

    Поэтому в большинстве режимов SVGA реализована схема прямого кодирования цвета (Direct Color Mode). Биты, определяющие пиксел, группируются на три основные группы, непосредственно определяющие красную, зеленую и синюю компоненты цвета. Данные из этих трех групп передаются на три ЦАП и формируют видеосигнал. Таблица цветов не используется.

    В некоторых режимах SVGA существует дополнительная, четвертая группа бит, также соответствующая каждому пикселу. Как правило, четвертая группа бит не используется. Некоторые модели видеоадаптеров могут использовать ее по своему усмотрению.

    Например, на видеоадаптере Diamond Stealth 64, в режиме 110h, соответствующему спецификации VESA, для кодирования одного пиксела отводится два байта (рис. 7.1). Они разделены на четыре группы. Три из них имеют размер 5 бит и отвечают за красный, зеленый и синий компоненты цвета пиксела. Четвертая группа, резервная, состоит из одного бита. На рисунке 7.1 резервная группа отмечена символом 'X'.

    Рисунок 7.1 Формат видеопамяти, 15 бит на пиксел

    Таким образом, в режиме 110h видеоадаптер может отображать пикселы 25+5+5 = 32768-и различных цветов.

    В режиме 111h на каждый пиксел также как и в режиме 110h отводится 2 байта, однако они имеют другой формат (рис. 7.2). Резервное поле отсутствует. За счет этого увеличен размер поля, управляющего зеленым компонентом цвета пиксела. Поэтому, в данном режиме видеоадаптер может отображать пикселы 25+6+5 = 65536-и различных цветов.

    Рисунок 7.2 Формат видеопамяти, 16 бит на пиксел и резервное поле

    Чтобы видеоадаптер мог одновременно отображать на экране 16777216 различных цветов, необходимо, чтобы для кодирования каждого пиксела отводилось 24 бита. Обычно видеоадаптеры используют для этого два различных формата кодирования пиксела (рис. 7.3 и 7.4)

    Рисунок 7.3 Формат видеопамяти, 24 бит на пиксел

    В режимах 112h, 115 и 118h на один пиксел отводится 4 байта (рис. 7.4). Они разделены на четыре группы по 8 бит в каждой. Три группы отвечают за красный, зеленый и синий компоненты цвета пиксела. Четвертая группа резервная. Такой формат позволяет одновременно отображать на экране монитора пикселы 28+8+8 = 16777216 различных цветов.

    Рисунок 7.4 Формат видеопамяти, 24 бит на пиксел и резервное поле

    Интересно отметить, что даже в режиме 118h, имеющем разрешение 1024x768 пикселов, на экране отображается 786432 пиксела. То есть меньше, чем количество цветов, которое видеоадаптер может одновременно отобразить на экране монитора.

    Стандарт VESA

    Стандарт VESA описывает расширение прерывания BIOS номер 10h (VESA BIOS Extention - VBE), отвечающего за управление видеоадаптерами. Поддержка VBE обычно включается производителями видеоадаптеров в ПЗУ самого адаптера или поставляется в виде отдельной резидентной программы. Во втором случае перед использованием функций VBE необходимо загрузить данную резидентную программу в оперативную память компьютера. Ниже мы полностью опишем функции VBE версии 1.2 и опишем некоторые функции VBE версии 2.0.

    Перед вызовом функций VBE следует записать в регистр AH значение 4Fh. Если ваша реализация VBE поддерживает данную функцию, то в регистре AL возвращается значение 4Fh. Если функция не реализована, тогда в регистре AL возвращается значение, отличное от 4Fh.

    Результат выполнения функции записывается в регистр AH. В случае успешного завершения функции в регистре AH возвращается нулевое значение. Если в регистре AH записано значение 1h, значит функция завершилась с ошибкой. И, наконец, если в регистре AH возвращается значение 2h, значит аппаратура видеоадаптера не поддерживает данную функцию.

    Возможна ситуация, когда VBE может выполнить запрашиваемую функцию, а аппаратура видеоадаптера - нет. В этом случае после завершения функции регистр AH содержит значение 4Fh, а регистр AH - 2h.

    Получить информацию о реализации VBE и видеоадаптере

    Функция позволяет получить различную информацию о возможностях VBE и видеоадаптера. Вы должны использовать данную функцию, чтобы определить, наличие VBE и его версию. Формат вызова функции отличается для VBE версии 2.0 и VBE более ранних версий.

    В следующей таблице представлен формат вызова функции для VBE версии 1.2 и более ранних версий:

    На входе:

    AH

    4Fh

     

    AL

    00h

     

    ES:DI

    Указатель на буфер размером 256 байт (формат буфера см. ниже). В этот буфер записывается различная информация о видеоадаптере SVGA и реализации VBE

    На выходе:

    AL

    4Fh

     

    AH

    0, в случае успешного завершения, 1 в случае ошибки

    Примечание:

     

    Значения остальных регистров сохраняются

    Теперь приведем расширенный формат этой же функции соответствующий VBE версии 2.0:

    На входе:

    AH

    4Fh

     

    AL

    00h

     

    ES:DI

    Указатель на буфер размером 512 байт (формат буфера см. ниже). Первые четыре байта буфера должны содержать строку "VBE2". В буфер записывается различная информация о видеоадаптере SVGA и реализации VBE

    На выходе:

    AL

    4Fh

     

    AH

    0, в случае успешного завершения, 1 в случае ошибки

    Примечание:

     

    Значения остальных регистров сохраняются

    В следующей таблице представлен формат буфера, содержащего информацию об адаптере SVGA и реализации VBE. В таблице мы объединили разные версии VBE.

    Смещение

    Размер

    Описание

    00h

    4 байта

    В случае успешного завершения в это поле записывается строка 'VESA'

    04h

    Слово

    Номер версии VBE. Старший байт содержит старшую часть номера версии, младший байт - младшую часть номера версии

    06h

    Двойное слово

    Дальний указатель на строку, закрытую нулем. В строке содержится информация, определяемая производителем. Как правило, она служит для описания видеоадаптера и реализации VBE

    0Ah

    Двойное слово

    Возможности видеоадаптера. В реализации VBE версии 1.2 задействуется только бит D0.

    Бит D0 содержит единицу, если ЦАП видеоадаптера может работать с данными переменной длинны. В противном случае ЦАП может использовать для представления каждой компоненты цвета (RGB-красный, зеленый, синий) только 6 бит.

    Бит D1 (VBE 2.0) содержит единицу, если видеоадаптер не полностью совместим с VGA.

    Бит D2 (VBE 2.0) содержит единицу, если BIOS не поддерживает другие функции VBE

    0Eh

    Двойное слово

    Дальний указатель на список режимов, поддерживаемых функциями VBE. Список состоит из 16-битовых величин, являющихся номерами режимов и заканчивается числом 0FFFFh

    Следующие поля таблицы поддерживаются только VBE версии 1.2

    12h

    Слово

    Объем памяти видеоадаптера, представленный в блоках размером по 64 Кбайт

    Следующие поля таблицы поддерживаются только VBE версии 2.0

    14h

    Слово

    Дополнительный номер версии VBE (номер пересмотренной версии)

    16h

    Двойное слово

    Дальний указатель на строку, закрытую нулем. В строке содержится имя фирмы разработчика

    1Ah

    Двойное слово

    Дальний указатель на строку, закрытую нулем. В строке содержится название видеоадаптера

    1Eh

    Двойное слово

    Дальний указатель на строку, закрытую нулем. В строке содержится дополнительный номер версии видеоадаптера

    22h

    222 байт

    Не используется

    100h

    256 байт

    Информация фирмы разработчика

    Получить информацию о режиме видеоадаптера

    Функция позволяет определить различные характеристики любого режима видеоадаптера, отвечающего стандарту VESA. Программа должна подготовить буфер и передать указатель на него функции. В случае успешного завершения в буфер будут записаны характеристики режима.

    На входе:

    AH

    4Fh

     

    AL

    01h

     

    CX

    Номер режима

     

    ES:DI

    Указатель на буфер размером 256 байт (см. ниже) для таблицы описания режима

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

    Формат таблицы описания режима представлен ниже:

    Смещение

    Размер

    Описание

    00h

    Слово

    Атрибуты режима:

    D0 режим поддерживается

    D1 доступна дополнительная информация

    D2 поддерживаются функции BIOS

    D3 1 - цветной режим, 0 - монохромный режим

    D4 1 - графический режим, 0 - текстовый режим

    02h

    Байт

    Атрибуты окна A

    D0 доступно (поддерживается)

    D1 окно доступно для чтения

    D2 окно доступно для записи

    D3-D7 не используется

    03h

    Байт

    Атрибуты окна B (см. атрибуты окна A)

    04h

    Слово

    Шаг позиционирования окна в Кбайтах

    06h

    Слово

    Размер окна в Кбайтах

    08h

    Слово

    Начало сегмента окна A

    0Ah

    Слово

    Начало сегмента окна B

    0Ch

    Двойное слово

    Указатель на функцию перемещения (позиционирования) окна

    10h

    Слово

    Количество байт на линию сканирования. Не является обязательным для режимов VESA

    Следующие поля таблицы поддерживаются только VBE версии 1.2

    12h

    Слово

    Разрешение по горизонтали в пикселах

    14h

    Слово

    Разрешение по вертикали в пикселах

    16h

    Байт

    Ширина символа в пикселах

    17h

    Байт

    Высота символа в пикселах

    18h

    Байт

    Количество слоев видеопамяти

    19h

    Байт

    Количество бит на пиксел

    1Ah

    Байт

    Количество банков памяти

    1Bh

    Байт

    Тип модели памяти

    1Ch

    Байт

    Размер банка памяти в Кбайтах

    1Dh

    Байт

    Количество страниц видеопамяти, доступных в данном режиме минус один

    1E

    Байт

    Зарезервировано

    1Fh

    Байт

    Количество бит, представляющих красную компоненту цвета пикселов

    20h

    Байт

    Положение младшего бита поля, представляющего красную компоненту цвета пикселов

    21h

    Байт

    Количество бит, представляющих зеленую компоненту цвета пикселов

    22h

    Байт

    Положение младшего бита поля, представляющего зеленую компоненту цвета пикселов

    23h

    Байт

    Количество бит, представляющих синюю компоненту цвета пикселов

    24h

    Байт

    Положение младшего бита поля, представляющего синюю компоненту цвета пикселов

    25h

    Байт

    Количество бит, представляющих запасное поле цвета пикселов

    26h

    Байт

    Положение младшего бита запасного поля, предоставляющего цвет пикселов

    27h

    Байт

    D0 равен единице, если в данном режиме видеоадаптера вы можете программировать регистры ЦАП;

    D1 равен единице, если в данном режиме видеоадаптера каждое значение пиксела представлено 4 полями (красное, зеленое, синее, дополнительное) и дополнительное поле можно использовать. Если бит равен нулю, тогда дополнительное поле зарезервировано и не используется;

    D2-D7 зарезервировано

    Следующие поля таблицы поддерживаются только VBE версии 2.0

    28h

    Двойное слово

    Поле содержит физический 32-разрядный адрес начала видеобуфера для использования его в защищенном режиме

    2Сh

    Двойное слово

    Смещение от начала видеобуфера области памяти неиспользуемой для отображения изображения на экране монитора

    30h

    Слово

    Размер области памяти, неиспользуемой для отображения изображения

    32h

    206 байт

    Зарезервировано

    Теперь мы приведем программу VESATEST, которая позволяет собрать различную информацию о видеоадаптере и реализации VBE расширения BIOS. Объем информации, выдаваемой программой достаточно велик. Поэтому для упрощения программы вся выходная информация записывается в файл, который вы можете просмотреть с помощью любого текстового редактора. Программа VESATEST имеет следующий формат:

    
    VESATEST <имя файла>
    

    Параметр <имя файла> должен содержать имя файла, в который будут записаны результаты работы программы. Исходный текст программы представлен в листинге 7.1.

    Листинг 7.1. Файл VESATEST.CPP

    
    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <dos.h>
    #include "vesa.h"
    
    // Описание функций
    int     main( int argc, char * argv[] );
    int     GetBaseVESAInfo(FILE*);
    int     AnalyseResult(union REGS);
    
    // Главная функция
    int main( int argc, char * argv[] )
    {
            FILE    *fileVesaReport;
            int     iResult;
    
            // Проверка командной строки программы
            if( argc != 2 )
            {
                    printf("\nФормат вызова: VESATEST <имя файла>"
                            "\n  <имя файла>: имя файла, в который будет"
                            " записана информация");
                    return -1;
            }
    
            // Открываем файл
            fileVesaReport = fopen(argv[1], "w+");
    
            // Записываем в файл fileVesaReport информацию о VBE и
            // видеоадаптере
            iResult = GetBaseVESAInfo(fileVesaReport);
    
            // Закрываем файл
            fclose(fileVesaReport);
    
            return ((iResult==0) ? 0 : -1);
    }
    
    //===========================================================
    // Функция GetBaseVESAInfo
    //===========================================================
    int
    GetBaseVESAInfo(FILE *file)
    {
            union REGS regs;
            struct SREGS segregs;
            int     iResult, i;
    
            // Структуры для получения информации о VBE
            VESAINFO                        vesaInfo;
            VESAMODEINFO    modeInfo;
    
            // Подготавливаем буфер для VBE версии 2.0
            strcpy( vesaInfo.cSignature, "VBE2" );
    
            // Получаем данные о реализации VBE и видеоадаптере
            regs.h.ah = 0x4f;
            regs.h.al = 0x00;
            segregs.es = FP_SEG((void far *)&vesaInfo);
            regs.x.di = FP_OFF((void far *)&vesaInfo);
            int86x(0x10, &regs, &regs, &segregs);
    
            // Проверяем результат вызова функции VBE
            iResult = AnalyseResult(regs);
            if(iResult != 0) return -1;
    
            // Записываем в файл информацию из структуры vesaInfo
            fprintf(file,"Сигнатура: '%4.4s'\n",vesaInfo.cSignature );
            fprintf(file, "Информация фирмы производителя: '%s'\n",
                    vesaInfo.fpInfoOEM );
            fprintf(file, "Версия VBE: %Xh \n", vesaInfo.usVersion);
            fprintf(file, "Возможности видеоадаптера: '%x%x%x%x' \n",
                    vesaInfo.ucCapabilities[0],vesaInfo.ucCapabilities[1],
                    vesaInfo.ucCapabilities[2],vesaInfo.ucCapabilities[3]);
    
            fprintf(file, "Поддерживаются следующие режимы VESA: \n");
             for( i=0; i<50; i++ )        {
                    if(vesaInfo.fpModeTable[i] == 0xFFFF)   break;
                    fprintf(file,  "   %Xh \n", vesaInfo.fpModeTable[i] );
             }
    
            // Объем видеопамяти определяется VBE версии не младше 1.2
            if( vesaInfo.usVersion >= 0x102 )
                    fprintf(file,  "Объем видеопамяти %d Кбайт\n",
                            vesaInfo.usTotalMemory * 64);
    
            // Следующая информация доступна только для
            // VBE версии 2.0 и старше
            if( vesaInfo.usVersion >= 0x200 )
            {
                    fprintf(file,"Дополнительный номер версии: %04Xh\n",
                            vesaInfo.usRevVersion);
                    fprintf(file, "Дополнительный номер версии"
                            "видеоадаптера: '%s'\n",
                            vesaInfo.fpOEMRevVersion);
                    fprintf(file, "Имя фирмы разработчика: '%s'\n",
                            vesaInfo.fpOEMName);
                    fprintf(file, "Название видеоадаптера: '%s'\n",
                            vesaInfo.fpOEMProductName);
            }
    
            // Теперь получаем информацию для каждого доступного
            // режима VESA
            for( i=0; i<50; i++ )         {
    
                    // Получаем очередной номер режима VESA
                    if(vesaInfo.fpModeTable[i] == 0xFFFF)   break;
                    fprintf(file,  "\n\nРежим %Xh \n",
                            vesaInfo.fpModeTable[i] );
    
                    // Получаем информацию о режиме vesaInfo.fpModeTable[i]
                    regs.h.ah = 0x4f;
                    regs.h.al = 0x01;
                    regs.x.cx = vesaInfo.fpModeTable[i];
                    segregs.es = FP_SEG((void far *)&modeInfo);
                    regs.x.di = FP_OFF((void far *)&modeInfo);
                    int86x(0x10, &regs, &regs, &segregs);
    
                    // Проверяем результат вызова функции VBE
                    iResult = AnalyseResult(regs);
                    if(iResult != 0) return -1;
    
                    // Записываем в файл информацию из структуры modeInfo
                    fprintf(file, "Атрибуты режима: %04Xh \n",
                            modeInfo.usModeAttr);
                    fprintf(file, "Атрибуты окна: A %02Xh \n",
                            modeInfo.ucWinAAttr);
                    fprintf(file, "Атрибуты окна: B %02Xh \n",
                            modeInfo.ucWinBAttr);
                    fprintf(file, "Шаг позиционирования окна: %d Кбайт \n",
                            modeInfo.usWinGranularity);
                    fprintf(file, "Размер окна, Кбайт: %d  \n",
                            modeInfo.usWinSize );
                    fprintf(file, "Начало сегмента окна A: %04Xh \n",
                            modeInfo.usBegSegA );
                    fprintf(file, "Начало сегмента окна B: %04Xh \n",
                            modeInfo.usBegSegB );
                    fprintf(file, "Функция перемещения окна: %p \n",
                            modeInfo.fpWinFunc );
                    fprintf(file, "Байт на линию сканирования: %d \n",
                            modeInfo.usBytesPerScanLine );
    
            // Объем видеопамяти определяется VBE версии не младше 1.2
                    if(vesaInfo.usVersion >= 0x102)
                    {
                            fprintf(file, "Разрешение по горизонтали: %d \n",
                                    modeInfo.usSizeX);
                            fprintf(file, "Разрешение по вертикали: %d \n",
                                    modeInfo.usSizeY);
                            fprintf(file, "Ширина символа:  %02Xh \n",
                                    modeInfo.ucCharSizeX);
                            fprintf(file, "Высота символа: %02Xh \n",
                                    modeInfo.ucCharSizeY);
                            fprintf(file, "Количество слоев видеопамяти: %02Xh
                                    \n", modeInfo.ucNumPlanes);
                            fprintf(file, "Количество бит на пиксел: %02Xh \n",
                                    modeInfo.ucNumPixelBits);
                            fprintf(file, "Количество банков памяти: %02Xh \n",
                                    modeInfo.ucBanksNum);
                            fprintf(file, "Тип модели памяти: %02Xh \n",
                                    modeInfo.ucTypeMemModel);
                            fprintf(file, "Размер банка памяти: %02Xh \n",
                                    modeInfo.ucBankSize);
    
                            fprintf(file, "Количество доступных страниц
                                    видеопамяти: %02Xh \n",    modeInfo.ucPageNum);
    
                            fprintf(file, "Размер поля красного компоненты"
                                                    " цвета: %02Xh \n", modeInfo.ucRedSize);
                            fprintf(file, "Положение красного поля: %02Xh \n",
                                    modeInfo.ucRedField);
                            fprintf(file, "Размер поля зеленой компоненты"
                                    "цвета пикселов: %02Xh \n",modeInfo.ucGreenSize);
                            fprintf(file, "Положение зеленого поля: %02Xh \n",
                                    modeInfo.ucGreenField);
                            fprintf(file, "Размер поля синей компоненты цвета"
                                    " пикселов: %02Xh \n", modeInfo.ucBlueSize);
                            fprintf(file, "Положение синего поля: %02Xh \n",
                                    modeInfo.ucBlueField);
                            fprintf(file, "Размер резервной области: %02Xh \n",
                                    modeInfo.ucResSize);
                            fprintf(file, "Положение резервного поля: %02Xh \n",
                                    modeInfo.ucResField);
                            fprintf(file,  "Режим ЦАП: %02X\n",
                                    modeInfo.ucDACInfo);
                    }
            }
            return iResult;
    }
    
    //===========================================================
    // Функция AnalyseResult
    //===========================================================
    int
    AnalyseResult(union REGS regs)
    {
            int     iResult;
    
            if((regs.h.al == 0x4f) && (regs.h.ah == 0))
                    iResult = 0;
            else if(regs.h.al != 0x4f)
                    iResult = -1;
            else
                    iResult = 1;
    
            return iResult;
    }
    

    Во включаемом файле VESA.H определены структуры VESAINFO и VESAMODEINFO, которые используются при определении возможностей VBE и видеоадаптера. Исходный текст файла VESA.H представлен в листинге 7.2.

    Листинг 7.2. Файл VESA.H

    
    //      Информация о VBE и видеоадаптере
    typedef struct
    {
            // Поддерживается всеми версиями VBE
            char                                            cSignature[4];
            unsigned short                  usVersion;
            char far                                *fpInfoOEM;
            unsigned char                   ucCapabilities[4];
            unsigned short far      *fpModeTable;
    
            // Поддерживается VBE версии 1.2
            unsigned short                  usTotalMemory;
    
            // Поддерживается VBE версии 2.0
            unsigned short                  usRevVersion;
            char far                                *fpOEMName;
            char far                                        *fpOEMProductName;
            char far                                        *fpOEMRevVersion;
            char                                            cReserv[222];
            char                                            cOEMData[256];
    }       VESAINFO;
    
    // Характеристика режима видеоадаптера
    typedef struct
    {
            unsigned short          usModeAttr;
            unsigned char           ucWinAAttr;
            unsigned char           ucWinBAttr;
            unsigned short          usWinGranularity;
            unsigned short          usWinSize;
            unsigned short          usBegSegA;
            unsigned short          usBegSegB;
            void far                                *fpWinFunc;
            unsigned short          usBytesPerScanLine;
    
            // Поддерживается VBE версии 1.2
            unsigned short          usSizeX;
            unsigned short          usSizeY;
            unsigned char           ucCharSizeX;
            unsigned char           ucCharSizeY;
            unsigned char           ucNumPlanes;
            unsigned char           ucNumPixelBits;
            unsigned char           ucBanksNum;
            unsigned char           ucTypeMemModel;
            unsigned char           ucBankSize;
            unsigned char           ucPageNum;
            unsigned char           ucReserv1;
    
            unsigned char           ucRedSize;
            unsigned char           ucRedField;
            unsigned char           ucGreenSize;
            unsigned char           ucGreenField;
            unsigned char           ucBlueSize;
            unsigned char           ucBlueField;
            unsigned char           ucResSize;
            unsigned char           ucResField;
            unsigned char           ucDACInfo;
    
            // Поддерживается VBE версии 2.0
            unsigned char far               *VideoBuff;
            unsigned char far               *ScrOffset;
            unsigned short                  usScrSize;
            unsigned char                   ucReserv2[206];
    }       VESAMODEINFO;
    

    На рисунке 7.5 мы проиллюстрировали назначение полей структуры VESAMODEINFO, отвечающих за формат видеопамяти.

    Рисунок 7.5 Определение образа символа

    Установить режим видеоадаптера

    Функция предназначена для установки режима работы видеоадаптера. Вы можете использовать ее для выбора любого из режимов, описанных в спецификации VBE и поддерживаемых видеоадаптером. Перед вызовом данной функции рекомендуется проверить, поддерживает ли адаптер данный режим. Для этого можно воспользоваться функцией 01h VBE.

    На входе:

    AH

    4Fh

     

    AL

    02h

     

    BX

    Номер режима VESA. Номера режимов VESA перечислены в главе "Режимы работы видеоадаптеров"

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

    Перед вызовом функции вы должны занести в регистр BX номер режима VESA, который необходимо установить. Старший бит регистра BX (бит D15) определяет, будет ли выполняться очистка видеопамяти. Если бит D15 равен единице, тогда видеопамять не очищается.

    Бит D14 управляет адресацией видеопамяти. Если бит D14 равен единице, функция устанавливает режим видеоадаптера, используя 32-битную адресацию защищенного режима видеопамяти. В этом случае вы можете получить адрес начала и размер видеобуфера при помощи функции 01h (см. выше).

    Определить текущий режим видеоадаптера

    Функция предназначена для определения текущего режима видеоадаптера. Если видеоадаптер работает в режиме не соответствующем спецификации VBE, функция может вернуть неправильные значения.

    На входе:

    AH

    4Fh

     

    AL

    03h

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

     

    BX

    Номер режима

    Сохранить/восстановить состояние видеоадаптера

    Функция позволяет сохранить в буфере программы информацию о текущем состоянии видеоадаптера и восстановить ее впоследствии.

    На входе:

    AH

    4Fh

     

    AL

    04h

     

    DL

    00h Определить размер буфера состояния

     

    DL

    01h Сохранить состояние видеосистемы

     

    ES:BX

    Указатель на буфер

     

    DL

    02h Восстановить состояние видеосистемы

     

    ES:BX

    Указатель на буфер

     

    CX

    Флаги управления сохранением и восстановлением:

    D0 состояние видеоадаптера;

    D1 состояние видеоданных BIOS;

    D2 состояние регистров ЦАП;

    D3 состояние регистров SVGA

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

    Управление адресацией видеопамяти

    Центральный процессор получает доступ к видеопамяти адаптера через окно небольшого размера. Функция 4F05h позволяет позиционировать окно по видеопамяти и определять его текущее положение. Окно может позиционироваться с определенным шагом.

    Функция 4F05h содержит две подфункции, выбираемые регистром BH. Первая подфункция BH = 0 позволяет переместить окно в определенную позицию. Вторая подфункция BH = 1 определяет текущее положение окна.

    На входе:

    AH

    4Fh

     

    AL

    05h

     

    BL

    Номер окна: 0 - окно A, 1 - окно B

     

    BH

    00h выбор окна видеопамяти

     

    DX

    Адрес окна видеопамяти (в единицах шага)

     

    BH

    01h определить адрес окна видеопамяти

     

    DX

    Адрес окна видеопамяти (в единицах шага)

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

    Установить/определить длину строки развертки

    Функция 4F06h содержит две подфункции, выбираемые регистром BH. Первая подфункция BL = 0 позволяет установить логическую длину строки развертки больше чем физически может поместиться на экране. Такая возможность полезна для организации плавной свертки экрана.

    Вторая подфункция BL = 1 определяет длину строки развертки.

    На входе:

    AH

    4Fh

     

    AL

    06h

     

    BL

    00h установить длину строки развертки

     

    CX

    Требуемая длинна строки развертки в пикселах

     

    BL

    01h определить длину строки развертки

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

     

    BX

    Количество байт на строку развертки

     

    CX

    Количество пикселов в строке развертки

     

    DX

    Максимальное количество строк развертки

    .   Если запрашивается длинна строки развертки, которая не поддерживается, тогда устанавливается первое возможное значение, большее запрашиваемого

    .   Линия развертки может быть шире видимой области экрана

    .   Данная функция доступна в текстовых режимах, при условии, что значения длинны строки развертки и количества строк развертки умножаются на соответствующие значения размера символов

    Установить/определить видимую область экрана

    Функция 4F07h содержит две подфункции, выбираемые регистром BL. Первая подфункция BL = 0 позволяет установить логические координаты пиксела, отображаемого в левом верхнем углу экрана. Установка новых логических координат позволяет отобразить на экране другую область видеобуфера. В частности, вы можете с помощью функции 4F06h выбрать логическую длину линии развертки больше физической, а затем плавно сворачивать изображение на экране.

    Вторая подфункция BL = 1 определить текущие координаты первого пиксела на экране.

    На входе:

    AH

    4Fh

     

    AL

    07h

     

    BH

    Не используется

     

    BL

    00h Установить начало видимой области монитора

     

    CX

    Первый (слева) видимый символ в строке развертки

     

    DX

    Первая видимая строка развертки

     

    BL

    01h Определить начало видимой области монитора

     

    BH

    00h

     

    CX

    Первый видимый символ в строке развертки

     

    DX

    Первая видимая строка развертки

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

    .   Данная функция доступна в текстовых режимах, при условии, что значения длинны строки развертки и количества строк развертки умножаются на соответствующие значения размера символов

    Установить/определить размер регистров ЦАП

    Видеоадаптеры VGA и SVGA содержат три ЦАП, каждый из которых определяет цвет одной из трех компонент цвета пиксела - красной, зеленой и синей.

    ЦАП стандартного видеоадаптера VGA отводит по шесть бит на определение каждой из этих компонент. Видеоадаптеры SVGA, имеющие переключаемый ЦАП, поддерживают переменное количество бит на каждую компоненту цвета. Чтобы определить обладает ли видеоадаптер переключаемым ЦАП следует воспользоваться функцией 4F00h.

    Функция 4F08h содержит две подфункции, выбираемые регистром BL. Первая подфункция BL = 0 позволяет установить количество бит используемых на каждый чистый цвет. Вторая подфункция BL = 1 позволяет определить количество бит используемых на каждый чистый цвет.

    На входе:

    AH

    4Fh

     

    AL

    08h

     

    BL

    00h

     

    BH

    Количество бит на каждый чистый цвет

     

    BL

    01h

    На выходе:

    AL

    4Fh

     

    AH

    Результат: 0, в случае успешного завершения, 1 в случае ошибки

    BH

    Количество бит на каждый чистый цвет

    Управление монитором

    Многие современные мониторы позволяют временно отключать свои подсистемы, резко уменьшая потребление электроэнергии. Для обеспечения этой особенности монитор видеоадаптер должен соответствовать спецификации Energy Star и Display Power Management Signaling (DPMS).

    Мы опишем несколько функций VBE/PM (VESA Display BIOS Extensions/Power Management) версии 1.0. С помощью них вы сможете определить, какие режимы экономии электроэнергии обеспечивает ваша видеосистема и выбрать любой из этих режимов.

    В спецификации VBE/PM 1.0 различают следующие режимы:

    Режим

    Описание

    ON

    Обычный режим монитора

    STANDBY

    Гаснет изображение на экране монитора. Режим STANDBY доступен для всех типов мониторов

    REDUSED ON

    Уменьшается яркость изображения. Предназначается для мониторов, выполненных на основе газоразрядных и жидкокристаллических панелей

    SUSPEND

    Отключаются строчная развертка. Монитор переходит в режим экономии электроэнергии первого уровня (см. описание вашего монитора). Чтобы видеоадаптер мог установить режим SUSPEND, необходимо, чтобы монитор соответствовал стандарту Energy Star

    OFF

    Монитор отключаются полностью. Работает необходимый минимум схем монитора, позволяющий снова его включить. Монитор должен соответствовать стандарту Energy Star

    Определение возможностей управления

    Функция 4F10h определяет, какие режимы экономии электроэнергии поддерживает видеоадаптер.

    На входе:

    AH

    4Fh

     

    AL

    10h

     

    BL

    00h

     

    ES:DI

    Зарезервировано, должен содержать 0000:0000h

    На выходе:

    AL

    4Fh - функция поддерживается;

    != 4Fh - функция не поддерживается

     

    AH

    0, в случае успешного завершения,

    1 в случае ошибки

     

    BH

    Поддерживаемые режимы сохранения электроэнергии:

    D0 - содержит 1, если доступен режим STANDBY;

    D1 - содержит 1, если доступен режим SUSPEND;

    D2 - содержит 1, если доступен режим OFF;

    D3 - содержит 1, если доступен режим REDUSED ON;

    D7-D4 зарезервировано

     

    BL

    Номер версии VBE/PM:

    D3-D0 младшая часть номера версии

    D7-D4 старшая часть номера версии

     

    ES:DI

    Не изменяется

    Включить режим сохранения электроэнергии

    Функция устанавливает один из режимов, определенных в спецификации VBE/PM. Перед установкой режима, следует убедиться, что он доступен вашей видеосистеме. Для этого следует воспользоваться функцией 4F10h.

    На входе:

    AH

    4Fh

     

    AL

    10h

     

    BL

    01h

     

    BH

    Режим:

    00h - установить режим ON (включить монитор);

    01h - установить режим STANDBY (погасить экран);

    02h - установить режим SUSPEND (отключить развертку);

    04h - установить режим OFF (выключить монитор);

    08h - установить режим REDUSED ON (уменьшить яркость)

    На выходе:

    AL

    4Fh - функция поддерживается;

    в противном случае функция не поддерживается

     

    AH

    0, в случае успешного завершения,

    1 в случае ошибки

     

    BH

    Не изменяется

    Определить состояние монитора

    Последняя функция, рассматриваемая нами, служит для определена текущего режима видеосистемы.

    На входе:

    AH

    4Fh

     

    AL

    10h

     

    BL

    02h

    На выходе:

    AL

    4Fh - функция поддерживается;

    в противном случае функция не поддерживается

     

    AH

    0, в случае успешного завершения,

    1 в случае ошибки

     

    BH

    Текущий режим:

    00h - ON (монитор включен)

    01h - STANDBY (погашен экран монитора)

    02h - SUSPEND (отключена строчная развертка)

    04h - OFF (монитор отключен)

    08h - REDUSED ON (уменьшена яркость изображения)

    Программа POWER, исходный текст которой представлен в листинге 7.3, демонстрирует использование функций VBE Power Management. После запуска программы POWER, она определяет возможности сохранения электроэнергии, доступные вашей видеоподсистеме. Затем, если компьютер поддерживает VBE Power Management, программа гасит экран монитора. Чтобы продолжить работу нажмите любую клавишу клавиатуры компьютера.

    Листинг 7.3. Файл POWER.CPP

    
    #include <stdio.h>
    #include <conio.h>
    #include <dos.h>
    
    // Описание функций
    void    main(void);
    int     SetPowerState( unsigned char );
    int     GetPowerState( unsigned char* );
    int     AnalyseResult(union REGS);
    int     PowerCapabilities( unsigned char*, unsigned char*,
                                                                                            unsigned char*);
    
    #define ON      0x00
    #define OFF     0x04
    #define STANDBY 0x01
    #define SUSPEND 0x02
    #define REDUCED 0x08
    
    //===========================================================
    // Главная функция
    //===========================================================
    void main(void) {
    
            int     uiResult;
            unsigned char   ucMode, ucModes,
                                                    ucMinorVer, ucMajorVer;
    
            // Определяем возможность управления энергопотреблением
            uiResult =
                    PowerCapabilities(&ucModes, &ucMajorVer, &ucMinorVer);
    
            printf("\n\n Copyright (C)Frolov G.V.,1995. "
                             "E-mail: frolov@glas.apc.org\n");
    
            if(uiResult==0) {
                    printf("\n Версия VBE Power Management %d.%d",
                                    (int)ucMajorVer, (int)ucMinorVer );
    
                    printf("\n Поддерживаются режимы:\n"
                                    "STANDBY - %s\n"
                                    "SUSPEND - %s\n"
                                    "OFF - %s\n"
                                    "REDUCED - %s\n",
                                    (ucModes & STANDBY)?        "да" : "нет",
                                    (ucModes & SUSPEND)?        "да" : "нет",
                                    (ucModes & OFF)?            "да" : "нет",
                                    (ucModes & REDUCED)?        "да" : "нет"
                    );
            }
    
            else if(uiResult < 0) {
                    printf("\n Возможность управления энергопотреблением"
                                     "не поддерживается" );
                    return;
            }
    
            else if(uiResult > 0) {
                    printf("\n Ошибка при вызове функции "
                                     "VBE Power Management" );
                    return;
            }
    
            // Определяем текущий режим
            uiResult = GetPowerState( &ucMode );
            printf("\n Функция GetPowerState возвращает %d",uiResult);
            printf("\n GetPowerState = %x", ucMode );
    
            printf("\n Текущий режим: %s\n",
                    (ucMode & STANDBY)  ?       "STANDBY" :
                    (ucMode & SUSPEND)  ?       "SUSPEND" :
                    (ucMode & OFF)                      ?       "OFF" :
                    (ucMode & REDUCED)  ?       "REDUCED" : "Неопределен"
            );
    
            printf("\n\n После нажатия на клавиатуру "
                             "гасим изображение (режим STANDBY)"
                             "\n Для продолжения работы нажмите любую клавишу"    );
    
            // Ожидаем нажатие на клавиатуру
            getch();
    
            // Гасим экран монитора
            uiResult = SetPowerState(STANDBY);
            printf("\n Функция SetPowerState(STANDBY) "
                             "возвращает %d", uiResult );
    
            // Ожидаем нажатие на клавиатуру
            getch();
    
            // Включаем монитор
            uiResult = SetPowerState( ON );
            printf("\n Функция SetPowerState( ON ) "
                             "возвращает %d", uiResult );
    
            return;
    }
    
    //===========================================================
    // Функция SetPowerState
    // Устанавливает режим видеоадаптера и монитора
    //===========================================================
    int
    SetPowerState( unsigned char ucMode )
    {
            union REGS regs;
            int     iResult;
    
            regs.h.ah = 0x4f;
            regs.h.al = 0x10;
            regs.h.bl = 0x01;
            regs.h.bh = ucMode;
            int86(0x10, &regs, &regs);
    
            iResult = AnalyseResult(regs);
    
            return iResult;
    }
    
    //===========================================================
    // Функция GetPowerState
    // Определят текущий режим видеоадаптера
    //===========================================================
    int
    GetPowerState( unsigned char *ucMode )
    {
            union REGS regs;
            int     iResult;
    
            regs.h.ah = 0x4f;
            regs.h.al = 0x10;
            regs.h.bl = 0x02;
    
            int86(0x10, &regs, &regs);
    
            *ucMode = regs.h.bh;
    
            iResult = AnalyseResult(regs);
    
            return iResult;
    }
    
    //===========================================================
    // Функция PowerCapabilities
    // Определяет возможности видеоподсистемы
    //===========================================================
    int
    PowerCapabilities( unsigned char *ucModes,
                                                     unsigned char *ucMajorVer,
                                                     unsigned char *ucMinorVer)
    {
            union REGS regs;
            struct SREGS segregs;
            int     iResult;
    
            regs.h.ah = 0x4f;
            regs.h.al = 0x10;
            regs.h.bl = 0x00;
    
            segregs.es = 0x00;
            regs.x.di = 0x00;
    
            int86x(0x10, &regs, &regs, &segregs);
    
            *ucModes = regs.h.bh;
            *ucMinorVer = regs.h.bl & 0x0F; // Младший
            *ucMajorVer = (regs.h.bl & 0xF0) >> 4; // Старший
    
            iResult = AnalyseResult(regs);
    
            return iResult;
    }
    
    //===========================================================
    // Функция AnalyseResult
    // Анализирует результат, возвращаемый функциями
    // Power VBE
    //===========================================================
    int
    AnalyseResult(union REGS regs)
    {
            int     iResult;
    
            // Функция VBE Power Management завершилась успешно
            if((regs.h.al == 0x4f) && (regs.h.ah == 0))
                    iResult = 0;
    
            // Функция не поддерживается
            else if(regs.h.al != 0x4f)
                    iResult = -1;
    
            // Ошибка при выполнении функции
            else
                    iResult = 1;
    
            return iResult;
    }
    

    [Назад] [Содеожание] [Дальше]


    Hosted by uCoz