Программирование видеоадаптеров© Александр Фролов, Григорий ФроловТом 21, М.: Диалог-МИФИ, 1993. Стандарт 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 и более ранних версий:
Теперь приведем расширенный формат этой же функции соответствующий VBE версии 2.0:
В следующей таблице представлен формат буфера, содержащего информацию об адаптере SVGA и реализации VBE. В таблице мы объединили разные версии VBE.
Получить информацию о режиме видеоадаптераФункция позволяет определить различные характеристики любого режима видеоадаптера, отвечающего стандарту VESA. Программа должна подготовить буфер и передать указатель на него функции. В случае успешного завершения в буфер будут записаны характеристики режима.
Формат таблицы описания режима представлен ниже:
Теперь мы приведем программу 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, ®s, ®s, &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, ®s, ®s, &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.
Перед вызовом функции вы должны занести в регистр BX номер режима VESA, который необходимо установить. Старший бит регистра BX (бит D15) определяет, будет ли выполняться очистка видеопамяти. Если бит D15 равен единице, тогда видеопамять не очищается. Бит D14 управляет адресацией видеопамяти. Если бит D14 равен единице, функция устанавливает режим видеоадаптера, используя 32-битную адресацию защищенного режима видеопамяти. В этом случае вы можете получить адрес начала и размер видеобуфера при помощи функции 01h (см. выше). Определить текущий режим видеоадаптераФункция предназначена для определения текущего режима видеоадаптера. Если видеоадаптер работает в режиме не соответствующем спецификации VBE, функция может вернуть неправильные значения.
Сохранить/восстановить состояние видеоадаптераФункция позволяет сохранить в буфере программы информацию о текущем состоянии видеоадаптера и восстановить ее впоследствии.
Управление адресацией видеопамятиЦентральный процессор получает доступ к видеопамяти адаптера через окно небольшого размера. Функция 4F05h позволяет позиционировать окно по видеопамяти и определять его текущее положение. Окно может позиционироваться с определенным шагом. Функция 4F05h содержит две подфункции, выбираемые регистром BH. Первая подфункция BH = 0 позволяет переместить окно в определенную позицию. Вторая подфункция BH = 1 определяет текущее положение окна.
Установить/определить длину строки разверткиФункция 4F06h содержит две подфункции, выбираемые регистром BH. Первая подфункция BL = 0 позволяет установить логическую длину строки развертки больше чем физически может поместиться на экране. Такая возможность полезна для организации плавной свертки экрана. Вторая подфункция BL = 1 определяет длину строки развертки.
. Если запрашивается длинна строки развертки, которая не поддерживается, тогда устанавливается первое возможное значение, большее запрашиваемого . Линия развертки может быть шире видимой области экрана . Данная функция доступна в текстовых режимах, при условии, что значения длинны строки развертки и количества строк развертки умножаются на соответствующие значения размера символов Установить/определить видимую область экранаФункция 4F07h содержит две подфункции, выбираемые регистром BL. Первая подфункция BL = 0 позволяет установить логические координаты пиксела, отображаемого в левом верхнем углу экрана. Установка новых логических координат позволяет отобразить на экране другую область видеобуфера. В частности, вы можете с помощью функции 4F06h выбрать логическую длину линии развертки больше физической, а затем плавно сворачивать изображение на экране. Вторая подфункция BL = 1 определить текущие координаты первого пиксела на экране.
. Данная функция доступна в текстовых режимах, при условии, что значения длинны строки развертки и количества строк развертки умножаются на соответствующие значения размера символов Установить/определить размер регистров ЦАПВидеоадаптеры VGA и SVGA содержат три ЦАП, каждый из которых определяет цвет одной из трех компонент цвета пиксела - красной, зеленой и синей. ЦАП стандартного видеоадаптера VGA отводит по шесть бит на определение каждой из этих компонент. Видеоадаптеры SVGA, имеющие переключаемый ЦАП, поддерживают переменное количество бит на каждую компоненту цвета. Чтобы определить обладает ли видеоадаптер переключаемым ЦАП следует воспользоваться функцией 4F00h. Функция 4F08h содержит две подфункции, выбираемые регистром BL. Первая подфункция BL = 0 позволяет установить количество бит используемых на каждый чистый цвет. Вторая подфункция BL = 1 позволяет определить количество бит используемых на каждый чистый цвет.
|