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

         

Начало импульса гашения вертикальной развертки (Start Vertical Blank Register - SVBR) (индекс 15h)


Регистр определяет момент гашения луча в процессе вертикальной развертки. У видеоадаптера EGA регистр имеет 9, а у видеоадаптера VGA - 10 разрядов. Девятый бит регистра SVBR расположен в дополнительном регистре (OVR). Десятый бит расположен в регистре высоты символов текста (MSLR).



Начало импульса горизонтального


Для видеоадаптеров EGA, VGA и SVGA регистр задает момент начала импульса горизонтального обратного хода луча.

При установке режима работы видеоадаптера, BIOS загружает в регистр SHRR следующие значения:

Режим

0,1

4,5,D

2,3



6,E

7

F,10

Содержимое регистра

31h

30h

5Fh

5Eh

51h

50h

Если используется улучшенный цветной монитор, то эти значения отличаются:

Режим

0,1

2,3

Содержимое регистра

28h

51h



Начало обратного вертикального хода луча (Vertical Retrace Start Register - VRSR) (индекс10h)


Регистр определяет начало обратного вертикального хода луча. У видеоадаптера EGA регистр имеет 9, а для видеоадаптеров VGA и SVGA - 10 разрядов. Дополнительные биты регистра VRSR расположены в регистре OVR. Регистр VRSR доступен только для записи.



Нестандартные режимы видеоадаптера VGA


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

Мы рассмотрим два наиболее интересных с нашей точки зрения нестандартных режимов VGA: 320х400 и 360х480 пикселов при возможности одновременного отображения 256 цветов.

Нестандартные режимы нельзя установить на обычных видеоадаптерах VGA с помощью функций BIOS. С помощью BIOS можно установить только один режим с 256-цветной палитрой - режим номер 13h (разрешение 320х200 пикселов, 256 цветов). Однако если вы воспользуетесь возможностью непосредственного программирования адаптера через регистры, то любой адаптер VGA можно перевести в эти режимы.

Программирование всех трех описанных ниже нестандартных режимов мы будем проводить в два этапа:

       устанавливаем при помощи BIOS стандартный режим номер 13h (320х200 пикселов, 256 цветов),

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

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



Область данных видеофункций BIOS


Глава описывает переменные BIOS, размещенные в младших адресах памяти (в так называемой системной области) и используемые видеофункциями BIOS. Знание адресов этих переменных позволяет программе определить количество и тип видеоадаптеров, подключенных к компьютеру, объем видеопамяти, текущий режим работы адаптера.

По содержимому переменных BIOS можно также узнать значения регистров видеоадаптера, используемые по умолчанию в каждом поддерживаемом видеоадаптером режиме.



Область сохранения


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

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

Смещение в байтах

Размер, байт

Содержимое

0

16

Список значений 16 регистров цветовой палитры

10h

1

Значение регистра цвета рамки экрана

11h-0FFh

239

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



Общая длина линии горизонтальной развертки (Horizontal Total Register - HTR) (индекс 0)


Регистр HTR относится к группе регистров контроллера ЭЛТ, которые управляют генерацией синхросигналов монитора. Необходимость модификации данной группы регистров возникает только при программировании нестандартных режимов работы видеоадаптера.

Кроме регистров, контроллер ЭЛТ использует при генерации синхросигналов два внутренних счетчика. Счетчик числа горизонтальных знакомест экрана увеличивается при выводе очередного символа на экран (регенерация экрана) и сбрасывается, когда его значение становится равным регистру общей длины линии горизонтальной развертки. Счетчик числа горизонтальных линий развертки увеличивается после окончания обратного горизонтального хода луча и сбрасывается, когда достигает величины, хранящейся в регистре числа горизонтальных линий растра.

Регистр HTR определяет число знакомест в одной строке развертки, включая обратный ход луча и нерабочую область развертки (рамку экрана). Для видеоадаптера EGA число знакомест по горизонтали на два, а для адаптеров VGA и SVGA на пять больше, чем значение, хранящееся в регистре.

При установке режима работы видеоадаптера, BIOS загружает в регистр HTR следующие значения:

Режим

0,1,4,5,D

2,3,6,E

7,

F

10

Содержимое регистра

37h

70h

60h

5Bh

Если используется улучшенный цветной монитор, то эти значения отличаются:

Режим

0,1

2,3

Содержимое регистра

2Dh

5Bh



Операция чтения


Во время цикла чтения данных из видеопамяти, графический контроллер может выполнять операцию сравнения цветов (Color Compare). Эта операция позволяет найти на экране пикселы определенного цвета. В отличие от обычной операции чтения, когда за один раз читается только один цветовой слой, при выполнении операции сравнения цветов графический контроллер имеет доступ ко всем четырем цветовым слоям одновременно.

Графический контроллер сравнивает данные из всех четырех цветовых слоев (или из любого подмножества цветовых слоев) с данными в регистре сравнения цветов контроллера, и в случае совпадения вырабатывает определенный сигнал.



Операция записи


При чтении процессором данных из видеопамяти они также запоминаются в регистрах-защелках, расположенных на плате видеоадаптера. Если затем выполняется цикл записи, то над данными, находящимися в этих регистрах, и над данными, поступающими от процессора могут выполняться следующие логические операции:

       Запись данных процессора в видеопамять без изменения

       Циклический сдвиг данных, записываемых процессором в видеопамять

       Выполнение булевой операции И между данными, записываемыми в видеопамять и содержимым регистров-защелок. В видеопамять записывается результат операции

       Выполнение булевой операции ИЛИ между данными, записываемыми в видеопамять и содержимым регистров-защелок. В видеопамять записывается результат операции

       Выполнение булевой операции ИСКЛЮЧАЮЩЕЕИЛИ между данными, записываемыми в видеопамять и содержимым регистров-защелок. В видеопамять записывается результат операции

Таким образом, видеоадаптер может выполнять часть работы по обработке видеоданных. Рисунок 3.15 иллюстрирует выполнение графическим контроллером операции записи данных в видеопамять:

PICTURE._FIG_40.PCX;6";4.308";PCX

Рисунок 3.15   Запись данных в видеопамять

Байт, записываемый процессором в видеопамять (на нашем рисунке 11100001b), поступает в графический контроллер. В соответствии со значением регистра циклического сдвига и выбора функции (регистры адаптеров описаны в следующем разделе), происходит циклический сдвиг на один бит содержимого  байта, записываемого в видеопамять.

Полученный результат складывается по логике ИЛИ с содержимым регистров-защелок. Какая булева функция используется - ИЛИ, И, ИСКЛЮЧАЮЩЕЕ ИЛИ также определяется регистром циклического сдвига и выбора функции.

Дальнейшие преобразования происходят в соответствии со значениями регистра разрешения установки/сброса и регистра установки/сброса:

       Если бит регистра разрешения установки/сброса, управляющий данным цветовым слоем, равен нулю, тогда байт, записываемый в видеопамять не изменяется

       Если бит регистра разрешения установки/сброса, управляющий данным цветовым слоем равен единице, то в видеопамять записывается байт, все биты которого устанавливаются в соответствии со значением регистра установки/сброса для данного цветового слоя

Затем в соответствии с состоянием регистра битовой маски происходит запись данных в видеопамять:

       Если данный бит регистра битовой маски содержит единицу, то соответствующие биты для каждого из цветовых слоев поступают от центрального процессора

       Если данный бит регистра битовой маски содержит ноль, то соответствующие биты для каждого из цветовых слоев поступают из регистров-защелок

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



Определение конфигурации и выбор программы распечатки экрана - функция 12h


Функция 12h содержит девять различных подфункций:

Номер подфункции

Назначение

10h

Определение конфигурации видеоадаптера

20h

Выбор программы печати экрана

30h

Выбор количества линий развертки в текстовом режиме

31h

Запрещение загрузки палитры цветов, принятой по умолчанию

32h

Управление доступом к видеопамяти и регистрам видеоадаптера

33h

Управление преобразованием серого цвета

34h

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

35h

Выбор активного монитора (PS/2)

36h

Гашение экрана монитора



Определение конфигурации видеоадаптера - подфункция 10h


Проверяет наличие видеоадаптеров EGA/VGA, а также позволяет получить данные о текущем состоянии видеоадаптера:

На входе:

AH

12h

BL

10h - определение конфигурации EGA/VGA

На выходе:

BH

Режим видеоадаптера устанавливаемый по умолчанию:

0 - цветной режим,

1 - монохромный режим

BL

Объем видеопамяти (для видеоадаптера EGA):

0 - 64 Кбайт,

1 - 128 Кбайт,

2 - 192 Кбайт,

3 - 256 Кбайт

CH

Биты управления дополнительным устройством

CL

Положение переключателей на плате видеоадаптера EGA

Если видеоадаптер, установленный на компьютере, не является видеоадаптером EGA, VGA или SVGA, то регистр BX не изменяет своего значения. Это можно использовать для проверки наличия видеоадаптеров EGA/VGA:

mov        ah, 12h

; Определение конфигурации EGA/VGA

mov        bl, 10h 

mov        bh, 55h

int           10h

; Изменился ли регистр BX

cmp        bx, 5510h

; Если нет, то видеоадаптеры EGA/VGA не обнаружены

je             ega_vga_not_found



Определение положения и формы курсора - функция 03h


Функция 03h позволяет узнать размер и текущие координаты курсора для любой страницы видеопамяти:

На входе:

AH

03h

BH

Номер страницы видеопамяти

На выходе:

CH

Верхняя граница курсора

CL

Нижняя граница курсора

DH

Позиция текущей строки курсора

DL

Позиция текущего столбца курсора

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



Определение размера буфера - подфункция 00h


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

На входе:

AH

1Ch

AL

00h - определение размера буфера

CX

Тип данных, который необходимо сохранить (1 - надо сохранять, 0 - не надо сохранять):

D0 - регистры видеоадаптера,

D1 - область переменных BIOS,

D2 - таблица цветов (регистры ЦАП)

На входе:

AL

1Ch

BX

Размер буфера в 64-байтных блоках



Определение режима подмножества цветов - подфункция 1Ah ???


Возвращает количество текущих цветовых подмножеств:

На входе:

AH

10h

AL

1Ah - определение числа цветовых подмножеств

На выходе:

BL

0 - используются 4 цветовых подмножества по 64 цвета;

1 - используются 16 цветовых подмножеств по 16 цветов

BH

Номер подмножества, используемого в данный момент

mov        ah,10h

mov        al,1ah

int           10h

mov        num_subset,bh



Определение текущего режима работы видеоадаптера - функция 0Fh


Функция позволяет определить номер текущего режима работы видеоадаптера, номер активной страницы и количество символов в строке экрана. Список различных режимов приведен в таблице 3.1. Формат функции имеет следующий вид:

На входе:

AH

0Fh

На выходе:

AH

Количество символов в строке

AL

Номер текущего режима

BH

Номер активной страницы видеопамяти

Бит D7 регистра AL соответствует значению бита D7 регистра AL, использованному при предыдущем выборе режима работы видеоадаптера (см. функцию 0).



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


Функция 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

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



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


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

На входе:

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;

}


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


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

На входе:

AH

4Fh

AL

03h

На выходе:

AL

4Fh

AH

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

BX

Номер режима



Организация видеопамяти


Режим 13h использует простую линейную организацию видеопамяти, в которой по каждому адресу видеопамяти находится один байт данных, управляющий одним пикселом. Такая организация видеопамяти хотя и облегчает программирование, но не позволяет увеличить разрешающую способность. Дело в том, что в режиме 13h адресное пространство видеопамяти ограничено 64 Кбайт,  которых хватает как раз для того, чтобы получить разрешающую способность 200х320 точек при 256 цветах (200*320 = 64000). Кроме того, такая организация видеопамяти не позволяет использовать для копирования видеоданных регистры-защелки, что может существенно повысить скорость работы программ.

Исходя из вышесказанного для нашего нестандартного режима используется другая структура видеопамяти, более схожая со структурой видеопамяти режимов 10h и 12h. На рисунке 4.20 представлена структура видеопамяти используемая нами во всех описываемых нестандартных режимах:

PICTURE._HRESVGA.PCX;6";4.308";PCX

Рисунок 4.20   Структура видеопамяти в нестандартных, 256-цветовых режимах

Как видно из рисунка, первый пиксел экрана, отображаемый в левом верхнем углу, определяется байтом со смещением 0 из нулевого цветового слоя. Второй пиксел определяется байтом со смещением 0 из первого слоя, третий пиксел - байтом со смещением 0 из второго слоя, четвертый пиксел - байтом со смещением 0 из третьего слоя. Пятый пиксел определяется байтом со смещением 1 из нулевого слоя и так далее.

Таким образом, цвет пиксела с координатами x и y определяет байт видеопамяти, который расположен со смещением (x+ y * PIXEL_PER_LINE) / 4, в цветовой плоскости (x + y * PIXEL_PER_LINE) mod 4. В этой формуле константа PIXEL_PER_LINE должна определять горизонтальную разрешающую способность экрана в данном режиме.

Такая организация видеопамяти неудобна для вычисления адреса пикселов, но дает другие неоспоримые преимущества.

Во первых, в режиме с разрешением 320х400 пикселов мы можем использовать две страницы видеопамяти. Первая из них имеет нулевое смещение, а вторая смещение 8000h от начала видеопамяти. Режим с разрешением 360х480 пикселов позволяет иметь только одну страницу, но так как он использует только 172800 байт из 256 Кбайт, то неиспользуемую память можно использовать для хранения пиктограмм и шрифтов.

Во вторых, организация видеопамяти в виде отдельных цветовых слоев позволяет использовать для операций копирования и заполнения областей видеопамяти регистры-защелки. Это дает возможность одновременно копировать четыре байта, и, следовательно, значительно увеличить скорость работы программ.



Переменные в младших адресах памяти


В младших адресах памяти 0000:0400h - 0000:0500h расположены переменные, используемые функциями BIOS. В них находятся основные параметры, определяющие состояние компьютера. Прикладные программы должны осторожно обращаться с этой областью памяти, так как нарушения в ней могут вызвать зависание системы, или другие нежелательные эффекты.

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

Например, если вы изменили непосредственно через регистры видеоадаптера положение курсора, а потом желаете определить его положение при помощи функций BIOS, то надо сразу после изменения регистра изменить и соответствующую переменную BIOS (ее адрес 0000:0450h).

Адрес и имя

Размер

0000:0410h

bEquipFlags

Байт

Флаги конфигурации: биты D5 и D4 определяют режим видеоадаптера, используемый сразу после включения компьютера:

D5 D4   

0   0        зарезервировано;

0   1        40 символов в строке, цветной;

1   0        80 символов в строке, цветной;

1   1        текстовый, монохромный.

Если биты D5 и D4 содержат единицы, значит используется монохромный адаптер. Видеопамять начинается по адресу B000:0000h.

В противном случае активным является цветной видеоадаптер и видеопамять начинается по адресу B800:0000h.

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

0000:0449h

bVideoMode

Байт

Номер текущего режима работы видеоадаптера

0000:044Ah

wColumns

Слово

Количество символов в строке экрана

0000:044Сh

wPageLength

Слово

Размер страницы видеопамяти в байтах

0000:044Eh

wVidStart

Слово

Смещение отображаемой области видеопамяти от начала видеопамяти (значение регистра начального адреса - SAR)

0000:0450h

w8CursorPos

8 слов

Каждое слово определяет координаты курсоров для одной из 8 страниц видеопамяти. Младший байт слова определяет столбец, а старший строку экрана в которой находится курсор

0000:0460h

wCursorShape

Слово

Определяет форму курсора (позицию первой и последней линии курсора). Старший байт слова содержит позицию первой строки курсора, а младший - последней. Состояние данной переменной отвечает регистрам начальной и конечной линии курсора (CSR - старший и CER - младший байты соответственно)

0000:0462h

bActivePage

Байт

Номер отображаемой (текущей) страницы видеопамяти

0000:0463h

wAddrCRT

Слово

Адрес индексного регистра контроллера ЭЛТ. Содержит 3B4h для монохромных или 3D4h для цветных режимов адаптера

0000:0465h

bRegMode

Байт

Значение регистра режима для видеоадаптеров CGA и MDA (регистр MCR). Для видеоадаптеров EGA и VGA эмулируется CGA и MDA

0000:0466h

bRegPalette

Байт

Значение регистра цветовой палитры CGA (регистр CSR). Для видеоадаптеров EGA и VGA эмулируется CGA и MDA

0000:0484h

bRows

Байт

Количество текстовых строк на экране минус единица

0000:0485h

wCharHigh

Слово

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

0000:0487h

bInfo

Байт

Первый байт информации (для видеоадаптеров EGA и VGA):

D0 если бит равен единице, то разрешена эмуляция курсора CGA

D1 равен единице, видеоадаптер подсоединен к монохрому монитору

D2 единица в этом бите означает, что BIOS будет ожидать обратного вертикального хода луча перед записью в видеопамять (для видеоадаптера EGA).

D3 бит установлен, если  видеоподсистема неактивна

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

D6 D5 позволяют определить объем видеопамяти, установленной на адаптере EGA. Объем видеопамяти адаптеров VGA и SVGA, как правило, не бывает меньше 256 Кбайт

D6 D5    объем видеопамяти:

0   0        64 Кбайт;

0   1        128 Кбайт;

1   0        192 Кбайт;

1   1        256 Кбайт

D7 единица означает, что последняя операция выбора режима видеоадаптера не очистила видеопамять

0000:0488h

bInfoTwo

Байт

Второй байт информации о EGA:

D3-D0 положение переключателей на плате EGA (1 - OFF, 0 - ON)

D3           переключатель 4;

D2           переключатель 3;

D1           переключатель 2;

D0           переключатель 1

BIOS видеоадаптера VGA эмулирует переключатели EGA в соответствии с типом используемого монитора;

D7-D4 значение регистра управления дополнительным устройством видеоадаптера EGA

0000:0489h

bFlags

Байт

Набор различных флагов

D7, D4 количество линий развертки для текстовых режимов:

D7 D4

0   0        350 линий;

0   1        400 линий;

1   0        200 линий;

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

D6 содержит единицу, если переключение мониторов разрешено и ноль в противном случае

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

D3 если данный бит содержит значение 1, значит загрузка палитры по умолчанию запрещена

D2 содержит единицу, если используется монохромный монитор и ноль - если используется цветной монитор

D1 содержит единицу, если разрешено преобразование серого цвета

D0 содержит единицу, если VGA активен и ноль - если не активен

0000:048Ah

bDCC

Байт

Индекс таблицы кодов комбинаций мониторов (Display Combination Code table index)

0000:04A8h

dwSavePtr

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

Адрес таблицы окружения (см. следующий раздел)

Имена переменных видеофункций BIOS, которые мы привели в таблице соответствуют названиям полей структуры BIOS_VAR. Структура BIOS_VAR определена во включаемом файле SYSGRAPH.H. Вы можете просмотреть этот файл в листинге 3.3.

В конце данной главы мы приведем пример использования структуры BIOS_VAR для доступа к переменным видеофункций BIOS (листинг 6.1).



Положение подчеркивания символа (Underline Location Register - ULR) (индекс14h)


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

D4-D0    Определяют положение подчеркивания символа.

D5    Для видеоадаптеров VGA и SVGA установка этого бита означает, что для каждого знакоместа счетчик адреса регенерации будет увеличиваться на 4 вместо 1.

D6    Установка для видеоадаптеров VGA и SVGA этого бита выбирает адресацию видеопамяти по двойным словам.

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

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

Листинг 4.7. Файл MORESTR.ASM

#include <conio.h>

// Описания функций

void        main(void);

// Функция Set43Line опреелена в файле SET43.ASM

// (листинг 4.8)

void        __pascal _far Set43Line(void);

// Главная функция

void main(void) {

 

int  i;

 

// Увеличиваем количество отображаемых строк текста

 

Set43Line();

 

// Отображаем на экране монитора несколько текстовых строк

 

for(i = 0; i < 50; i++)

                 

printf("Text line number %d\n", i);

 

getch();

 

return;

}

Основная функция программы MORESTR - функция Set43Line определена в файле SET43.ASM. Исходный текст файла помещен в листинге 4.8.

Листинг 4.8. Файл SET43.ASM

TITLE      SET43.ASM

NAME     SET43

PAGE      55,132

P286

IDEAL

NOWARN BRK

SEGMENT LINE_TEXT WORD PUBLIC 'CODE'

ASSUME                cs:LINE_TEXT

;============================================================

; void Set43Line(void)

; Переводит адаптеры EGA и VGA в режим отображения 43

; строк текста.

;============================================================


  CHAR_SIZE EQU 8

  PUBLIC                SET43LINE

  PROC   SET43LINE FAR

  enter    0, 0

  ; Устанавливаем регистр es на начало оперативной памяти

  xor  ax,ax

  mov  es,ax

  ; Получаем адрес порта индексного регистра контроллера ЭЛТ

  ; (3B4h/3D4h), в монохромных режимах для адресации к

  ; индексному регистру используется порт с адресом 3B4h,

  ; а в цветных - порт 3D4h

  mov  dx,es:[463h]

  ; Выбираем для обмена регистр максимальной линии

  ; сканирования этот регистр задает высоту символов на

  ; экране дисплея

  mov  al,9

  out  dx,al

  ; Вычисляем адрес порта регистра данных контроллера ЭЛТ,

  ; в монохромных режимах для адресации к регистру данных

  ; используется порт с адресом 3B5h, в цветных - порт 3D5h

  inc  dx

  ; Биты D4-D0, регистра максимальной линии сканирования

  ; содержат число, меньшее на единицу, чем высота символов

  ; в пикселах

  mov  al,CHAR_SIZE-1

  out  dx,al

  ; Вычисляем адрес порта индексного регистра

  ; контроллера ЭЛТ

  dec  dx

  ; Выбираем для обмена регистр положения подчеркивания

  mov  al,14h

  out  dx,al

  ; Вычисляем адрес порта регистра данных контроллера ЭЛТ

  inc  dx

  ; Определяем положение подчеркивания символов

  mov  al,CHAR_SIZE

  out  dx,al

  ; Вычисляем адрес порта индексного регистра

  ; контроллера ЭЛТ

  dec  dx

  ; Выбираем для обмена регистр завершения отображения

  ; вертикальной развертки

  ; Регистр завершения отображения вертикальной развертки

  ; содержит восемь младших бит, определяющих число

  ; отображаемых горизонтальных линий растра минус один

  mov  al,12h

  out  dx,al

  ; Вычисляем адрес порта регистра данных контроллера ЭЛТ

  inc  dx

  ; Для отображения 43 текстовых символов, при высоте

  ; символов 8 пикселов, необходимо иметь 43 * 8 = 344

  ; горизонтальных линий растра

  ; Помещаем в регистр завершения отображения вертикальной

  ; развертки младшие 8 бит числа 344

  mov  al,(43 * CHAR_SIZE - 1 - 256)

  out  dx,al

  ; Устанавливаем новые значения переменных BIOS

  ; Количество символов в строке равно восьмидесяти

  mov  WORD PTR es:[44Ah],80

  ; Количество строк текста минус один

  mov  BYTE PTR es:[484h],(350/CHAR_SIZE)-1

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

  mov  WORD PTR es:[485h],CHAR_SIZE

  ; Загружаем нулевую таблицу знакогенератора набором

  ; символов (размер 8х8) из ПЗУ BIOS

  mov  ax,1112h

  xor  bl,bl

  int  10h

  leave

  ret

  ENDP    SET43LINE

ENDS      LINE_TEXT

END


Получение данных о состоянии VGA - функция 1Bh


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

На входе:

AH

1Bh - получение данных о видеосистеме

BX

00h

ES:DI

Адрес буфера для записи данных,  64 байта

На выходе:

AL

1Bh

ES:DI

Буфер заполненный данными (см. таблицу ниже)

Формат буфера представлен в следующей таблице:

Смещение, байт

Размер

0

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

Адрес статической таблицы функций (см. ниже)

4

Байт

Номер текущего режима работы видеоадаптера

5

Слово

Количество символов в строке

7

Слово

Размер отображаемой области видеоданных (в байтах)

9

Слово

Начальный адрес отображаемой области видеоданных

0Bh

8 слов

Позиции курсоров для каждой из 8 страниц видеопамяти (одно слово на страницу). В старшем байте записан номер колонки, в младшем байте номер строки курсора

1Bh

Байт

Нижняя линия курсора

1Ch

Байт

Верхняя линия курсора

1Dh

Байт

Номер активной страницы видеопамяти

1Eh

Слово

Адрес индексного порта контроллера ЭЛТ (3B4/3D4)

20h

Байт

Состояние регистра 3x8h

21h

Байт

Состояние регистра 3x9h

22h

Байт

Количество текстовых строк на экране

23h

Байт

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

25h

Байт

Код первичного видеоадаптера (см. функцию 1Ah подфункция 0h)

26h

Байт

Код дополнительного видеоадаптера (см. функцию 1Ah подфункция 0h)

27h

Слово

Количество одновременно отображаемых цветов в текущем режиме

29h

Байт

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

2Ah

Байт

Количество строк развертки в текущем режиме:

0 - 200;

1 - 350;

2 - 400;

3 - 480

2Bh

Байт

Номер первой таблицы знакогенератора

2Ch

Байт

Номер второй таблицы знакогенератора

2Dh

Байт

Байт, содержащий различные данные:

D0 не используется;

D1 бит равен единице, если разрешено преобразование палитры в серый цвет;

D2 бит равен единице, если подключен монохромный монитор;

D3 запрещена перезагрузка регистров палитры при выборе режима видеоадаптера;

D4 бит равен единице, если разрешена эмуляция курсора CGA;

D5 определяет назначение бита D3 байта атрибутов: если бит равен 1, то он управляет миганием  символа, если бит равен нулю, то бит D3 управляет интенсивностью фона символа;

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

2Eh

Байт

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

2Fh

Байт

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

31h

Байт

Объем видеопамяти адаптера:

0 - 64 Кбайт,

1 - 128 Кбайт,

2 - 192 Кбайт,

3 - 256 Кбайт

32h

Байт

Состояние области сохранения: ???

D0 бит равен единице, если используется набор из 512 символов;

D1 бит равен единице, если используется область сохранения цветовой палитры;

D2 бит равен единице, если используется текстовый набор символов пользователя;

D3 бит равен единице, если используется графический набор символов пользователя;

D4 бит равен единице, если используется цветовая палитра, определенная пользователем;

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

33h - 3Fh

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

<
/p> Далее следует описание статической функциональной таблицы:

Смещение, байт

Размер

0

Байт

Таблица режимов работы видеоадаптера. Если бит равен единице, то режим поддерживается:

D0 Режим 00h;

D1 режим 01h;

D2 режим 02h;

D3 режим 03h;

D4 режим 04h;

D5 режим 05h;

D6 режим 06h;

D7 режим 07h

1

Байт

D0 Режим 08h;

D1 режим 09h;

D2 режим 0Ah;

D3 режим 0Bh;

D4 режим 0Ch;

D5 режим 0Dh;

D6 режим 0Eh;

D7 режим 0Fh

2

Байт

D0 Режим 10h;

D1 режим 11h;

D2 режим 12h;

D3 режим 13h;

D7-D4 Не используются

3

4 байта

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

7

Байт

Количество строк растра в текстовых режимах. Если бит равен единице, то режим поддерживается:

D0 200 строк растра;

D1 350 строк растра;

D2 400 строк растра;

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

8

Байт

Количество таблиц знакогенератора, которые можно одновременно использовать (для текстовых режимов)

9

Байт

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

0Ah

Байт

Биты имеют различное назначение: ???

D0 не используется;

D1 поддерживается преобразование  таблицы цветов в серые цвета;

D2 поддерживается загрузка шрифтов пользователя;

D3 поддерживается загрузка цветовой палитры по умолчанию;

D4 поддерживается эмуляция курсора CGA;

D5 присутствует палитра EGA;

D6 присутствует таблица цветов;

D7 поддерживается функция выбора множества цветов

0Bh

Байт

Биты имеют различное назначение:  ???

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

D1 сохранение/восстановление видеосостояний, поддерживается функция 1Ch;

D2 управление битом D3 байта атрибутов;

D3 код конфигурации монитора

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

0Ch

2 байта

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

0Eh

Байт

Состояние указателя: ???

D0 бит равен единице, если поддерживается набор из 512 символов

D1 бит равен единице, если поддерживается область сохранения цветовой палитры

D2 бит равен единице, если поддерживается текстовый набор символов пользователя

D3 бит равен единице, если поддерживается графический набор символов пользователя

D4 бит равен единице, если поддерживается цветовая палитра, определенная пользователем

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

0Fh

Байт

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


Получение информации об используемом наборе символов - подфункция 30h


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

На входе:

AH

11h

AL

30h

BH

Тип запрашиваемой информации:

0 - вернуть содержимое вектора INT 1Fh;

1 - вернуть содержимое вектора INT 43h;

2 - вернуть указатель на набор символов размера 8х14 пикселов, расположенный в ПЗУ BIOS;

3 - вернуть указатель на набор символов размера 8х8 пикселов, расположенный в ПЗУ BIOS;

4 - вернуть указатель на символы с ASCII кодами от 127 до 255 (размера 8х8 пикселов), расположенные в ПЗУ BIOS;

5 - вернуть указатель на альтернативный набор символов размером 9х14 пикселов, расположенный в ПЗУ BIOS;

6 - вернуть указатель на набор символов размером 8х16 пикселов, расположенный в ПЗУ BIOS;

7 - вернуть указатель на альтернативный набор символов размером 9х16 пикселов, расположенный в ПЗУ BIOS

На выходе:

CL

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

DL

Количество текстовых строк на экране - 1

ES:BP

Указатель на таблицу символов (значение зависит от значения регистра BH)



Получить информацию о реализации 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 байт

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

<
  // Подготавливаем буфер для 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   Определение образа символа


Последовательный преобразователь


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



Предварительная установка горизонтальной развертки (Preset Row Scan Register - PRSR) (индекс8)


Регистр позволяет в текстовых режимах выполнить плавную вертикальную свертку текста на экране монитора. В графических режимах регистр должен содержать нулевое значение.

D4-D0    Биты предварительной установки строчной развертки. Эти биты определяют номер линии развертки, начиная с которой начинают отображаться символы (рис. 8.1). Как видно из рисунка самая верхняя строка текста отображается только частично. Вы можете плавно перемешать изображение на экране увеличивая или уменьшая значение этих битов.

D6-D5    Биты управления побайтовой сверткой. Используются видеоадаптерами VGA и SVGA. Биты D6 D5 являются двумя дополнительными битами регистра горизонтального панорамирования контроллера атрибутов и позволяют сдвигать изображение на экране более чем на 8 пикселов.

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

Рисунок 4.1 иллюстрирует использование регистра предварительной установки горизонтальной развертки для вертикальной свертки содержимого экрана. В левой части рисунка показано начальное состояние экрана монитора, когда биты D0-D4 регистра PRSR содержит нулевые значения. Справа представлен экран монитора после увеличения значения регистра PRSR до трех. Изображение на экране сдвигается на три пиксела вверх, в результате чего часть верхней строки пропадает.

PICTURE._FIG_32.PCX;6";4.308";PCX

Рисунок 4.1   Плавная свертка экрана

После установки режима работы видеоадаптера регистр PRSR содержит нулевое значение.



Регистр адреса светового пера (Light Pen Address Register - LPAR)


Это 16-битовый регистр видеоадаптеров CGA и EGA, доступный только для чтения. Регистр LPAR позволяет определить положение светового пера на экране монитора. Регистр, содержащий старший байт адреса светового пера, имеет индекс10h, а регистр, содержащий младший байт, индекс 11h.

Регистр LPAR сохраняет адрес видеопамяти, которая регенерировалась в момент включения светового пера.



Регистр битовой маски (Bit Mask Register - BMR) (индекс8)


Регистр управляет записью данных в видеопамять. Если бит регистра BMR содержит ноль, то соответствующий бит будет записываться в видеопамять из регистра-защелки. В противном случае данный бит поступает от центрального процессора (рис. 4.17). Регистр BMR используется только в нулевом режиме записи.

PICTURE._FIG_29.PCX;6";4.308";PCX

Рисунок 4.17   Использование регистра битовой маски

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

По умолчанию, во всех режимах регистр BMR хранит число 0FFh.



Регистр циклического сдвига и выбора функции (Data Rotate & Function Select - DRFS) (индекс3)


Регистр DRFS выполняет две различные функции, отраженные в его названии:

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

       Выполнение логических операций над данными записываемыми в видеопамять и содержимым регистров-защелок.

D2-D0    Счетчик сдвига.

D4-D3    Биты выбора логической функции.

D7-D5    Не используются.

После выполнения BIOS установки режима работы видеоадаптера биты регистра DRFS содержат нулевые значения.

При выполнении операции циклического сдвига биты счетчика сдвига могут иметь следующие значения:

D2 D1 D0

Данные циклически сдвигаются вправо на следующее количество битов

0  0  0

Ноль, сдвиг не происходит

0  0  1

Один бит

0  1  0

Два бита

0  1  1

Три бита

1  0  0

Четыре бита

1  0  1

Пять бит

1  1  0

Шесть бит

1  1  1

Семь бит

Во время выполнения процессором операции чтения из видеопамяти одновременно происходит запись данных из всех четырех цветовых слоев (по считываемому адресу) в регистры-защелки. Каждому цветовому слою видеопамяти соответствует один 8-битовый регистр-защелка. Когда процессор начнет записывать данные в видеопамять (возможно уже по другому адресу), адаптер может комбинировать их с данными из регистров-защелок. Вид выполняемой логической операции будет зависеть от содержимого битов выбора логической функции:

D4  D3

Логическая операция

0   0

Запись не модифицированных данных

0   1

И

1   0

ИЛИ

1   1

ИСКЛЮЧАЮЩЕЕ ИЛИ

Следует отметить, что операция циклического сдвига выполняется до выполнения логических функций.

Регистр DRFS можно использовать для быстрого копирования областей видеопамяти с возможной их модификацией.

Рисунок 4.12 иллюстрирует выполнение логической операции ИЛИ. Регистр циклического сдвига и выбора функции содержит число 00010000b. После операции чтения данные из всех четырех слоев записываются в регистры-защелки. Затем выполняется операция записи. Данные процессора в соответствии с состоянием регистра циклического сдвига и выбора функции складываются по логике ИЛИ со значением регистров-защелок и помещаются в видеопамять.

PICTURE._FIG_26.PCX;6";4.308";PCX

Рисунок 4.12   Логические операции и операция циклического сдвига

     Логические операции можно выполнять только в нулевом и втором режиме записи.



Регистр цвета рамки экрана (Screen Border Color Register - SBCR) (индекс11)


В текстовых режимах работы видеоадаптеров регистр SBCR определяет цвет рамки, расположенной вокруг текста. Назначение битов регистра соответствует регистрам цветовой палитры. По умолчанию регистр цвета рамки содержит нулевые значения для всех режимов работы.

Операция установки цвета рамки не работает на большинстве адаптеров EGA.



Регистр данных таблицы цветов (Look-up Table Data Register - LTDR)


Регистр используется для получения доступа к регистрам таблицы цветов. Для чтения и записи одного элемента таблицы цветов необходимо три раза прочитать (записать) содержимое регистра данных. При этом каждый раз считывается (записывается) шесть очередных битов. Первые шесть битов отвечают за интенсивность красного, вторые - зеленого и третьи - синего цвета.

Нельзя прерывать цикл чтения регистров таблицы цветов, состоящий из трех операций чтения, выполнением операции записи в другой регистр таблицы и наоборот. Во время доступа к регистру LTDR прерывания должны быть запрещены. Между операциями доступа к регистрам таблицы цвета необходимо выдержать временной интервал не менее 240 наносекунд.

D5-D0    Данные для обмена с регистрами таблицы цветов.

D7-D6    Не используется.

Программа VGA256 (листинг 4.13) записывает новые значения в таблицу цветов непосредственно через регистры цифро-аналогового преобразователя VGA. На экране монитора отображается пять вертикальных полос различного цвета. Каждая полоса состоит из 64 вертикальных линий. Интенсивность цвета этих линий плавно уменьшается слева на право.

Листинг 4.13. Файл VGA256.C

#include                <stdio.h>

#include                <conio.h>

#include                "sysp.h"

#include                "sysgraph.h"

#include                <dos.h>

// Описания функций

int           main( void );

void        SetVideoMode( unsigned char );

void        Hello(void);

// Функция SetVgaDAC определена в файле DACTABLE.ASM

void __pascal __far           SetVgaDAC(unsigned, unsigned);

//===========================================================

// Главная функция

//===========================================================

int main( void )

{

 

RGB      color_table[256];

 

int          error, x_num, y_num;

 

unsigned             i, j, iii;

 

unsigned             seg_table,off_table;

 

unsigned char   far *ptr;

// Записываем в массив color_table новые значения для

// регистров таблицы цветов


  for(j = 0; j < 4; j++) {

                for(i = 0; i < 64; i++) {

                                (color_table[i+j*64]).red =

                                                (j == 0) ? i : 0;

                                (color_table[i+j*64]).green =

                                                (j == 1) ? i : (j == 3) ? i : 0;

                                (color_table[i+j*64]).blue =

                                                (j == 2) ? i : (j == 3) ? i : 0;

                }

  }

// Устанавливаем режим видеоадаптера номер 13h (256 цветов)

// данный режим поддерживается только VGA и Super VGA

  SetVideoMode( 0x13 );

// Определяем сегмент и смешение массива color_table

  ptr = (unsigned char far*) &color_table[0];

  seg_table = FP_SEG(ptr);

  off_table = FP_OFF(ptr);

// Загружаем новые значения в регистры таблицы цветов

  SetVgaDAC(seg_table,off_table);

// Записываем в ptr указатель на начало видеопамяти

  ptr = (unsigned char far*) (FP_MAKE(0xA000, 0x0));

// Выводим на экран вертикальные линии различного цвета,

// процессор записывает данные непосредственно в видеопамять

  for(y_num = 0; y_num < 200; y_num++) {

                for(x_num = 0; x_num < 320; x_num++) {

                                *ptr = (unsigned char) x_num;

                                ptr++;

                }

  }

// Ожидаем нажатие на клавишу

  getch();

// Плавно гасим изображение на экране, уменьшая значения

// регистров таблицы цветов

  for(i=0;i<320;i++){

                for(iii=0;iii<256;iii++)  {

                                (color_table[iii]).red =

                                                ((color_table[iii]).red>6) ?

                                                color_table[iii].red-1 : 1;

                                (color_table[iii]).green =

                                                ((color_table[iii]).green>6) ?

                                                color_table[iii].green-1 : 1;

                                (color_table[iii]).blue =



                                                ((color_table[iii]).blue>6) ?

                                                color_table[iii].blue-1 : 1;

                }

                SetVgaDAC(seg_table,off_table);

  }

// Ожидаем нажатие на клавишу

  SetVideoMode( 0x3 );

  Hello();

  return 0;

}

//===========================================================

// Функция SetVideoMode устанавливает режим работы

// видеоадаптера, заданный параметром vmode

//===========================================================

void SetVideoMode( unsigned char vmode ) {

  union  REGS    inregs, outregs;

  inregs.h.ah = 0x0;

  inregs.h.al = vmode;

  int86( 0x10, &inregs, &outregs );

}

//===========================================================

// Функция Hello выводит на экран краткую справку о программе

//===========================================================

void Hello(void) {

  printf("\nCopyright (C)Frolov G.V.,1995. "

                                 "E-mail: frolov@glas.apc.org\n");

}

Функция SetVgaDAC, предназначенная для заполнения таблицы цветов, представлена в листинге 4.14.

Листинг 4.14. Файл DACTABLE.ASM

TITLE      DACTABLE.ASM

NAME     DACTABLE

PAGE      55,132

P286

IDEAL

NOWARN BRK

SEGMENT VGA_TEXT WORD PUBLIC 'CODE'

ASSUME                cs:VGA_TEXT

;============================================================

; Функция

; void SetVgaDAC(unsigned seg_table, unsigned off_table)

;============================================================

off_table               EQU        [bp+6]

seg_table             EQU        [bp+8]

  PUBLIC                SETVGADAC

  PROC   SETVGADAC FAR

  enter    0, 0

  ; Сохраняем регистры DS и ES

  push  ds

  push  es

  ; Устанавливаем регистр ES на начало оперативной памяти

  xor   ax,ax

  mov   es,ax

  ; Получаем адрес порта индексного регистра контроллера ЭЛТ

  ; (3B4h/3D4h), в монохромных режимах для адресации к

  ; индексному регистру используется порт с адресом 3B4h, а



  ; в цветных - порт 3D4h

  mov   dx,es:[463h]

  ; Вычисляем адрес порта регистра состояния 1, в

  ; монохромных режимах для адресации к регистру состояния 1

  ; используется порт с адресом 3BAh, а в цветных порт 3DAh

  add   dx,6

  pop   es

  ; Ожидаем начало обратного вертикального хода луча

  in    al,dx

  nop

  nop

  ; Если бит D3 равен единице, то происходит обратный

  ; вертикальный ход луча

  test  al,08h

  jz    wait_on

wait_off:

  in    al,dx

  nop

  nop

  test  al,08h

  jnz   wait_off

wait_on:

  in    al,dx

  nop

  nop

  test  al,08h

  jz    wait_on

  ; Устанавливаем индекс первого записываемого регистра

  ; таблицы цветов

  mov   dx,3C8h

  ; Начинаем модифицировать таблицу цветов с первого

  ; регистра

  mov   ax,1

  out   dx,al

  ; Задержка

  nop

  nop

  ; Устанавливаем DS:SI на массив данных, записываемых

  ; в регистры таблицы цветов

  mov   ax,seg_table

  mov   ds,ax

  mov   si,off_table

  ; Загружаем 256 регистров (по 3 байта на регистр)

  mov   cx,(256 * 3)

  ; Выбираем регистр данных таблицы цветов (порт 3C9h)

  mov   dx,3C9h

  cld

  ; Загружаем все регистры таблицы цветов

get_reg:

  lodsb

  out   dx,al

  nop

  nop

  loop  get_reg

  ; Восстанавливаем регистр DS

  pop   ds

  leave

  ret 4

  ENDP    SETVGADAC

ENDS      VGA_TEXT

END


Регистр горизонтального панорамирования (Horizontal Panning Register - HPR) (индекс13)


Регистр позволяет сдвинуть изображение на экране в горизонтальном направлении. При использовании регистра HPR совместно с регистром начального адреса контроллера атрибутов можно сдвигать изображение на любое количество пикселов.

Формат регистра горизонтального панорамирования представлен ниже:

D3-D0    Биты определяют величину горизонтального сдвига:

Биты

Величина сдвига содержимого экрана (в пикселах)

D3 D2 D1 D0

Монохромный текстовый режим

Режим 13h

Остальные режимы

0  0  0  0

8

0

0

0  0  0  1

0

-

1

0  0  1  0

1

1

2

0  0  1  1

2

-

3

0  1  0  0

3

2

4

0  1  0  1

4

-

5

0  1  1  0

5

3

6

0  1  1  1

6

-

7

1  0  0  0

7

-

-

1  0  0  1

-

-

-

1  0  1  0

-

-

-

1  0  1  1

-

-

-

1  1  0  0

-

-

-

1  1  0  1

-

-

-

1  1  1  0

-

-

-

1  1  1  1

-

-

-

D7-D4    Не используются.

По умолчанию для всех режимов работы видеоадаптера регистр горизонтального панорамирования содержит нулевые значения для всех битов.

На рисунке 8.18 иллюстрируется операция горизонтального сдвига содержимого экрана при различных значениях регистра HPR. На левой части рисунка регистр горизонтального панорамирования содержит ноль, а на правой части рисунка значение регистра увеличено до трех. Изображение на экране сдвигается на три пиксела влево.

PICTURE._FIG_30.PCX;6";4.308";PCX

Рисунок 4.18   Горизонтальный сдвиг экрана

Программа SCRSPLIT позволяет перемещать содержимое экрана по горизонтали и вертикали. Исходный текст программы представлен в листинге 4.11.

Листинг 4.11. Файл SCRSPLIT.C

// Смещение содержимого экрана по горизонтали и вертикали

#include "sysgraph.h"

#include <stdio.h>

#include <stdlib.h>

#include <graph.h>

#include "sysp.h"

#include <dos.h>

void HorScroll(unsigned, unsigned);


void VerScroll(unsigned);

void SetColumn(unsigned char);

void main(void) {

  struct videoconfig vc;

  unsigned char   i,j;

  // выбираем текстовый режим работы видеоадаптера,

  // принятый по умолчанию

  _setvideomode(_DEFAULTMODE);

  // устанавливаем логическую ширину экрана в 100 символов

  SetColumn(100);

  // отображаем на экране монитора 24 строки текста

  for(i = 0; i < 24; i++)

                printf("\ntext text text");

  // производим горизонтальное смещение экрана

  // на i пикселов при каждом нажатии на клавиатуру

  for(i = 0; i < 13; i++) {

                getch();

                HorScroll(i,8);

  }

  // производим вертикальное смещение экрана

  // на i пикселов при каждом нажатии на клавиатуру

  for(i = 0; i < 13; i++) {

                getch();

                VerScroll(i);

  }

  getch();

_setvideomode(_DEFAULTMODE);

}

Сдвиг изображения на экране монитора выполняют функции HorScroll и VerScroll. Функция HorScroll сдвигает изображение в горизонтальном направлении, а функция VerScroll в вертикальном. Исходный текст функций представлен в листинге 4.12.

Листинг 4.12. Файл SPLIT.ASM

/**

*.Name  HorScroll

*

*.Title     Горизонтальный сдвиг содержимого экрана.

*

*.Descr  Функция смещает содержимое экрана влево на определенное

*                              число пикселов.

*

*.Proto   void HorScroll(unsigned offset, unsigned wide)

*

*.Params              unsigned  offset - величина смещения в пикселах,

*

*                              unsigned  wide   - ширина символов (8 или 9).

*

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

*

*.Sample               scroll.c

**/

void HorScroll(unsigned offset, unsigned wide) {

  unsigned start_addr_reg, panning_reg;

  div_t res;

  res = div(offset,wide);

  start_addr_reg = res.quot;

  panning_reg = (wide == 9) ?

                                                ((res.rem == 0) ? 8 : res.rem - 1 ) : res.rem;

  _asm {

                push       ds

; вычисляем адрес регистра состояния 1 (3BAh/3DAh)



                xor          ax,ax

                mov        es,ax

                mov        dx,es:[463h]

                add         dx,6

; ожидаем начало обратного вертикального хода луча

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

  wait_off:

                in             al,dx

                nop

                nop

                test         al,08h

                jnz           wait_off

  wait_on:

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

; вычисляем адрес порта индексного регистра контроллера ЭЛТ

                sub         dx,6

; выбираем для доступа младший байт регистра начального адреса

                mov        al,0Dh

                out          dx,al

; вычисляем адрес порта регистра данных контроллера ЭЛТ

                inc          dx

; устанавливаем новый начальный адрес

                mov        ax,start_addr_reg

                out          dx,al

; снова получаем адрес порта регистра состояния 1

                add         dx,5

; сбрасываем внутренний триггер контроллера атрибутов, управляющий

; адресацией его регистров

                in             al,dx

                nop

                nop

; выбираем регистр горизонтального панорамирования

                mov        dx,3C0h

                mov        al,13h

                out          dx,al

                mov        ax,panning_reg

                out          dx,al

                pop         ds

  }

}

/**

*.Name  VerScroll

*

*.Title     Вертикальный сдвиг содержимого экрана.

*

*.Descr  Функция смещает содержимое экрана вверх на определенное

*                              число пикселов.

*

*.Proto   void VerScroll(unsigned offset)

*

*.Params              unsigned  offset - величина смещения в пикслах.

*

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



*

*.Sample               scroll.c

**/

void VerScroll(unsigned offset) {

  unsigned start_addr_reg, preset_row_reg;

  div_t res;

  BIOS_VAR _far  *bios_var_ptr;

  bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410);

  res = div(offset,bios_var_ptr -> wCharHigh);

  start_addr_reg = res.quot * (bios_var_ptr -> wColumns);

  preset_row_reg = res.rem;

  _asm {

                push       ds

; вычисляем адрес регистра состояния 1 (3BAh/3DAh)

                xor          ax,ax

                mov        es,ax

                mov        dx,es:[463h]

                add         dx,6

; ожидаем начало обратного вертикального хода луча

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

  wait_off:

                in             al,dx

                nop

                nop

                test         al,08h

                jnz           wait_off

  wait_on:

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_on

; вычисляем адрес порта индексного регистра контроллера ЭЛТ

                sub         dx,6

; модифицируем младший байт регистра начального адреса

                mov        al,0Dh

                out          dx,al

                inc          dx

                mov        ax,start_addr_reg

                out          dx,al

                dec         dx

; модифицируем старший байт регистра начального адреса

                mov        al,0Ch

                out          dx,al

                inc          dx

                mov        al,ah

                out          dx,al

; вычисляем адрес порта регистра состояния 1

                add         dx,5

; ожидаем вертикальный обратный ход луча

wait_next:

                in             al,dx

                nop

                nop

                test         al,08h

                jz             wait_next



; определяем адрес порта индексного регистра контроллера ЭЛТ

                sub         dx,6

; устанавливаем регистр предустановки линии сканирования

                mov        al,8

                out          dx,al

                mov        ax,preset_row_reg

                inc          dx

                out          dx,al

                pop         ds

  }

}

/**

*.Name  SetColumn

*

*.Title     Установка логической ширины экрана.

*

*.Descr  Функция устанавливает логическую ширину экрана.

*

*.Proto   void SetColumn(unsigned char col)

*

*.Params              unsigned char  col - логическая ширина экрана (в символах).

*

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

*

*.Sample               scroll.c

**/

void SetColumn(unsigned char col) {

  _asm {

                xor          ax,ax

                mov        es,ax

; получаем адрес порта индексного регистра

; контроллера ЭЛТ (3B4h/3D4h)

                mov        dx,es:[463h]

; выбираем для обмена регистр логической ширины экрана

                mov        al,13h

                out          dx,al

; вычисляем адрес порта регистра данных контроллера ЭЛТ (3B5h/3D5h)

                inc          dx

; модифицируем переменную BIOS, содержащую число символов в строке

                mov        al,col

                mov        es:[44Ah],al

; регистр логической ширины экрана в текстовых режимах содержит

; смещение между соседними строками текста в словах

                shr          al,1

                out          dx,al

  }

}


Регистр маскирования цветовых слоев (Color Don't Care Register - CDCR) (индекс7)


Регистр используется в режиме сравнения цветов (см. регистр сравнения цветов - CCR). Если какие-либо биты D3-D0 содержат ноль, то при операции сравнения цветов соответствующие цветовые слои в рассмотрение не принимаются.

D0    Управление нулевым цветовым слоем.

D1    Управление первым цветовым слоем.

D2    Управление вторым цветовым слоем.

D3    Управление третьим цветовым слоем.

D7-D4    Не используются.

При установке режима работы в регистр заносятся  следующие значения:

Режим

3

7

F

10

Содержимое регистра

00

00

0Fh

0Fh



Регистр маскирования пикселов (Pixel Mask Register - PMR)


Фирма IBM в руководстве видеоадаптера VGA предупреждает, что доступ к регистру нежелателен. В противном случае могут разрушиться данные в таблице цветов.



Регистр определения различных режимов работы (Miscellaneous Output Register - MOR)


У видеоадаптера EGA данный регистр доступен только для записи. Вы можете записать в него новое значение через порт ввода/вывода с адресом 3C2h. Видеоадаптер VGA позволяет прочитать содержимое регистра MOR, но уже по адресу 3CCh. Ниже представлено описание отдельных битов регистра MOR:

Биты

Описание

D0

Выбор адресов портов ввода/вывода

D1

Разрешение доступа к видеопамяти

D2, D3

Выбор частоты

D4

Запрещение управления видеоадаптером

D5

Бит четной/нечетной страницы

D6

Полярность сигнала горизонтальной синхронизации

D7

Полярность сигнала вертикальной синхронизации

D7    Полярность сигнала вертикальной синхронизации. Нулевая величина для данного бита устанавливает положительную полярность сигнала, единичная - отрицательную. Монохромный, цветной и улучшенный цветной мониторы используют положительную полярность сигнала синхронизации.

D6    Полярность сигнала горизонтальной синхронизации. Нулевая величина для данного бита устанавливает положительную полярность, единичная - отрицательную. Монохромный монитор использует отрицательную полярность сигнала синхронизации, а цветной - положительную.

Улучшенный цветной монитор и аналоговый монитор используют биты D7 и D6 для определения частоты развертки. Следующая таблица содержит допустимые значения для этих битов:

D7 D6

EGA

VGA

00

200 линий

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

01

350 линий

350 линий

10

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

400 линий

11

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

480 линий

D5    Бит четной/нечетной страницы используется для режимов, которые передают данные по четным адресам в нулевой цветовой слой, а по нечетным - в первый. Все текстовые режимы устанавливают этот бит. Бит D5 выбирает одну из двух страниц видеопамяти.

D4    Управление видеоадаптером. Бит доступен только для видеоадаптера EGA. Видеоадаптеры VGA и SVGA этот бит не используют. Обычно бит D4 имеет значение 0. В этом случае управление монитором осуществляет видеоадаптер. Если бит D4 принимает значение 1, то монитор управляется сигналами, поступающими от разъема дополнительного устройства.


D2, D3   Биты выбора частоты управляют тактовой частотой видеоадаптера. Таблица, расположенная ниже, представляет правильные варианты установки битов D3 и D2:

D3

D2

Режим

0

0

640 пикселов в строке

0

1

720 пикселов в строке

1

0

Используется внешний генератор. Внешний генератор подключается через разъем дополнительного устройства)

1

1

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

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

D0    Выбор адресов портов ввода/вывода. Бит D0 определяет адрес регистра управления дополнительным устройством (Feature Control Register), регистра состояния 1 (Input Status Register 1) и регистров контроллера ЭЛТ (CRT Controller). Когда бит D0 равен нулю, происходит выбор адресного пространства монохромного режима (адреса 3Bхh). Если бит равен единице, то используется адресное пространство цветного режима работы видеоадаптера (адреса 3Dхh).

Данные, первоначально записываемые BIOS в этот регистр зависят от режима работы видеоадаптера:

Режим

0-6,0Dh,0Eh

7

Fh

10h

Содержимое регистра

23h

0A6h

0A2h

0A7h


Регистр определения структуры памяти (Memory Mode Register - MMR) (индекс4)


Регистр инициализируется BIOS во время выбора режима работы видеоадаптера и определяет структуру видеопамяти в этом режиме.

D0    Для видеоадаптера EGA бит D0 содержит единицу, при использовании в текстовом режиме функции выбора знакогенератора. Для адаптера VGA этот бит обычно сброшен в ноль.

D1    Для видеоадаптера EGA бит D1 равен единице, если объем видеопамяти больше 64 Кбайт.

D2    Если бит D2 содержит ноль, то доступ по четным адресам происходит к нулевому цветовому слою, а по нечетным - к первому.

D7-D3    Не используются.

При выборе режима работы адаптера, BIOS загружает в регистр CPWE следующие значения:

Режим

0,1,2,3,7

4,5

6,0Dh,0Eh

0Fh,10h

Содержимое регистра

03

02

06

00



Регистр разрешения цветового слоя (Color Plane Enable Register - CPER) (индекс12)


D3-D0    Биты разрешения цветовых слоем. Если бит равен нулю, то данные из соответствующего цветового слоя не поступают в регистры цветовой палитры. Таким образом, достигается эффект маскирования отдельных цветовых слоев.

D5-D4    Используются вместе с диагностическими битами регистра состояния 1 для чтения регистров палитры.

D7-D6    Не используются.

При установке режима работы видеоадаптера BIOS записывает в регистр следующие значения:

Режим

0,1,2,3,7,D,E

4,5

6

F,10

Содержимое регистра

0Fh

03

03

01

05



Регистр разрешения работы системы VGA (VGA Enable Register - VGA_ER)


Данный регистр имеет адрес 3С3h. Регистр используется только видеоадаптерами VGA и SVGA. Биты D1-D7 зарезервированы, а бит D0 управляет работой адаптера. Если бит D0 равен нулю, тогда запрещен доступ к видеопамяти и портам ввода/вывода видеоадаптера (кроме регистра VGA_ER).



Регистр разрешения установки/сброса (Set/Reset Enable Register - SRER) (индекс1)


Регистр разрешения установки/сброса позволяет при записи в видеопамять для одних цветовых слоев использовать данные от центрального процессора, а для других - из регистра установки/сброса (рис. 4.10).

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

Теперь приведем формат регистра разрешения установки/сброса:

D0    Разрешение использования данных из регистра установки/сброса для цветового слоя 0.

D1    Разрешение использования данных из регистра установки/сброса для цветового слоя 1.

D2    Разрешение использования данных из регистра установки/сброса для цветового слоя 2.

D3    Разрешение использования данных из регистра установки/сброса для цветового слоя 3.

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

По умолчанию во все биты регистра записываются нулевые значения.

Заметим, что возможность использования регистров установки/сброса можно реализовать только в нулевом режиме записи. Режим записи устанавливается регистром режима работы графического контроллера (Mode Register, индекс 5). В нулевом режиме записи, если запрещено выполнение операции маскирования пикселов (регистр битовой маски содержит значение 0FFh), то каждый байт, записываемый процессором в видеопамять определяет 8 пикселов в одном или нескольких цветовых слоях.

Рассмотрим на рисунке 4.10 применение регистров установки/сброса. Пусть графический контроллер находится в нулевом режиме работы, и регистр битовой маски равен 0FFh (используются только данные от процессора). В этом случае можно использовать регистры установки/сброса.

Допустим, что после преобразования данных, записываемых процессором в видеопамять, в соответствии со значением регистра циклического сдвига и выбора функций, данные имеют следующий вид:

          байт 11110000b передается в третий слой видеопамяти,

          байт 00000011b передается во второй слой видеопамяти,

          байт 00110011b передается в первый слой видеопамяти,

          байт 00110011b передается в нулевой слой видеопамяти.

Данные, записываемые в видеопамять зависят от значения регистра разрешения установки/сброса. Биты D3 и D0, регистра разрешения установки/сброса равны нулю, поэтому в третий слой и нулевой слой видеопамяти данные заносятся без изменения. Биты D2 и D1 регистра разрешения установки/сброса равны единице, значит во второй и первый слои видеопамяти записываются данные в соответствии со значением битов D2 и D1 регистра установки/сброса. То есть во второй слой записывается байт 00000000b, а в первый - 11111111b.

PICTURE._FIG_24.PCX;6";4.308";PCX

Рисунок 4.10  Использование регистров установки/сброса



Регистр разрешения записи цветового слоя (Color Plane Write Enable - CPWE) (индекс2)


При помощи данного регистра можно запретить запись данных в любые цветовые слои видеопамяти. На рисунке 4.8 показан механизм запрещения записи данных в отдельные слои видеопамяти. Рассмотрим процесс записи данных процессором в видеопамять:

ПЕРВЫЙ ШАГ

          Процессор передает видеоадаптеру данные для записи в видеопамять. Они проходят через графический контроллер и попадают в синхронизатор. Графический контроллер выполняет над данными, записываемыми в видеопамять, операции, определяемые состоянием его регистров (смотри главу "Исполнение видеоадаптером операции записи" из раздела "Графический контроллер").

ВТОРОЙ ШАГ

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

PICTURE._FIG_17.PCX;6";4.308";PCX

Рисунок 4.8   Разрешение записи в цветовые слои

Биты регистра разрешения записи цветового слоя имеют следующие значения:

D0    Если бит D0 равен единице, то можно записывать данные в нулевой цветовой слой.

D1    Если бит D1 равен единице, то можно записывать данные в первый цветовой слой.

D2    Если бит D2 равен единице, то можно записывать данные в второй цветовой слой.

D3    Если бит D3 равен единице, то можно записывать данные в третий цветовой слой.

D7-D4    Не используются.

При установке режима работы адаптера BIOS загружает в регистр CPWE следующие значения:

Режим

0,1,2,3,4,5,7

6

D,E,F,10

Содержимое регистра

03

01

0Fh



Регистр режима работы (Mode Register - MDR) (индекс5)


Регистр управляет несколькими функциями графического контроллера. В частности он управляет режимом записи в видеопамять и режимом сравнения цветов (см. регистр сравнения цветов графического контроллера).

Биты

Описание

D1-D0

Режим записи

D2

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

D3

Разрешение режима сравнения цветов

D4

Четный/нечетный режим

D5

Режим регистра сдвига

D6

Управление режимом VGA с 256 цветами (режим номер 13h)

D7

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

Ниже подробно рассмотрены отдельные биты регистра MDR. Изменение битов D4-D7, может привести к потере изображения на экране монитора. Обычно эти биты загружаются только при установке режима работы видеоадаптера.

D1, D0 Данные биты устанавливают режим записи в видеопамять. Вы можете выбрать один из трех режимов записи:

D1 D0

Номер режима

Режим записи

0  0

0

Режим непосредственной записи

0  1

1

Использование для записи регистров-защелок

1  0

2

Заполнение N-ого цветового слоя битом номер N из данных, записываемых процессором

1  1

-

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

       Режим 0 (рис. 4.14). Режим непосредственной записи. Процессор имеет доступ к видеопамяти. Видеоадаптер может выполнять следующие операции: установка/сброс, циклический сдвиг, вызов логических функций. В этом режиме также возможно использование регистра битовой маски.

PICTURE._FIG_27.PCX;6";4.308";PCX

PICTURE._FIG_28.PCX;6";4.308";PCX

Рисунок 4.14   Режим записи 0

       Режим 1 (рис. 4.15). Режим записи, использующий регистры-защелки. При чтении данных из видеопамяти происходит запись восьми битов из каждого цветового слоя в регистры-защелки. Затем, при выполнении операции записи, содержимое регистров-защелок может быть записано обратно в видеопамять, но уже по другому адресу. Этот режим можно использовать для быстрого копирования данных из одной области видеопамяти в другую.

PICTURE._FIG_27.PCX;6";4.308";PCX

PICTURE._FIG_28.PCX;6";4.308";PCX


Рисунок 4.15   Режим записи 1

       Режим 2 (рис. 4.16). В режиме 2 происходит заполнение N-ого цветового слоя битом с порядковым номером N из байта данных, переданного процессором  видеоадаптеру для записи. Содержимое четырех старших битов записываемого байта (то есть битов D4-D7) значения не имеет.



PICTURE._FIG_27.PCX;6";4.308";PCX

PICTURE._FIG_28.PCX;6";4.308";PCX

Рисунок 4.16   Режим записи 2

D3    Бит D3 управляет режимом сравнения цветов (см. регистр сравнения цветов графического контроллера). Для перевода видеоадаптера в режим сравнения цветов бит D3 должен содержать единицу.

Остальные биты регистра модифицировать не рекомендуется.

D4    Бит D4 устанавливается в текстовых режимах. В этом случае доступ по четным адресам происходит к четным цветовым слоям, а по нечетным адресам - к нечетным цветовым слоям видеопамяти (см. видеопамять в текстовых режимах).

D5    Бит D5 используется в режимах видеоадаптера номер 4 и 5 для обработки видеоданных в формате "два бита на пиксел".

D6    Бит D6 используется видеоадаптерами VGA и SVGA в режиме с 256 цветами (режим 13h).

При установке режима работы видеоадаптера BIOS загружает в регистр MDR следующие значения, в зависимости от режима работы видеоадаптера:

Режим

0,1,2,3,7,F,10

4,5

6,D,E

Содержимое регистра

10h

30h

00


Регистр режима синхронизации (Clock Mode Register - CMR) (индекс1)


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

Перед модификацией регистра CMR надо сбросить бит D1 в регистре сброса синхронизатора, переведя, таким образом, синхронизатор в режим синхронного сброса и остановки.

D0    Бит определяет ширину символов в текстовых монохромных режимах с разрешением 720 пикселов по горизонтали. Если бит D0 равен нулю, то ширина матрицы символов составляет 9 пикселов, если единице - 8 пикселов.

D1    Бит используется видеоадаптером EGA для определения числа циклов, отводимых центральному процессору, для доступа к видеопамяти. При D1 равном единице, процессор может получить три из каждых пяти циклов, а при D1 равном нулю - только один из пяти циклов. Остальные циклы используются адаптером для регенерации видеопамяти.

D4-D2    Не используются.

D5    Используется только видеоадаптерами VGA и SVGA. Если бит D5 равен единице, то экран монитора гаснет и центральный процессор получает монополию на доступ к видеопамяти. Это несколько ускоряет процесс обмена процессора с видеопамятью.

D7-D6    Не используются.

Ниже приведены значения регистра CMR, устанавливаемые BIOS при установке режима работы адаптера:

Режим

00,01,04,05,0Dh

02,03,06,0Eh

0Fh,10h

Содержимое регистра

0Bh

01

05



Регистр сброса синхронизатора (Reset Register - RR) (индекс 0)


Если регистр переведен в состояние сброса, то все процессы видеоадаптера приостанавливаются. В результате могут быть разрушены данные в видеопамяти.

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

D1    Бит синхронного сброса. Нулевое значение сбрасывает и останавливает синхронизатор в конце исполняемого цикла.

D7-D2    Не используются.

Для нормальной работы видеоадаптера биты D0 и D1 должны быть равны единице. Перед доступом к регистру режима синхронизации синхронизатор должен быть переведен в состояние синхронного сброса (бит D1 равен 0).



Регистр сброса триггера-защелки светового пера (Light Pen Latch Reset Register - LPLRR)


В цветных режимах регистр LPLRR доступен через порт 3DBh, а в монохромных режимах через порт 3BBh. Регистр используется только видеоадаптерами CGA и EGA. Любая операция записи в регистр LPLRR сбрасывает триггер-защелку светового пера.



Регистр смешанного назначения (Miscellaneous Register - MIR) (индекс6)


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

D0    Бит разрешения графического режима. Бит должен содержать 1 для графического и 0 для текстового режима. В графическом  режиме запрещается генерация символов и разрешается адресация к отдельным пикселам.

D1    Используется видеоадаптерами EGA, имеющими 64 Кбайт памяти. Если бит D1 установлен, то четыре слоя видеопамяти по 16 Кбайт каждый объединяются в два слоя по 32 Кбайт.

D3-D2    Биты D3 и D2 устанавливают начальный и конечный адреса, на которые отображается видеопамять адаптера EGA:

D3 D2           Адреса видеопамяти

0    0              A000:0000h-B000:FFFFh

0    1              A000:0000h-A000:FFFFh

1    0              B000:0000h-B000:7FFFh

0    1              B800:0000h-B000:FFFFh

D7-D4    Не используются.

При установке режима работы видеоадаптера BIOS загружает в регистр MIR следующие значения, в зависимости от режима работы видеоадаптера:

Режим

3

7

F

10

Содержимое регистра

Eh

Ah

07

05



Регистр состояния 0 (Input Status Register 0 - ISR0)


Регистр ISR0 доступен через порт 3C2h только для чтения. Формат регистра приведен ниже:

Биты

Описание

D3-D0

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

D4

Состояние переключателей

D5

Бит 0 дополнительного устройства (FEAT0)

D6

Бит 1 дополнительного устройства (FEAT1)

D7

Бит прерывания от ЭЛТ

D7    Бит установлен в 1, во время обратного вертикального хода луча (погашенный луч перемещается из правого нижнего угла экрана в левый верхний). Бит D7 устанавливается в начале обратного вертикального хода луча и сбрасывается при записи в регистр конца вертикального хода луча.

D6    Бит 1 дополнительного устройства. Используется только видеоадаптерами EGA. Бит D6 регистра управляет уровнем сигнала FEAT0 (вывод 17 разъема дополнительного устройства).

D5    Бит 0 дополнительного устройства. Используется только видеоадаптерами EGA. Бит регистра управляет уровнем сигнала FEAT1 (вывод 19 разъема дополнительного устройства).

D4    Состояние переключателей. Проанализировав бит D4, функции BIOS EGA могут определить состояние четырех переключателей, находящихся на плате видеоадаптера. Номер считываемого переключателя задается двумя битами выбора частоты (D2 и D3) регистра определения различных режимов работы (MOR), согласно следующей таблице:

Бит D3

Бит D2

Номер переключателя

0

0

1

0

1

2

1

0

3

1

1

4

Если бит D4 установлен в единицу, то переключатель, заданный битами D2 и D3 регистра определения различных режимов работы, находится в положении ON. Если бит сброшен в ноль, то переключатель находится в положении OFF.

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

Если к компьютеру подключены два видеоадаптера, то один из них является первичным, а другой дополнительным. Первичный видеоадаптер используется по умолчанию сразу после включения компьютера.


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

4

3

2

1

ON

Первичный: EGA с цветным монитором (40х25)

OFF

Дополнительный: MDA

4

3

2

1

ON

Первичный: EGA с цветным монитором (80х25)

OFF

Дополнительный: MDA

4

3

2

1

ON

Первичный: EGA с улучшенным цветным монитором

OFF

Дополнительный: MDA

4

3

2

1

ON

Первичный: EGA с улучшенным цветным монитором

OFF

Дополнительный: MDA

4

3

2

1

ON

Первичный: EGA с монохромным монитором

OFF

Дополнительный: CGA с цветным монитором (40х25)

4

3

2

1

ON

Первичный: EGA с монохромным монитором

OFF

Дополнительный: CGA с цветным монитором (80х25)

4

3

2

1

ON

Первичный: MDA

OFF

Дополнительный: EGA с цветным монитором (40х25)

4

3

2

1

ON

Первичный: MDA

OFF

Дополнительный: EGA с цветным монитором (80х25)

4

3

2

1

ON

Первичный: MDA

OFF

Дополнительный: EGA с цветным монитором (80х25)

4

3

2

1

ON

Первичный: MDA

OFF

Дополнительный: EGA с цветным монитором

4

3

2

1

ON

Первичный: CGA с цветным монитором 40х25

OFF

Дополнительный: EGA с монохромным монитором

<


/p>
4

3

2

1

ON

Первичный: CGA с цветным монитором 80х25

OFF

Дополнительный: EGA с монохромным монитором

Видеоадаптеры VGA и SVGA используют бит D4 для определения типа монитора (цветной или монохромный). Положение этих переключателей может быть считано из оперативной памяти по адресу 0000:0488h:

Биты

Описание

D3-D0

Биты, соответствующие переключателям. Если бит установлен в единицу, то соответствующий переключатель находится в положении ON. Если бит сброшен в ноль, то переключатель находится в положении OFF

D7-D4

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


Регистр состояния 1 (Input Status Register 1 - ISR0)


Регистр позволяет получить различную информацию о состоянии видеоадаптера. Для видеоадаптера CGA содержимое регистра можно считать через порт, имеющий адрес 3DAh. Для адаптеров EGA, VGA и SVGA данный регистр, имеет адрес 3BAh в монохромных режимах и адрес 3DAh - в цветных. Регистр состояния 1 доступен только для чтения.

Приведем формат регистра состояния 1:

Биты

Описание

D0

Бит разрешения отображения

D1

Бит триггера светового пера

D2

Бит переключателя светового пера

D3

Бит обратного вертикального хода

D5-D4

Диагностические биты

D7-D6

Биты не используются

D7, D6   Биты не используются

D5, D4   Диагностические биты позволяют проверить два из шести цветовых выходных сигналов передаваемых монитору (для видеоадаптера EGA). Для выбора проверяемых сигналов используют регистр разрешения цветового слоя контроллера атрибутов:

Регистр разрешения цветового слоя

Регистр состояния 1

D5

D4

D5

D4

0

0

Красный

Синий

0

1

Второй красный

Второй зеленый

1

0

Второй синий

Зеленый

1

1

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

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

Следующая таблица показывает, как можно считать два из восьми цветовых сигналов, вырабатываемых контроллером атрибутов видеоадаптера VGA:

Регистр разрешения цветового слоя

Регистр состояния 1

D5

D4

D5

D4

0

0

P2

P0

0

1

P5

P4

1

0

P3

P1

1

1

P7

P6

Биты D5 и D4 позволяют прочитать содержимое регистров таблицы цветовой палитры видеоадаптера EGA. Следует отметить, что некоторые адаптеры, совместимые с EGA, не поддерживают эти биты. Поэтому их использование может наложить ограничения на работу программы.

D3    Бит обратного вертикального хода луча. Бит принимает значение 1 в течение обратного вертикального хода луча по кадру. Данный бит также установлен в случае, если разрешено прерывание IRQ2, и любое устройство компьютера выдает запрос на это прерывание.

Биты D2 и D1 управляют световым пером. Видеоадаптеры VGA и SVGA не поддерживают световое перо, поэтому биты D2 и D1 не используются.


D2    Бит переключателя светового пера. Если переключатель светового пера находится в положении ON (включено), то бит D2 равен единице. Если переключатель находится в положении OFF (выключено), то бит D2 равен нулю.

D1    Бит триггера светового пера. Бит равен единице, если триггер светового пера установлен. Сброс бита происходит при записи нуля через порт с адресом 3BBh для монохромного режима, или через порт 3DBh - для цветного режима.

D0    Бит разрешения отображения. Бит принимает значение единицы во время интервала активности монитора (когда адаптер читает данные из видеопамяти), и равен нулю во время горизонтального и вертикального обратного хода луча.

Во многих случаях возникает необходимость синхронизовать программирование регистров видеоадаптера с периодом вертикального или горизонтального обратного хода луча. Этого можно достичь периодической проверкой регистра состояния 1.

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

Листинг 4.2. Файл RASTR.C

// Программа определения частоты кадров

#include  <time.h>

#include  <stdio.h>

#include  <bios.h>

#define   NUM  200

// Описания функций. Смотри файл DISPLAY.ASM

void                        __pascal __far WaitVert(void);

unsigned               __pascal __far HorByVer(void);

//===========================================================

// Главная функция

//===========================================================

void main() {

  time_t  t_start, t_end;

  int                          i;

  float                      fr;

  unsigned             vert_fr;

  // Определяем начальное время

  t_start = clock();

  // Ожидаем исполнения NUM вертикальных разверток

  for(i = 0; i < NUM; i++) WaitVert();

  // Определяем конечное время

  t_end = clock();

  // Вычисляем частоту кадров

  fr = NUM/(((float)t_end - t_start) / CLK_TCK);

  printf( "\nЧастота кадров = %4.1f \n", (float)fr );



}

Исходный текст функции WaitVert представлен в листинге 4.3. Функция WaitVert периодически проверяет регистр состояния 1 (ISR1), ожидая начало обратного вертикального хода луча по экрану монитора.

Листинг 4.3. Файл DISPLAY.ASM

TITLE      DISPLAY.ASM

NAME     DISPLAY

PAGE      55,132

P286

IDEAL

NOWARN BRK

SEGMENT WAIT_TEXT WORD PUBLIC 'CODE'

ASSUME                cs:WAIT_TEXT

;===========================================================

; Функция void WaitVert(void)

;===========================================================

PUBLIC  WAITVERT

PROC     WAITVERT FAR

  enter    0, 0

  mov  ax,0h

  mov  es,ax

  ; Определяем адрес порта индексного регистра контроллера

  ; ЭЛТ (3B4h/3D4h)

  mov  dx,es:[463h]

  ; Вычисляем адрес порта регистра состояния 1 (ISR1)

  add  dl,6

  ; Читаем содержимое порта регистра состояния 1

  in   al,dx

  ; Тестируем бит D3 регистра состояния 1

  ; бит D3 = 1 при обратном вертикальном ходе луча

  test al,8

  jz   wait_on

wait_off:

  in   al,dx

  ; Тестируем бит D3

  test al,8

  ; Ожидаем конец обратного вертикального хода луча

  jnz  wait_off

wait_on:

  in   al,dx

  test al,8

  ; Ожидаем начало обратного вертикального хода луча

  jz   wait_on

  ; +------------------------------------------------------+

  ;  Здесь могут распологаться операции, которые необходимо

  ;  выполнить  во время обратного  вертикального хода луча

  ; +------------------------------------------------------+

  leave

  ret

  ENDP    WAITVERT

ENDS      WAIT_TEXT

END


Регистр состояния ЦАП (DAC State Register - DAC_SR)


Регистр адресуется при помощи порта с адресом 3C7h и доступен только для чтения. Прочитав данные из регистра, можно определить, доступны регистры цветовой таблицы для чтения или же они доступны для записи.

D1-D0    Если биты D0 D1 содержат двоичное число 11b, то регистры цветовой таблицы доступны для записи, если D0 D1 содержат двоичное число 00b (шестнадцатиричное 0), то регистры цветовой таблицы доступны для чтения.

D7-D2    Не используются.



Регистр сравнения цветов (Color Compare Register - CCR) (индекс2)


Регистр CCR можно использовать для поиска на экране пикселов с определенным цветом. Без использования регистра CCR за один цикл чтения видеопамяти процессор может считать данные только из одного цветового слоя. Программирование регистра CCR позволяет за один цикл чтения прочитать все четыре цветовых слоя, сравнить считанные значения с искомыми и возвратить результат.

Ниже представлен формат регистра сравнения цветов:

D0    Искомая величина для нулевого цветового слоя.

D1    Искомая величина для первого цветового слоя.

D2    Искомая величина для второго цветового слоя.

D3    Искомая величина для третьего цветового слоя.

D7-D4    Не используются.

После выполнения BIOS установки режима работы видеоадаптера все биты регистра содержат нулевые значения.

Операция поиска пикселов данного цвета иллюстрируется рисунком 4.11.

PICTURE._FIG_25.PCX;6";4.308";PCX

Рисунок 4.11   Использование регистра CCR

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

Перед использованием регистра CCR для выполнения операции поиска пикселов определенного цвета необходимо установить регистр режима работы (Mode Register - MDR) и регистр маскирования цветовых слоев (Color Don't Care Register - CDCR), описанные ниже.



Регистр сравнения линий (Line Compare Register - LCR) (индекс18h)


Позволяет разделить изображение на две независимые части. При этом одну из них можно свертывать. Содержимое другой части экрана остается на месте.

Регистр LCR используют совместно с регистром начального адреса. Когда счетчик горизонтальных линий сканирования достигает значения, записанного в регистре LCR, происходит сброс счетчика адреса регенерируемой видеопамяти в ноль. В результате экран разбивается на две части. В верхней части экрана отображаются данные, на которые указывает регистр начального адреса, а в нижней - данные, находящиеся в начале видеопамяти. Процесс разделения экрана иллюстрируется рисунком 4.7.

PICTURE._FIG_39.PCX;6";4.308";PCX

Рисунок 4.7   Процесс разделения экрана

Изображение в верхней части экрана можно перемещать, изменяя содержимое регистра начального адреса.

У видеоадаптера EGA регистр сравнения линий имеет 9 разрядов. Девятый бит регистра доступен через дополнительный регистр (OVR) контроллера ЭЛТ. Регистр сравнения линий видеоадаптера VGA имеет 10 разрядов. Десятый бит регистра LCR расположен в регистре MSLR.

При изменении режима работы видеоадаптера, BIOS записывает в регистр сравнения линий значение 0FFh.

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

Листинг 4.9. Файл SCRSPLIT.C

#include <dos.h>

#include <stdio.h>

#include <conio.h>

void        __pascal __far Split(unsigned);

void        main(void);

// Главная функция

void main(void) {

 

int   i;

 

for(i = 0; i < 25; i++)

                                 

printf("Строка номер %d.\n",i);

 

getch();

// Разделяем экран по линии 200

 

Split(200);

// Ожидаем нажатие на клавиши клавиатуры

 

getch();

// После завершения программы значения регистров не

// восстанавливеются!

}

Для разделения изображения на экране монитора предназначена функция Split. Исходный текст этой функции представлен в листинге 4.10.

Листинг 4.10. Файл SPLIT.ASM


TITLE      SPLIT.ASM

NAME     SPLIT

PAGE      55,132

P286

IDEAL

NOWARN BRK

SEGMENT SPLIT_TEXT WORD PUBLIC 'CODE'

ASSUME                cs:SPLIT_TEXT

;===========================================================

; void Split(unsigned split_line)

; Функция разделяет экран на две части. Функция работает

; только на видеоадаптерах EGA и VGA.

; Параметр split_line определяет линию горизонтальной

; развертки, в которой происходит разделение экрана монитора

;===========================================================

split_line               EQU        [bp+6]

PUBLIC  SPLIT

PROC     SPLIT FAR

  enter    0, 0

  ; Устанавливаем регистр ES на начало оперативной памяти

  xor   ax,ax

  mov   es,ax

  ; Получаем адрес порта индексного регистра контроллера ЭЛТ

  ; (3B4h/3D4h), в монохромных режимах для адресации к

  ; индексному регистру используется порт с адресом 3B4h, а

  ; в цветных - порт 3D4h

  mov   dx,es:[463h]

  ; Вычисляем адрес порта регистра состояния 1, в

  ; монохромных режимах для адресации к регистру состояния 1

  ; используется порт с адресом 3BAh, в цветных - порт 3DAh

  add   dx,6

  ; Ожидаем начало обратного вертикального хода луча

  in    al,dx

  nop

  ; Если бит D3 равен единице, то происходит обратный

  ; вертикальный ход луча

  test  al,8

  jz    wait_on

wait_off:

  in    al,dx

  nop

  test  al,8

  jnz    wait_off

wait_on:

  in    al,dx

  nop

  test  al,8

  jz    wait_on

  ; Вычисляем адрес порта индексного регистра

  ; контроллера ЭЛТ (3B4h/3D4h)

  sub   dx,6

  ; Выбираем для обмена регистр сравнения линий

  mov   al,18h

  out   dx,al

  ; Вычисляем адрес порта регистра данных контроллера ЭЛТ,

  ; в монохромных режимах для адресации к регистру данных

  ; используется порт с адресом 3B5h, а в цветных порт 3D5h

  inc   dx

  ; Определяем линию горизонтальной развертки, в которой

  ; происходит разделение экрана дисплея

  mov   ax,split_line

  ; У видеоадаптера EGA регистр сравнения линий состоит из 9

  ; бит, доступ к девятому биту происходит через



  ; дополнительный регистр контроллера ЭЛТ; видеоадаптер

  ; VGA имеет еще и десятый бит, расположенный в регистре

  ; высоты символов текста

  ; Записываем младшие 8 битов в регистр сравнения линий

  out   dx,al

  ; Вычисляем адрес порта индексного регистра

  ; контроллера ЭЛТ

  dec   dx

  ; Вызываем функцию чтения конфигурации видеосистемы

  mov   ax,1A00h

  int   10h

  ; Если после вызова функции регистр AL не равен 1Ah, то

  ; используемый видеодаптер не VGA

  cmp   al,1Ah

  je    vga

  jmp   ega

vga:

  ; Считываем в AL состояние дополнительнго регистра

  mov   al,7

  out   dx,al

  inc   dx

  in    al,dx

  ; Модифицируем бит D4 дополнительного ргистра

  mov   bx,split_line

  mov   cl,4

  shl   bh,cl

  and   bh,00010000b

  and   al,11101111b

  or    al,bh

  out   dx,al

  ; Сбрасываем бит D6 регистра высоты символов текста

  dec   dx

  mov   al,9

  out   dx,al

  inc   dx

  in    al,dx

  and   al,10111111b

  out   dx,al

  jmp   quit_split

ega:

  mov   bx,split_line

  mov   cl,4

  shl   bh,cl

  and   bh,00010000b

  cmp   dx,3B4h       ; монохромный режим?

  je    default_1Fh

  ; Определяем наличие улучшенного цветного дисплея по

  ; положению переключателей на плате EGA

  mov   al,es:[488h]

  and   al,0Fh

  ; Положение переключателей "OFF OFF ON ON" ?

  cmp   al,3

  je    default_1Fh

  ; Положение переключателей "OFF ON ON OFF" ?

  cmp   al,9

  je    default_1Fh

  ; Для видиосистем с монохромным или цветным дисплеями,

  ; дополнительный регистр по умолчанию содержит 11h

  or    bh,1

  jmp   set_overflow

  ; Для видиосистем с улучненным цветным дисплеем или в

  ; монохромных текстовых режимах дополнительный регистр по

  ; умолчанию содержит 1Fh

default_1Fh:

  or    bh,0Fh

  ; Устанавливаем дополнительный регистр

set_overflow:

  mov   al,07h

  out   dx,al

  inc   dx

  mov   al,bh

  out   dx,al

quit_split:

  leave

  ret 2

ENDP      SPLIT

ENDS      SPLIT_TEXT

END


Регистр управления дополнительным устройством (Feature Control Register - FCR)


Для видеоадаптера EGA биты D1 и D0 данного регистра передают сигналы на разъем дополнительного устройства. Бит D0 соответствует линии FC0 (вывод 21 разъема дополнительного устройства), а бит D1 линии FC1 (вывод 20 разъема дополнительного устройства).

Регистр не используется для видеоадаптеров VGA и SVGA, однако бит D3 в этом случае должен содержать ноль.

Адрес порта ввода/вывода регистра FCR зависит от режима работы видеоадаптера. В монохромных режимах адрес порта 3BAh, а в цветных - 3DAh. У видеоадаптера EGA регистр FCR доступен только для записи. Видеоадаптеры VGA и SVGA позволяют прочитать его содержимое через порт 3CAh.



Регистр управления режимом (Mode Control Register - MCR) (индекс10h)


Регистр управления режимом управляет контроллером атрибутов.

D0    Бит D0 содержит ноль для текстовых режимов, единицу - для графических. Бит определяет метод интерпретации атрибутов.

D1    Бит D1 определяет тип атрибутов. Для монохромных режимов он должен быть равен единице, а для режимов - нулю.

D2    Бит используется в монохромных режимах с разрешением по горизонтали 720 пикселов для расширения горизонтального размера матриц символов псевдографики с 8 до 9 пикселов. Если бит D2 равен 1, то девятый пиксел в каждой строке будет повторять восьмой. В противном случае девятый пиксел отображается цветом фона.

D3    Бит D3 управляет назначением седьмого бита в байте атрибутов. Если бит установлен, то бит D7 байта атрибутов управляет миганием символа. Если бит D3 равен нулю, то - интенсивностью фона.

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

D5    Доступен только для видеоадаптеров VGA и SVGA. Совместно с регистром разделения экрана монитора (регистр контроллера ЭЛТ) бит D5 управляет горизонтальной сверткой экрана. При установке бита D5 запрещается горизонтальная свертка стационарной части экрана.

D6    Бит D6 используется только видеоадаптерами VGA и SVGA. Бит должен быть равен нулю для режима с 256 цветами (режим 13h).

D7    Доступен только для видеоадаптеров VGA и SVGA. Выбор источника сигнала для видеовыходов Р4 И Р5. Если D7 равен нулю, то линии Р4 и Р5 управляются регистрами палитры. В противном случае сигналы на линии Р4 и Р5 поступают из битов D0 и D1 регистра выбора цветов.

По умолчанию регистр содержит следующие значения:

Режим

0,1,2,3

4,5,6,D,E,10

7

F

Содержимое регистра

08

01

0Eh

0Bh



Регистр установки/сброса (Set/Reset Register - SRR) (индекс 0)


Регистр SRR совместно с регистром разрешения установки/сброса (Set/Reset Enable Register), управляет записью данных в видеопамять. Возможности использования регистра SRR разъясняются при описании регистра разрешения установки/сброса.

Приведем формат регистра установки/сброса:

D0    Данные, записываемые в цветовой слой 0.

D1    Данные, записываемые в цветовой слой 1.

D2    Данные, записываемые в цветовой слой 2.

D3    Данные, записываемые в цветовой слой 3.

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

По умолчанию во все биты регистра записываются нулевые значения.