3. Архитектура видеоадаптеров EGA и VGA

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

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

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

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

Генерирует временные синхросигналы, управляющие ЭЛТ.

Преобразует информацию о цвете из формата, в котором она хранится в видеопамяти, в формат, необходимый для ЭЛТ. Преобразование цветов осуществляется в соответствии с таблицей цветовой палитры (Color Look-up Table). Модифицируя таблицу цветовой палитры, можно выбрать 16 цветов, поддерживаемых видеоадаптером EGA из 64 цветов, которые может отображать цветной улучшенный монитор.

Определяет все временные параметры видеоадаптера. Синхронизатор также управляет доступом процессора к цветовым слоям видеопамяти

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

Рисунок 3.1 Блок схема видеоадаптеров EGA/VGA

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

Монитор

В большинстве мониторов устройство отображения представляет собой электронно-лучевую трубку, газоразрядную или жидкокристаллическую панель. Для стационарных компьютеров обычно используются мониторы с ЭЛТ. Газоразрядные и жидкокристаллические панели применяют в переносных и блокнотных компьютерах.

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

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

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

Рисунок 3.2 Экран электронно-лучевой трубки

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

Для решения задач управления лучом электронов служит большинство регистров контроллера электронно-лучевой трубки (контроллера ЭЛТ).

Видеопамять

Видеоадаптеры EGA и VGA содержат на своей плате до 256 Кбайт оперативной памяти, разделенной на четыре банка или, другими словами, на четыре цветовых слоя. Эти слои памяти размещаются в одном адресном пространстве. Таким образом, что по каждому адресу расположено четыре байта (по байту в каждом слое памяти). Какой из слоев памяти используется для записи или чтения данных процессором, определяется с помощью установки нескольких регистров адаптера.

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

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

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

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

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

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

Текстовый режим

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

Стандартные текстовые режимы работы видеоадаптеров позволяют вывести на экран 25 строк по 40 или 80 символов. Если перепрограммировать некоторые регистры видеоадаптера, то можно увеличить число отображаемых строк для адаптера EGA до 43, а для VGA до 50. Если в компьютере установлен видеоадаптер SVGA, вам могут быть доступны другие текстовые режимы - 80x60, 132x25, 132x43, 132x50, 132x60 символов.

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

Рисунок 3.3 Структура видеопамяти в текстовых режимах

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

Рисунок 3.4 Преобразование кода ASCII в образ символа на экране

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

Рисунок 3.5 Отображение цветовых слоев

Ниже приведен дамп видеопамяти в текстовом режиме с разрешением 80х25 символов:


Адрес           0  1   2   3  4   5   6   7  8   9   A  B   C   D  E  F    0123456789ABCDEF
-----------------------------------------------------------------------------
B800:0000  91 07 E2 07 E0 07 AE 07-AA 07 A0 07 20 07 AD 07   С.т.р.о.к.а. .н.
B800:0010  AE 07 AC 07 A5 07 E0 07-20 07 30 07 20 07 20 07   о.м.е.р. .0. . .
B800:0020  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0030  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0040  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0050  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0060  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0070  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0080  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0090  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .

B800:00A0  91 07 E2 07 E0 07 AE 07-AA 07 A0 07 20 07 AD 07   С.т.р.о.к.а. .н.
B800:00B0  AE 07 AC 07 A5 07 E0 07-20 07 31 07 20 07 20 07   о.м.е.р. .1. . .
B800:00C0  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:00D0  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:00E0  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:00F0  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0100  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0110  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0120  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .
B800:0130  20 07 20 07 20 07 20 07-20 07 20 07 20 07 20 07    . . . . . . . .

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

Знакогенератор

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

Благодаря этому, можно легко заменить стандартную таблицу знакогенератора своей собственной. Эта особенность, широко применяется при русификации компьютеров. У видеоадаптера CGA таблицы знакогенератора расположены в ПЗУ, поэтому изменить образы символов текстового режима нельзя.

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

Каждая такая таблица знакогенератора содержит описание 256 символов. Активными могут быть одна или две таблицы знакогенератора. Это дает возможность одновременно отображать на экране до 512 различных символов.

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

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

Рисунок 3.6 Активные таблицы знакогенераторов

Видеоадаптер EGA поддерживает два размера для матриц символов - стандартный и улучшенный. Стандартный размер составляет 8 пикселов в ширину и 8 пикселов в высоту, а улучшенный - 8 пикселов в ширину и 14 пикселов в высоту. Один из этих наборов символов автоматически загружается BIOS в видеопамять при выборе текстового режима. Так как адаптеры VGA и SVGA имеют большую разрешающую способность, то их набор символов имеет в ширину 9 пикселов, а в высоту - 16.

Адреса таблиц знакогенератора для видеоадаптеров EGA, VGA и SVGA приведены в следующей таблице:

Первая таблица знакогенератора Вторая таблица знакогенератора
Символ ASCII 0 0000h-001Fh Символ ASCII 0 2000h-201Fh
Символ ASCII 1 0020h-003Fh Символ ASCII 1 2020h-203Fh
Символ ASCII 2 0040h-005Fh Символ ASCII 2 2040h-205Fh
... ... ... ...
Символ ASCII 255 1FE0h-1FFFh Символ ASCII 255 3FE0h-3FFFh
Третья таблица знакогенератора Четвертая таблица знакогенератора
Символ ASCII 0 4000h-401Fh Символ ASCII 0 6000h-601Fh
Символ ASCII 1 4020h-403Fh Символ ASCII 1 6020h-603Fh
Символ ASCII 2 4040h-405Fh Символ ASCII 2 6040h-605Fh
... ... ... ...
Символ ASCII 255 5FE0h-1FFFh Символ ASCII 255 7FE0h-7FFFh
Пятая таблица знакогенератора (только VGA) Шестая таблица знакогенератора (только VGA)
Символ ASCII 0 8000h-801Fh Символ ASCII 0 A000h-A01Fh
Символ ASCII 1 8020h-803Fh Символ ASCII 1 A020h-A03Fh
Символ ASCII 2 8040h-805Fh Символ ASCII 2 A040h-A05Fh
... ... ... ...
Символ ASCII 255 9FE0h-9FFFh Символ ASCII 255 BFE0h-BFFFh
Седьмая таблица знакогенератора (только VGA) Восьмая таблица знакогенератора (только VGA)
Символ ASCII 0 C000h-C01Fh Символ ASCII 0 E000h-E01Fh
Символ ASCII 1 C020h-C03Fh Символ ASCII 1 E020h-E03Fh
Символ ASCII 2 C040h-C05Fh Символ ASCII 2 E040h-E05Fh
... ... ... ...
Символ ASCII 255 DFE0h-DFFFh Символ ASCII 255 FFE0h-FFFFh

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

Атрибуты символов

Внешний вид символа, отображаемого на экране в текстовом режиме, определяется не только его кодом ASCII, но и байтом атрибутов. Атрибуты задают цвет символа, цвет фона, а также некоторые другие параметры:

Биты байта атрибутов Назначение
D2-D0 Цвет символа
D3 Интенсивность символа и выбор таблицы знакогенератора
D6-D4 Цвет фона символа
D7 Мигание символа или интенсивность фона символа

Биты D0-D2 байта атрибутов определяют цвет символа, а биты D4-D6 цвет фона, на котором отображается символ. Таким образом, можно независимо задавать до 23 = 8 различных цветов для текста и фона.

Бит D3 играет различную роль в зависимости от числа активных таблиц знакогенератора. Если активной является одна таблица, бит D3 используется для управления интенсивностью цвета символа, что позволяет увеличить количество воспроизводимых цветов от 8 до 16.

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

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

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

Код цвета в байте атрибутов Стандартный цвет Цвет с повышенной интенсивностью
000 Черный Серый
001 Синий Светло-синий
010 Зеленый Светло-зеленый
011 Морской волны Голубой
100 Красный Светло-красный
101 Фиолетовый Малиновый
110 Коричневый Желтый
111 Белый Ярко-белый

Атрибуты символов (монохромный режим)

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

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

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

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

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

Атрибут Внешний вид символа
00000000b (00h) Черный символ на черном фоне
00000001b (01h) Подчеркнутый символ
00000111b (07h) Обычный символ (светлый символ на черном фоне)
00001001b (09h) Подчеркнутый символ с повышенной интенсивностью
00001111b (0Fh) Символ с повышенной интенсивностью
01110000b (70h) Обратное отображение символа (черный символ на светлом фоне)
10000001b (81h) Подчеркнутый мигающий символ
10000111b (87h) Мигающий символ
10001001b (89h) Подчеркнутый мигающий символ с повышенной интенсивностью
11110000b (0F0h) Мигающее обратное отображение символа

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

Теперь приведем программу TEXTATTR (листинг 3.1), иллюстрирующую непосредственный доступ к видеопамяти в текстовых режимах работы адаптера. При запуске программы TEXTATTR вы должны указать ей два числовых параметра.

Первый параметр определяет режим работы видеоадаптера. Вы можете задать любой текстовый режим. Второй параметр управляет атрибутами символов, отображаемых на экране монитора. Если второй параметр равен 0, то бит D7 байта атрибутов управляет интенсивностью фона символов, а если он равен 1, то бит D7 байта атрибутов управляет миганием символов.

Листинг 3.1. Файл TEXTATTR.C


#include	<stdio.h>
#include	<conio.h>
#include	<dos.h>

// Файл для определения макрокоманды FP_MAKE
#include	"sysp.h"

// Файл для определения структуры VIDEOBUF
#include	"sysgraph.h"

// Описание функций
void	SetVideoMode( unsigned char vmode );
void	SetBlinkIntensity( unsigned char mode );
int	GetColumn(void);
int	GetVideoBuf(int);
void	Hello(void);
int	main( int, char ** );

//======================================================
// Главная функция программы
//======================================================
int main( int argc, char * argv[] )
{
	union REGS	inregs, outregs;
	VIDEOBUF	_far *vbuf, _far *ptr_vbuf;

	unsigned char	background, foreground;
	unsigned char	char_attr;

	int	vmode, bl_in_mode;
	char	szText[4];

	// Проверка командной строки программы
	if( argc != 3 )
	{
		Hello();
		return -1;
	}

	// Разбор строки параметров
	sscanf(argv[1],"%d",&vmode);
	sscanf(argv[2],"%d",&bl_in_mode);

	// Если указан графический режим, завершаем программу
	if(vmode > 3 && vmode != 7)
		return(-2);

	// Если неправильно указан параметр <интенсивность>,
	// завершаем программу
	if((bl_in_mode != 0)&&(bl_in_mode != 1))
		return(-3);

	// Устанавливаем новый режим работы видеоадаптера,
	// указанный параметром <режим>
	SetVideoMode((unsigned char) vmode );

	// Выбираем как будут интерпритироваться атрибуты
	// символов. Если параметр <интенсивность> равен 0
	// атрибуты управляют интенсивностью цвета символов,
	// если параметр равен 1 атрибуты управляют миганием
	//символов
	SetBlinkIntensity((unsigned char) bl_in_mode );

	// Определяем адрес начала активной страницы
	// видеопамяти
	ptr_vbuf = vbuf= (VIDEOBUF _far *)
		FP_MAKE(GetVideoBuf((unsigned char) vmode ),0);

	// Отображаем на экране массив символов, имеющих
	// различные атрибуты
	for( background=0; background<16; background++)
	{
		for( foreground=0; foreground<16; foreground++)
		{
			char_attr =
					(unsigned char)((background<<4) | foreground);

			sprintf( szText, "%02X", char_attr );

			// Отображаем на экране символ. Записываем
			// в видеопамять код символа и его атрибут
			ptr_vbuf->chr =
				szText[0];	ptr_vbuf->attr = char_attr;

			ptr_vbuf++;

			ptr_vbuf->chr =
				szText[1]; ptr_vbuf->attr = char_attr;

			ptr_vbuf++;
		}
		ptr_vbuf = vbuf = vbuf + GetColumn();
	}

	// Ожидаем нажатие на любую клавишу клавиатуры
	getch();

	// Устанавливаем текстотвый режим номер 3
	SetVideoMode(3);

	return 0;
}

//======================================================
// Функция возвращает сегментный адрес активной страницы
// видеопамяти (учитывается значение регистров смещения
// адреса видеопамяти)
//======================================================
int GetVideoBuf(int vmode) {

	unsigned vbase;
	unsigned adr_CRT;
	unsigned high;
	unsigned low;
	unsigned offs;

	// В зависимости от режима видеоадаптера базовый адрес
	// видеопамяти может быть 0xb000 или 0xb800
	vbase = (vmode == 7) ? 0xb000 : 0xb800;

	// Определяем адрес порта контроллера ЭЛТ
	adr_CRT = *(unsigned _far *)(FP_MAKE(0x40,0x63));

	// Считываем содержимое регистров начального адреса
	outp(adr_CRT,0xc);
	high = inp(adr_CRT+1);

	outp(adr_CRT,0xd);
	low = inp(adr_CRT+1);

	offs = ((high << 8) + low) >> 4;

	// Добавляем к базовому адресу видеопамяти смещение,
	// взятое из регистров начального адреса
	vbase += offs;

	return(vbase);
}

//======================================================
// Функция возвращает количество символов в строке
//======================================================
int GetColumn(void) {

	// Считываем содержимое переменной BIOS, расположенной по
	// адресу 0000:044Ah. В ней записано количество символов
	// в строке для текущего режима
	return(*(int _far *)(FP_MAKE(0x40,0x4a)));
}

//======================================================
// Функция устанавливает режим работы видеоадаптера, заданный
// параметром vmode
//======================================================
void SetVideoMode( unsigned char vmode ) {

	union  REGS    inregs, outregs;

	// Устанавливаем режим vmode
	inregs.h.ah = 0x0;
	inregs.h.al = vmode;
	int86( 0x10, &inregs, &outregs );
}

//======================================================
// Функция управляет назначением атрибутов символов.
//  mode = 0 атрибут управляет интенсивностью цвета символов
//  mode = 1 атрибут управляет миганием символов
//======================================================
void SetBlinkIntensity( unsigned char mode ) {

	union  REGS    inregs, outregs;

	inregs.h.ah = 0x10;
	inregs.h.al = 0x3;
	inregs.h.bl = mode;
	int86( 0x10, &inregs, &outregs );
}

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

	printf(	"\nCopyright (C)Frolov G.V.,1995. E-mail:"
				"frolov@glas.apc.org\n"
			"\nФормат вызова: TEXTATTR <режим> <интенсивность>"
			"\n   <режим>: любые текстовые режимы"
			"\n   <интенсивность>: 0 - интенсивность цвета, "
			"1 - мигание символа" );
}

Исходный текст включаемого файла SYSP.H, который используется в примере TEXTATTR.C, а также в других примерах книги, представлен в листинге 3.2. Файл SYSP.H содержит определение макрокоманды FP_MAKE, служащей для получения дальнего указателя из сегмента и смещения.

Листинг 3.2. Файл SYSP.H


// Макрокоманда FP_MAKE составляет дальний указатель
// из сегмента и смещения
#define FP_MAKE(seg,off) ((void far *)			\
	((((unsigned long) (unsigned)(seg)) << 16L) |	\
	((unsigned long) (unsigned) (off))))

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

Листинг 3.2. Файл SYSGRAPH.H


#pragma pack(1)

// Структура для определения символа и его атрибута
typedef struct _VIDEOBUF_ {
	unsigned char chr;
	unsigned char attr;
} VIDEOBUF;

// Структура для доступа к переменным видеофункций BIOS
typedef struct _BIOS_VAR_ {
	unsigned char  bEquipFlags;
	unsigned char  bReserv1[0x38];
	unsigned char  bVideoMode;
	unsigned       wColumns;
	unsigned       wPageLength;
	unsigned       wVidStart;
	unsigned       w8CursorPos[8];
	unsigned       wCursorShape;
	unsigned char  bActivePage;
	unsigned       wAddrCRT;
	unsigned char  bRegMode;
	unsigned char  bRegPalette;
	unsigned char  bReserv2[0x1D];
	unsigned char  bRows;
	unsigned       wCharHigh;
	unsigned char  bInfo;
	unsigned char  bInfoTwo;
	unsigned char  bReserv3[0x1F];
	void far       dwSavePtr;
} BIOS_VAR;

// Структура для заполнения таблицы цветов (таблицы ЦАП)
typedef struct _RGB_ {
	unsigned char red;
	unsigned char green;
	unsigned char blue;
} RGB;

#pragma pack()

Видеопамять в графических режимах

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

Ниже рассмотрена структура видеопамяти отдельно для каждого графического режима.

Режимы 4 и 5

Это режимы низкого разрешения - 320х200 пикселов. Используются 4 цвета. Режимы поддерживаются видеоадаптерами CGA, EGA, VGA и SVGA. У адаптеров EGA, VGA и SVGA видеоданные расположены в нулевом цветовом слое. Остальные три слоя не используются.

Для совместимости с видеоадаптером CGA, отображение видеопамяти на экран не является непрерывным. Первая половина видеопамяти (начальный адрес B800:0000h) содержит данные обо всех нечетных линиях экрана, а вторая половина (начальный адрес B800:2000h) - относительно всех четных линий. Каждому пикселу изображения соответствуют два бита видеопамяти. За верхний левый пиксел экрана отвечают биты D7 и D6 нулевого байта видеопамяти. На рисунке 3.7 изображено соответствие видеопамяти пикселам экрана.

Рисунок 3.7 Структура видеопамяти для режимов 4 и 5

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

Следующие формулы позволяют определить смещение байта от начала станицы видеопамяти и номера битов в нем, управляющие пикселом с координатами (x,y):


Если y четное число, то смещение байта = 50h*(y/2)+(x/4)
Если y нечетное число, то смещение байта = 2000h+50h*((y-1)/2)+(x/4)

Номер первого бита = 7-mod(x/4)*2

В режимах 4 и 5 доступны два набора цветов - стандартный и альтернативный. Для выбора набора цветов можно воспользоваться функцией 0Bh прерывания INT 10h. Ниже представлена таблица соответствия значений битов, определяющих пиксел, его цвету:

Значение битов пиксела Стандартный цвет Альтернативный цвет
00 Черный Черный
01 Светло-синий Зеленый
10 Малиновый Красный
11 Ярко-белый Коричневый

Режим 6

Режим 6 (640х200) является режимом наибольшего разрешения для видеоадаптера CGA. В этом режиме видеоадаптеры EGA, VGA и SVGA используют для хранения информации только нулевой слой памяти.

На рисунке 3.8 представлено соответствие видеопамяти и пикселов экрана. Как и в режимах 4 и 5, первая половина видеопамяти содержит данные обо всех нечетных линиях экрана, а вторая половина - обо всех четных линиях.

В режиме 6 на один пиксел отводится один бит видеопамяти. Таким образом, каждый байт видеопамяти управляет восьмью пикселами. Если значение бита видеопамяти, отвечающего за данный пиксел, равно нулю, то пиксел имеет черный цвет, если единице - белый. За верхний левый пиксел экрана отвечает бит D7 в нулевом байте видеопамяти, то есть самый старший его бит.

Рисунок 3.8 Структура видеопамяти в режиме 6

При непосредственном доступе к видеопамяти вы можете воспользоваться следующими формулами:


Если y четное число, то смещение байта = 50h*(y/2)+(x/8)
Если y нечетное число, то смещение байта = 2000h+50h*((y-1)/2)+(x/8)

Номер бита = 7-mod(x/8)

Эти формулы позволяют определить для пиксела, имеющего координаты (x,y), смещение от начала станицы видеопамяти байта и номер бита в нем, управляющего данным пикселом.

Режимы 0Dh и 0Eh

Разрешающая способность в режиме 0Dh составляет 320 пикселов по горизонтали и 200 пикселов по вертикали, а в режиме 0Eh соответственно 640 и 200 пикселов.

Режимы 0Dh и 0Eh поддерживают только видеоадаптеры EGA и VGA. На рисунке 3.9 представлена структура видеопамяти для этого режима.

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

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

Рисунок 3.9 Структура видеопамяти в режимах 0Dh и 0Eh

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


Смещение байта = 50h*y+x/8

Номер бита = 7-mod(x/8)

Запись в каждый из четырех слоев видеопамяти можно разрешить или запретить при помощи регистра разрешения записи цветового слоя. Смотри раздел "Регистры видеоадаптеров EGA, VGA и SVGA".

Режим 0Fh

Графический монохромный режим с разрешением 640х350 пикселов. Данный режим поддерживают только видеоадаптеры EGA, VGA и SVGA.

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

На рисунке 3.10 представлена структура видеопамяти для режима 0Fh.

Рисунок 3.10 Структура видеопамяти режима 0Fh

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


Смещение байта = 50h*y+x/8

Номер бита = 7-mod(x/8)

Режим 10h

Графический цветной режим с разрешением 640х350 пикселов. Данный режим поддерживают только видеоадаптеры EGA, VGA и SVGA.

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

На рисунке 3.11 представлена структура видеопамяти для режима 10h.

Рисунок 3.11 Структура видеопамяти режима 10h

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


Смещение байта = 50h*y+x/8

Номер бита = 7-mod(x/8)

Режим 11h

Графический цветной режим с разрешением 640х480 пикселов. Данный режим поддерживают только видеоадаптеры VGA и SVGA.

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

На рисунке 3.12 представлена структура видеопамяти для режима 11h.

Рисунок 3.12 Структура видеопамяти режима 11h

При непосредственном доступе к видеопамяти вы можете воспользоваться следующими формулами:


Смещение байта = 50h*y+x/8

Номер бита = 7-mod(x/8)

Формулы позволяют определить для пиксела, имеющего координаты (x,y), смещение от начала станицы видеопамяти байта и номер бита в нем, управляющего данным пикселом.

Режим 12h

Режим 12h похож на режим 10h, за исключением того, что он имеет большую разрешающую способность - 640х480 пикселов. В видеопамяти задействованы все четыре цветовых слоя. Структура видеопамяти показана на рисунке 3.13.

Рисунок 3.13 Структура видеопамяти режима 12h

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

Режим 13h

Этот режим, как и режим 12h, поддерживается только видеоадаптерами VGA и SVGA. Он обеспечивает отображение 256 различных цветов при разрешающей способности 320х200 пикселов.

Структура видеопамяти приведена на рисунке 3.14. Как видно из рисунка, в этом режиме видеопамять организована линейно. Каждый пиксел определяется одним байтом.

Рисунок 3.14 Структура видеопамяти в режиме 13h

Следующая формула позволяет определить смещение от начала видеопамяти байта, управляющего пикселом с координатами (x,y):


Смещение байта = 140h*y+x

Графический контроллер

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Контроллер атрибутов

Контроллер атрибутов в графических и текстовых режимах работы видеоадаптера управляет цветом элементов изображения. Значениям цветовых атрибутов ставится в соответствие определенный цвет. Для этого используется таблица цветовой палитры (Color Lock-up Table). Таблица цветовой палитры ставит в соответствие четырем битам, взятым из видеопамяти, 6 битов цветовой информации. Изменяя данные, записанные BIOS в таблицу цветовой палитры, можно менять используемую палитру цветов.

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

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

На рисунках 3.16 и 3.17 показана работа контроллера атрибутов в графическом и текстовом режимах.

Рисунок 3.16 Контроллер атрибутов в текстовых режимах

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

Аналогично битам, определяющим цвет фона символа, четыре младших бита задают цвет самого символа.

Рисунок 3.17 Контроллер атрибутов в графических режимах

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

Контроллер атрибутов подробно описан в разделе "Регистры видеоадаптеров EGA и VGA".

Контроллер ЭЛТ

Контроллер ЭЛТ выполняет следующие функции:

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

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

Синхронизатор

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

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

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

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