Видеоадаптер CGA построен на основе мкросхемы Motorolla 6845 или ее аналога. Эта микросхема содержит контроллер электронно-лучевой трубки (ЭЛТ). Контроллер ЭЛТ Motorolla 6845 устанавливает формат экрана, управляет курсором и световым пером, а также управляет цветовыми характеристиками изображения.
Адаптер CGA имеет 16К байт видеопамяти. Видеопамять периодически отображается на экране дисплея, формируя изображение. Процессор может непосредственно обращаться к видеопамяти, которая расположена в адресном пространстве процессора начиная с адреса B800:0000.
В некоторых режимах видеоадаптера видеопамять разделена на несколько страниц. При этом одна из них является активной и отображается на экране. При помощи функций BIOS или непосредственного программирования регистров видеоадаптера можно переключать активные страницы видеопамяти. Вывод информации можно производить как в активную, так и в неактивные страницы памяти. Таким образом, можно заранее подготовить несколько страниц памяти (несколько экранов), а затем быстро сменять их на экране дисплея.
В зависимости от режима работы адаптера, видеопамять имеет различную структуру. Ниже рассмотрены текстовые и графические режимы видеоадаптера CGA.
Видеоадаптеры EGA и VGA можно условно разделить на шесть логических блоков:
Видеопамять. В видеопамяти размещаются данные, отображаемые адаптером на экране дисплея. Для видеоадаптеров EGA и VGA видеопамять, как правило, имеет объем 256К байт. На некоторых моделях Super VGA и XGA объем видеопамяти может быть увеличен до 1М байт. Видеопамять находится в адресном пространстве процессора и программы могут непосредственно производить с ней обмен данными. Физически видеопамять разделена на четыре банка или цветовых слоя, разделяющих единое адресное пространство.
Графический контроллер. Посредством его происходит обмен данными между центральным процессором компьютера и видеопамятью. Аппаратура графического контроллера позволяет производить над данными, поступающими в видеопамять, и над данными, расположенными в регистрах-защелках (регистры-защелки описаны ниже) простейшие логические опрерации (И, ИЛИ, ИСКЛЮЧАЮЩЕЕ ИЛИ, циклический сдвиг).
Последовательный преобразватель. Выбирает из видеопамяти один или несколько байт, преобразует их в последовательный поток битов и затем передает контроллеру атрибутов.
Контроллер ЭЛТ. Генерирует временные синхросигналы, управляющие ЭЛТ.
Контроллер атрибутов. Преобразует информацию о цветах из формата, в котором она хранится в видеопамяти, в формат, необходимый для ЭЛТ. Преобразование цветов осуществляется в соответствии с таблицей цветовой палитры (Color Look-up Table). Модифицируя таблицу цветовой палитры, можно выбирать 16 цветов, поддерживаемых видеоадаптером EGA из 64 цветов, которые может отображать цветной улучшенный дисплей.
Синхронизатор. Управляет всеми временными параметрами видеоадаптера. Синхронизатор также управляет доступом процессора к цветовым слоям видеоадаптера.
На рисунке 6.1 представлена блок схема видеоадаптеров EGA и VGA, отображающая связи между их основными логическими блоками.
Рисунок 6.1 Блок схема видеоадаптеров EGA/VGA.
Каждый символ, отображаемый на экране в текстовом режиме, определяется не только своим кодом ASCII, но и байтом атрибутов. Атрибуты задют цвет символа, цвет фона а также некоторые другие параметры.
На рисунке 6.7 представлен формат байта атрибутов. Биты D0-D2 задают цвет символа, D4-D6 определяют цвет фона на котором отображается символ. Таким образом можно независимо задавать до 23 = 8 различных цветов для текста и фона.
Бит D3 играет различную роль в зависимости от числа активных таблиц знакогенератора. Если активной является одна таблица, то D3 используется для управления интенсивностью цвета символа, что позволяет увеличить количество воспроизводимых цветов от 8 до 16.
Если одновременно определены две таблицы знакогенератора, то D3 также задает таблицу знакогенератора, которая будет использована при отображении данного символа.
Бит D7 также выполняет две различные функции в зависимости от состояния регистра режима контроллера атрибутов. Данный бит управляет либо интенсивностью цвета фона, увеличивая число отображаемых цветов до 16, либо разрешением гашения символа, в результате чего символ на экране дисплея будет мигать. По умолчанию данный бит управляет разрешением гашения символа (миганием).
D2-D0 | Цвет символа. |
D3 | Интенсивность символа и выбор таблицы знакогенератора. |
D6-D4 | Цвет фона символа. |
D7 | Мигание символа или интенсивность фона символа. |
Рисунок 6.7 Байт атрибутов символа.
В таблице 6.2 приведено соответствие цветов символов и фона значениям поля цвета символа байта атрибутов:
Код цвета в Стандартный цвет Цвет с повышенной байте атрибутов интенсивностью
000 черный серый 001 синий светло-синий 010 зеленый светло-зеленый 011 морской волны голубой 100 красный светло-красный 101 фиолетовый малиновый 110 коричневый желтый 111 белый ярко-белый
Таблица 6.2 Стандартные цветовые атрибуты.
Назначение полей байта атрибутов в монохромном режиме сходно с их назначениями в цветном режиме.
На рисунке 6.7 представлен формат байта атрибутов. Биты D0-D2 управляют типом символа, который может быть обычным, мигающим или подчеркнутым; D4-D6 могут выбрать обратный (инвертированный) символ.
Бит D3 играет различную роль в зависимости от того, сколько таблиц знакогенератора одновременно являются активными. Если активной является одна таблица, то D3 используется для управлния интенсивностью символа.
Если одновременно определены две таблицы знакогенератора, то D3 также задает таблицу знакогенератора, которая будет использована при отображении данного символа.
Бит D7 также выполняет две различные функции в зависимости от состояния регистра режима контроллера атрибутов. Данный бит управляет либо интенсивностью фона, либо миганием символа. По умолчанию данный бит управляет миганием символа.
В таблице 6.3 представлны все возможные значения для атрибутов символов в текством монохромном режиме. В случае использования другх значений атрибутов могут возникнуть проблемы совместимости для различных видеоадаптеров (MDA, CGA, EGA, VGA, Hercules).
Атрибут | Что означает |
00000000b (00h) | черный символ на черном фоне |
00000001b (01h) | подчеркнутый символ |
00000111b (07h) | обычный символ (светлый символ на черном фоне) |
00001001b (09h) | подчеркнутый символ с повышенной интенсивностью |
00001111b (0Fh) | символ с повышенной интенсивностью |
01110000b (70h) | обратное отображение символа (черный символ на светлом фоне) |
10000001b (81h) | подчеркнутый мигающий символ |
10000111b (87h) | мигающий символ |
10001001b (89h) | подчеркнутый мигающий символ с повышенной интенсивностью |
11110000b (0F0h) | мигающее обратное отображение символа |
Таблица 6.3 Стандартные монохромные атрибуты.
Регистр определяет общее число линий горизонтальной развертки в кадре вертикальной развертки, включая гашение вертикального хода луча и обратный вертикальный ход луча.
Для видеоадаптера EGA, регистр VTR содержит девять битов. Девятый бит находится в дополнительном регистре (OVR). Регистр VTR видеоадаптера VGA содержит десять битов. Десятый бит, также как и девятый, расположен в дополнительном регистре (OVR).
При помощи этой функции можно определить конфигурацию видеосистемы:
На входе: AH = 1Ah;
AL = 00h - чтение конфигурации видеосистемы.
На выходе: AL = 1Ah;
BL = тип первичного видеоадаптера:
BH = тип дополнительного видеоадаптера:
0 - дисплей отсутствует,
1 - MDA,
2 - CGA,
3 - EGA с улучшенным цветным дисплеем,
4 - EGA с цветным дисплеем,
5 - EGA с монохромным аналоговым дисплеем,
6 - PGC (профессиональный графический контроллер);
7 - VGA с монохромным аналоговым дисплеем,
8 - VGA с цветным аналоговым дисплеем,
0Ah - MCGA с цветным цифровым дисплеем.
0Bh - MCGA с монохромным аналоговым дисплеем,
0Ch - MCGA с цветным аналоговым дисплеем.
Функция производит чтение 18-битовых значений из нескольких последовательно расположенных регистров таблицы цветов:
На входе: AH = 10h;
AL = 17h - чтение нескольких регистров таблицы цветов;
BL = номер первого регистра таблицы цветов (0 -255);
CX = число считываемых регистров (1-256);
ES:DX - адрес таблицы цветов;
На выходе: Данные в таблице по адресу ES:DX.
Таблица цветов содержит по три байта на один регистр таблицы цветов. В каждом байте значащимии являются только младшие 6 бит.
Функция позволяет определить цвет любого пиксела экрана по его координатам. Функция используется только в графических режимах работы видеоадаптеров.
На входе: AH = 0Dh - определение цвета пиксела;
BH = номер страницы (для CGA не используется);
CX = координата X;
DX = координата Y;
На выходе: AL = номер цвета пиксела.
Приведем фрагмент программы, который определяет номер цвета пиксела, имеющего координаты x_pos и y_pos:
mov ah,0Dh mov cx,x_pos mov dx,y_pos int 10h
; сохраняем полученную величину
mov color_number
Функция поддерживается только видеоадаптером VGA. Позволяет прочитать содержимое регистра цвета рамки:
На входе: AH = 10h;
AL = 08h - чтение регистра цвета рамки.
На выходе: BH = содержимое регистра цвета рамки.
Функция поддерживается только видеоадаптером VGA. Она позволяет прочитать содержимое любого регистра палитры:
На входе: AH = 10h;
AL = 07h - чтение регистра палитры;
BL = номер читаемого регистра палитры (0-15).
На выходе: BH = содержимое регистра палитры.
... mov ah,10h mov al,7h mov bl,num_reg int 10h
mov reg_value,bh ...
Функция поддерживается только для видеоадаптеров VGA. Она выполняет чтение одного из регистров таблицы цветов:
На входе: AH = 10h;
AL = 15h - чтение регистра таблицы цветов;
BL = номер читаемого регистра (0-255).
На выходе: DH = интенсивность красного цвета (6 бит);
CH = интенсивность зеленого цвета (6 бит);
CL = интенсивность синего цвета (6 бит);
Следующий пример позволяет считать значение регистра таблицы цветов с номером num_color_reg:
mov ah,10h mov al,15h mov bx,num_color_reg int 10h mov red_data,dh mov green_data,ch mov blue_data,cl
Данная функция позволяет прочитать символ и его атрибуты из позиции экрана, определенной текущим положением курсора. Чтение можно производить как из активной, так и из неактивных страниц памяти:
На входе: AH = 08h - чтение символа и его атрибутов;
BH = номер страницы видеопамяти.
На выходе: AL = ASCII-код символа;
AH = байт атрибутов символа.
Следующий пирмер считывает символ и его атрибут из текущей позиции курсора на странице page:
... mov ah,8 ; читаем символ и его атрибуты mov bh,page ; выбираем страницу видеопамяти page
int 10h ; считываем символ и его атрибут
mov char,al ; сохраняем полученный ASCII-код символа mov attr,ah ; и его атрибут ...
Для видеоадаптера VGA данная функция позволяет прочитать значения всех регистров палитры и регистра цвета рамки. Для чтения регистров надо зарезервировать участок памяти (17 байт). После вызова функции байты 0 - 15 будут содержать значения соответствующих регистров палитры, а байт 16 - значение регистра цвета рамки.
На входе: AH = 10h;
AL = 9 - чтение всех регистров палитры;
ES:DX - указатель на 17-байтовую таблицу.
На выходе: По адресу ES:DX содержится таблица, заполненная значениями из регистров палитры.
Приведем фрагмент программы, который считывает значения всех регистров палитры и регистра цвета рамки в буфер памяти buffer:
; определяем адрес буфера для записи значений регистров ; палитры и регистра цвета рамки
mov ax,SEG buffer mov es,ax mov dx,OFFSET buffer
; считываем значения всех регистров палитры и регистра ; цвета рамки
mov ah,10h mov al,9 int 10h
Функция содержит две подфункции для чтения и записи текущей конфигурации видеосистемы компьютера.
Функция 1Ah реализована только на VGA. Если после выполнения функции регистр AL не содержит числа 1Ah, то это значит, что функция не поддерживается данным видеоадаптером и для определения конфигурации надо использовать другие способы.
Цветной дисплей фирмы IBM (CD - Color Display) используется совместно с цветным графическим адаптером (CGA) и обеспечивает четыре цвета для графики и восемь цветов для текста. Сам цветной дисплей имеет возможность отображать шестнадцать различных цветов. Разрешение цветного дисплея меньше, чем у монохромного - 640х200 и размер символов составляет 8 пикселов (пиксел - минимальный элемент изображения) по высоте и 8 пикселов по ширине. В результате заметно, что символы состоят из отдельных пикселов. С появлением улучшенного цветного дисплея, имеющего большую разрешающую способность, этот недостаток был устранен.
Цветной дисплей имеет частоту смены кадров, равную 60Гц.
D0 Голубой.
D1 Зеленый.
D2 Краснй.
D3 Не используется.
D4 Интенсивность.
D7-D5 Не используются.
Для видеоадаптера VGA фирмой IBM был разработан аналоговый RGB дисплей с высоким разрешением, а также монохромный аналоговый дисплей с высоким разрешением. На монохромном дисплее различные цвета изображаются различными градациями серого цвета. Эти два дисплея (монохромный и цветной) являются взаимозаменяемыми - приложения, написанные для одного из дисплеев, могут работать с другим дисплеем.
D0 P0
D1 P1
D2 P2
D3 P3
D4 P4
D5 P5
D7-D6 Не используются.
Данный регистр используется адаптерами CGA и Hercules. Регистр задает длину отображаемого участка горизонтальной развертки. Величина регистра равна числу символов в строке экрана.
Регистр задает длину отображаемого участка горизонтальной развертки. Величина, записанная в регистр на единицу меньше, чем число символов в строке экрана.
При установке режима работы видеоадаптера, BIOS загружает в регистр HDER следующие значения:
Режим | 0,1,4,5,D | 2,3,6,7,E,F,10 |
Содержимое регистра | 27h | 4Fh |
Регистр CGA, задающий число отображаемых текстовых строк.
В этой главе описаны остальные функции BIOS, которые реализованы только на видеоадаптерах EGA и VGA. Так же, как и в предыдущей главе, использование каждой группы функций иллюстрируется соответствующими примерами программ.
Многие регистры контроллера ЭЛТ, видеоадаптера EGA, имеют по девять, а для VGA и по десять битов. Дополнительный регистр содержит биты, которые не помещаются в восьмиразрядную сетку основных регистров.
D0 Регистр числа горизонтальных линий растра (VTR). Бит 8.
D1 Регистр начала гашения вертикальной развертки (VDER). Бит 8.
D2 Регистр начала обратного вертикального хода луча (VRSR). Бит 8.
D3 Регистр начала импульса гашения вертикальной развертки (SVBR). Бит 8.
D4 Регистр сравнения линий (LCR). Бит 8.
D5 Регистр количества горизонтальных линий в растре (VTR). Бит 9.
D6 Регистр начала гашения вертикальной развертки (VDER) Бит 9.
D7 Регистр начала обратного вертикального хода луча (VRSR). Бит 9.
Эти функции помещают один символ в текущую позицию выходного потока. Прототипы функциий представлены ниже:
int putc( int ch, FILE *stream );
int putchar( int ch );
Функция putc() отличается от putchar() наличием второго аргумента, который определяет выходной поток, в который помещается символ. Она может использоваться и для записи символов в открытый файл и для записи в стандартные потоки ввода-вывода. В частности, если второй аргумент функции равен константе stdout, то она эквивалентна функции putchar() и выводит символ в стандартный выходной поток. Этот поток может идти на экран дисплея или в файл, если используется свойство переназначения потока. Фактически функция putchar() является макроопределением:
#define putchar(_c) putc((_c),stdout)
Первые параметры обеих функций совпадают по смыслу и задают ASCII-код выводимого символа (не смотря на то, что переменная ch целого типа, используется только ее младший байт). При этом функции обрабатывают управляющие символы. Список управляющих символов приведен в таблице 13.1:
Символ Код ASCII Значение
\a 07h звуковой сигнал
\b 08h перемещение назад
\f 0Ch переход к новой странице
\n 0Ah новая строка
\r 0Dh возврат каретки
\t 09h горизонтальная табуляция
\v 0Bh вертикальная табуляция
\' 27h символ кавычки
\" 22h двойная кавычка
\\ 5Ch обратный слеш
\% 25h знак процента
Таблица 13.1 Управляющие символы.
Функции возвращают ASCII-код выведенного символа, а в случае ошибки возвращают константу EOF. Чтобы конкретизировать ошибку можно воспользоваться функцией ferror().
// использование функци putchar()
#include <stdio.h>
void main(void) {
char *ptr, out_str[] = "\aputchar\nputc\a";
for(ptr = out_str; *ptr; putchar(*(ptr++)) ); }
Включаемый файл stdio.h содержит спецификации функций putchar() и putc(). Следовательно, этот файл необходимо включать во все программы, использующие данные функции.
Функции применяются, для управления видеоадаптерами в режимах с несколькими страницами видеопамяти. Они обеспечивают возможность подготовки изображения на неактивной странице видеопамяти, а затем быстрого его вывода на экран.
Функция _setactivepage() направляет вывод информаци в определенную страницу видеопамяти, а функция _setvisualpage() задает страницу, которая отображается в данный момент на экране. Функции управления страницами видеопамяти могут использоваться совместно с функциями _gettextcursor(), _settextcursor(), _settextposition(), _gettextposition(), _outtext(), _gettextcolor(), _settextcolor(), _settextwindow().
Функция управления страницами видеопамяти имеет следующий прототип:
short _setactivepage( short page );
Параметр функции задает активную страницу, в которую будет направлен весь последующий вывод.
Если функция выполнилась успешно, то она возвращает номер предыдущей активной страницы. При возникновении ошибки возвращаемая величина равна -1. Ошибка может произойти в случае задания номера страницы видеопамяти, не поддерживаемого адаптером в данном режиме.
Приведем прототип функции:
short _setvisualpage( short page );
Параметр функции задает номер страницы, отображаемой на экране дисплея. Функция возвращает номер предыдущей отображаемой страницы. При возникновении ошибки возвращаемая величина равна -1. Ошибка может произойти, например, в случае задания номера страницы видеопамяти, не поддержиеваемой адаптером. Смена отображаемой страницы в этом случае не происходит.
short _getactivepage( void );
Функция _getactivepage() возвращает номер текущей активной страницы видеопамяти.
Следующая функция, _getvisualpage(), возвращает номер страницы видеопамяти, отображаемой на экране дисплея в данный момент. Ее прототип:
short _getvisualpage( void );
В приведенном ниже примере определяется число страниц видеопамяти, в каждую страницу записывается ее номер и затем по очереди отображаются все страницы экрана.
// Пример использования функций _setactivepage(), _setvisualpage(), // _getactivepage() и _getvisualpage().
Глава знакомит читателей с основными функциями стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0, предназначенными для управления экраном дисплея в текстовом режиме. Глава содержит описание функций, управляющих формой и координатами курсора, текущим режимом работы видеоадаптера и переключением страниц видеопамяти, отображением текста и изменением цвета символов и цвета фона.
Функция рисует дугу эллипса.
Прототип функции _arc() имеет следующий вид:
short _arc( short x_left, short y_top, short x_right, short y_bottom, short x_begin, short y_begin, short x_end, short y_end );
Эллипс задается прямоугольником, в который он вписан. Прямоугольник определяетя координатами любых двух противоположных углов (x_left, y_top) и (x_right, y_bottom). Дуга строится от точки пересечения эллипса с прямой, соединяющей центр эллипса с точкой (x_begin, y_begin) до точки пересечения эллипса прямой, соединяющей его центр с точкой (x_end, y_end) против часовой стрелки (см. рисунок 16.2).
ARC.PCX;6";3.439";PCX
Рисунок 16.2 Построение дуги эллипса функцией _arc().
Функция возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Функция выполняет очистку отдельной области или всего экрана дисплея. Очищаемая область закрашивается текущим цветом фона. Функция имеет следующий прототип:
void _clearscreen( short area );
Параметр area может быть равен одной из следующих констант, определенных в файле graph.h:
Константа Производится очистка
_GCLEARSCREEN всего экрана _GVIEWPORT текукщей логической системы координат _GWINDOW текущего текстового окна
Функция обеспечивает вывод на экран дисплея строк, отдельных символов и чисел в различных форматах непосредственно на консоль. При этом для вывода отдельных символов использется функция putch().
Приведем прототип функции cprintf():
int cprintf( char *format [,argument]... );
Ее параметры соответствуют параметрам функции printf(), описанной выше. Единственное ее отличие состоит в том, что она не преобразует символ перевода строки в пару символов - возврат каретки, перевод строки.
Функция cprintf() возвращает число напечатанных ею символов или отрицательную величину в случае ошибки.
Функция производит запись строки символов, оканчивающихся нулем, на консоль. Отметим, что в отличие от функции puts() курсор не переводится на новую строку.
Приведем прототип функции cputs():
int cputs( char *string );
Единственный параметр функции содержит указатель на отображаемую строку. При успешном выполнении функция возвращает ноль. Если произошла ошибка, то возвращается ненулевая величина.
При использовании функции cputs() необходимо включить директивой include файл conio.h, содержащий спецификацию этой функции.
Функция позволяет в текстовых режимах видеоадаптеров погасить курсор. Приведем ее прототип:
short _displaycursor( short toggle );
Параметр toggle равен _GCURSOROFF, если курсор необходимо погасить и _GCURSORON, если его надо высветить.
Функция возвращает предыдушее значение toggle, тоесть определяет отображался ли курсор на экране до вызова функции. Описание функции находится в файле graph.h.
Пример использования функции:
#include <stdio.h> #include <graph.h>
void main(void) { // очищаем экран дисплея
_clearscreen( _GCLEARSCREEN );
// гасим курсор
_displaycursor( _GCURSOROFF ); printf("\nКурсор погашен"); getch();
// восстанавливаем курсор
_displaycursor( _GCURSORON ); printf("\nКурсор включен"); getch(); }
Функция рисует эллипс. Приведем прототип этой функции:
short _ellipse( short fill, short x_left, short y_top, short x_right, short y_bottom );
Эллипс задается прямоугольником, в который он вписан. Прямоугольник определяется координатами любых двух противоположных углов (x_left,y_top) и (x_right,y_bottom). Работа функции иллюстрируется на рисунке 16.1.
ELLIPSE.PCX;6";2.559";PCX
Рисунок 16.1 Построение эллипса функцией _ellipse().
Граница эллипса изображается текущим цветом. Если аргумент fill функции равен _GFILLINTERIOR, то эллипс закрашивается, а если _GBORDER - то не закрашивается. Для изменения текущего цвета используют функцию _setcolor().
Если аргументы функции определяют вертикальную или горизонтальную линии или же точку, то эллипс не рисуется.
Функция возвращает не нулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Функция позволяет узнать текущий цвет фона символов (см. биты D4-D6 байта атрибутов):
long _getbkcolor( void );
В текстовом режиме функция возвращает индекс цвета, а в графическом - универсальное значение цвета:
Индекс Константа Цвет (универсальное значение)
0 _BLACK черный 1 _BLUE голубой 2 _GREEN зеленый 3 _CYAN синий 4 _RED красный 5 _MAGENTA малиновый 6 _BROWN коричневый 7 _WHITE белый 8 _GRAY серый 9 _LIGHTBLUE светло-голубой 10 _LIGHTGREEN светло-зеленый 11 _LIGHTCYAN светло-синий 12 _LIGHTRED светло-красный 13 _LIGHTMAGENTA светло-малиновый 14 _YELLOW желтый 15 _BRIGHTWHITE интенсивно-белый
Таблица 15.1 Значения цветов.
Функция имеет следующий прототип:
_getimage( short x_first, short y_first, short x_second, short y_second, char _huge *image );
Она записывает содержимое прямоугольной области экрана, определенной точками (x_first, y_first) и (x_second, y_second) в буфер, на который указывает параметр image. Необходимый размер буфера можно узнать при помощи функции _imagesize().
С помощью этой функции можно узнать текущй цвет символов:
short _gettextcolor( void );
Функция возвращает индекс цвета символов (см. таблицу 15.1), выводимых функцией _outtext(). Для изменения цвета символов используйте функцию _settextcolor().
Функция позволяет определить форму курсора, тоесть положение его верхней и нижней границы:
short _gettextcursor( void );
Старший байт возвращаемого функцией значения определяет верхнюю, а младший - нижнюю границы курсора. Функция возвращает величину -1, если призошла ошибка, например, если функция вызвана в графическом режиме (графический режим работы видеоадаптеров курсор не использует).
Определить положение курсора на экране можно при помощи прерывания INT 10h, функции 03h, или, что более удобно, вызвав функцию _gettextposition():
struct rccoord _gettextposition( void );
Функция возвращает в структуре rccoord текущие координаты курсора. Заметим, что начало координат находится в левом верхнем углу экрана, имеющем координаты (1,1), ось X направлена вправо, а ось Y вниз.
Структура rccoord определена во включаемом файле graph.h следующим образом:
struct rccoord {
short row; // Y координата курсора (строка) short col; // X координата курсора (столбец) };
Функция возвращает размер буфера (в байтах), необходимого для сохранения прямоугольного участка экрана дисплея, задаваемого двумя диагонально противоположными точками - (x_first, y_first) и (x_second, y_second).
long _imagesize( short x_first, short y_first, short x_second, short y_second );
Функция определяет размер буфера по следующим формулам:
width = abs(x_first-x_second) + 1; height = abs(y_first-y_second) + 1; size=((long)((width * bits_per_pixel + 7) / 8)*(long)height) + 4;
Величина bits_per_pixel, содержит число битов видеопамяти определяющих один пиксел. Этот параметр режима видеоадаптера можно получить через функцию _getvidioconfig().
После вычислений переменная size содержит необходимый размер буфера в байтах.
Теперь приведем программу, иллюстрирующую использование функций _imagesize(), _getimage() и _putimage(). Она переводит видеоадаптер в графический режим и отображает несколько строк текста. Затем она при помощи функции _getimage() записывает участок экрана в буфер памяти. Далее программа отображает этот участок в нескольких соседних местах экрана, создавая иллюзию перемещения изображения.
#include <conio.h> #include <stdlib.h> #include <malloc.h> #include <graph.h>
void main(void) { char _huge *buffer; char text[8]; long imsize; short i, x = 0, width = 60, height = 27;
// выбираем режим видеоадаптера с наибольшим разрешением
if(!_setvideomode(_MAXRESMODE)) exit(1);
sprintf(text, "текстовая строка");
// отображаем на экране несколько строк text
for(i = 1; i < 8; i++) { _settextposition(i, i); _outtext(text); }
// определяем размер буфера для пиктограммы высотой height // и шириой width
imsize = _imagesize(0, 0, width, height);
// резервируем буфер памяти для пиктограммы
buffer = halloc(imsize, 1); if(buffer == NULL) exit(1);
// запоминаем пиктограмму в буфере
_getimage(0, 0, width, height, buffer);
// перемещаем пиктограмму по экрану дисплея
while(x < 400)
// отображаем пиктограмму
_putimage(x++, 0, buffer, _GPSET);
getch(); free(buffer); }
Функция рисует на экране линию. Ее прототип приведен ниже:
short _lineto( short x_target, short y_target );
Линия начинается в текущей точке и заканчивается в точке, имеющей координаты (x_target, y_target). После отображения линии координаты текущей точки становяться равными (x_target, y_target). Для изменения координат текущей точки можно воспользоваться функцией _lineto().
Линия изображается в текущем цвете (функция _setcolor()) и текущем стиле (функция _setstyle()).
Как и все уже рассмотренные функции, функция _lineto() возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Функция изменяет положение текущей точки. Используется совместно с _lineto() для изображения линий. Прототип функции _moveto() имеет следующий вид:
struct xycoord _moveto( short x, short y );
Новые координаты текущей точки соответствуют параметрам функции (точка с координатами (x,y)).
Функция возвращает в структуре xycoord координаты предыдущей точки. Структура xycoord определена в файле graph.h следующим образом:
struct xycoord {
short xcoord ; // x координата точки short ycoord ; // y координата точки };
Функция выводит на экран строку символов в любом режиме работы видеоадаптера. Формат функции имеет следующий вид:
void _outtext( unsigned char _far *text );
Единственный параметр функции содержит указатель на выводимую строку, оканчивающуюся двоичным нулем. Строка начинает отображаться на экране с текущей позиции курсора. Символы изображаются цветом, задаваемым функцией _settextcolor().
Функция рисует сектор эллипса:
short _pie( short fill, short x_left, short y_top, short x_right, short y_bottom, short x_begin, short y_begin, short x_end, short y_end );
Эллипс задается прямоугольником, в который он вписан. Прямоугольник определяетя координатами любых двух противополжных углов (x_left, y_top) и (x_right, y_bottom). Дуга сектора строится от точки пересечения эллипса с прямой, соединяющей центр эллипса с точкой (x_begin, y_begin) до точки пересечения эллипса прямой, соединяющей его центр с точкой (x_end, y_end) против часовой стрелки (см. рисунок 16.3).
PIE.PCX;6";3.439";PCX
Рисунок16.3 Построение сектора эллипса при помоши функции _pie().
Граница эллипса изображается текущим цветом. Если поле fill равно _GFILLINTERIOR, то эллипс закрашивается, а если _GBORDER - то не закрашивается. Для изменения текущего цвета используют функцию _setcolor().
Функция возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Наиболее универсальной стандартной функцией, обеспечивающей запись в выходной поток stdout, является функция printf(). Она производит вывод на экран дисплея строк, отдельных символов и чисел в различных форматах.
Приведем прототип функции printf():
int printf( char *format [,argument]... );
Первый аргумент функции содержит указатель на управляющую строку, которая может состоять из:
непосредственно выводимых символов,
управляющих символов,
спецификаторов формата.
Непосредственно выводимые символы и управляющие символы помещаются в выходной поток без изменения.
Если управляющая строка содержит спецификаторы формата, то каждому спецификатору должен соответствовать один аргумент, следующий за управляющей строкой. Аргументы представляют собой переменные или константы, которые преобразуются согласно соответствующих им спецификаторов формата и затем также помещаются в выходной поток.
Различные спецификаторы формата перечислены в таблице 13.2:
Спецификатор формата Тип данных
%d, %i целое десятичное число
%s текстовая строка
%c один символ
%e, %E число с плавающей точкой в экспоненциальной форме
%f число с плавающей точкой в десятичной записи
%u целое десятичное число без знака
%o целое восьмеричное число без знака
%x, %X целое шестнадцатиричное число без знака
%g, %G либо %e, либо %f в зависимости от того, запись в каком формате короче
%p значение указателя
%n число символов
Таблица 13.2 Спецификаторы формата функции printf().
В более общем случае, в спецификаторе формата между символом '%' и символом, определяющим тип преобразования можно разместить флаги и префиксы типов:
% [флаг] [ширина] [.точность] [префикс типа] символ преобразования
Флаги приведены в таблице 13.3, а префиксы типов в таблице 13.4.
Поле [ширина] задает мимнимальную ширину поля, используемую при печати строки или числа. Если это число или строка не помещаются в поле целиком, то ширина поля увеличивается.
Поле [.точность] определяет для чисел количество отображаемых после запятой цифр, а для строк - максимальное число символов в строке.
Функция производит запись символа на консоль без буферизации. Прототип функции:
int putch( int ch );
Параметр функции - ch - содержит код ASCII выводмого символа. Заметим, что используется только младший байт параметра функции.
Функция putch() возвращет ASCII-код записанного символа или, в случае возникновения ошибки, константу EOF.
При использовании функции putch() необходимо включить в программу файл conio.h, который содержит ее спецификацию.
Функция имеет следующий прототип:
void _putimage( short x, short y, char _huge *image, short action );
Функция помещает пиктограмму, записанную в буфере image, на экран. При этом верхняя левая точка пиктограммы помещается в точке с координатами (x, y).
Параметр action определяет способ записи пиктограммы. В следующей таблице приведены возможные значения параметра action:
Констаната Смысл
_GAND записываемая пиктограмма накладывается на область экрана так, что результат получается как логическое "И" данных пиктограммы и экрана
_GOR, записываемая пиктограмма накладывается на область экрана так, что результат получается как логическое "ИЛИ" данных пиктограммы и экрана
_GXOR записываемая пиктограмма накладывается на область экрана так, что результат получается как логическое "ИСКЛЮЧАЮЩЕЕ ИЛИ" данных пиктограммы и экрана
_GPRESET копирует пиктограмму на экран, при этом цвет каждого пиксела инвертируется
_GPSET копирует пиктограмму на экран, при этом цвет каждого пиксела сохраняется
Таблица 16.2 Различные способы записи пиктограмм.
Функция puts() позволяет записать строку в стандартный выходной поток stdout. Строка должна оканчиваться нулем (символ '\0'). Этот символ не помещается в выходной поток. Вместо него записывается упрвляющий символ '\n', который переводит курсор в начало новой строки.
Функция имеет следующий прототип:
int puts( char *string );
Единственный параметр функции содержит указатель на отображаемую строку. При успешном выполнении функция возвращает ноль. Если же произошла ошибка, то возвращается ненулевая величина.
При использовании функции puts() необходимо включить директивой include файл stdio.h, содержащий спецификацию этой функции.
// использование функци puts
#include <stdio.h>
void main(void) { puts("Работает функция puts!"); }
Функция рисует прямоугольник. В зависимости от параметров функции прямоугольник может быть закрашенным или не закрашенным. Прототип функции имеет следующий вид:
short _rectangle( short fill, short x_left, short y_top, short x_right, short y_bottom );
Прямоугольник определяетя координатами любых двух противоположных углов (x_left,y_top) и (x_right,y_bottom).
Граница прямоугольника изображается текущим цветом с использованием текущего стиля. Если например fill равен _GFILLINTERIOR, то прямоугольник закрашивается, а если _GBORDER - то не закрашивается. Для изменения текущего цвета используют функцию _setcolor().
Функция возвращает ненулевую величину, если она выполнилась успешно и ноль, если произошла ошибка.
Следующая программа иллюстрирует использование функций _moveto(), _lineto() и __rectangle():
#include <conio.h> #include <stdlib.h> #include <stdio.h> #include <graph.h>
// макроопределение, ранжирующее величину, возвращаемую // генератором случайных чисел (rand) в интервале от 0 // до max
#define random(max) (rand() % (int)((max)+1))
void main(void) {
short x, y; short color; struct videoconfig vc;
// устанавливаем графический режим с максимальным числом цветов
if(!_setvideomode(_MAXCOLORMODE)) { puts("Видеоадаптер не поддерживает графический режим."); exit(1); }
// получаем информацию о конфигурации видеосистемы и об // установленном режиме работы видеоадаптера
_getvideoconfig(&vc);
while(!kbhit()) {
// устанавливаем произвольный допустимый цвет, который // используется при изображении графических объектов
_setcolor((short)random(vc.numcolors));
// выбираем произвольную точку экрана - (x,y) x = (short)random(vc.numxpixels), y = (short)random(vc.numypixels);
// рисуем закрашенный и незакрашенный прямоугольники
_rectangle(_GFILLINTERIOR, x + 30, y + 40, x, y); _rectangle(_GBORDER, x + 40, y + 30, x, y); }
// ожидаем нажатие на клавиатуру
getch();
// помещаем текущую точку в центр экрана
_moveto(vc.numxpixels/2, vc.numypixels/2);
while(!kbhit()) { _setcolor((short)random(vc.numcolors)); x = (short)random(vc.numxpixels), y = (short)random(vc.numypixels);
// рисуем линию из центра экрана в произвольную точку экрана _lineto(x, y); _moveto(vc.numxpixels/2, vc.numypixels/2); } getch();
// устанавливаем режим видеоадаптера, принятый по умолчанию
_setvideomode(_DEFAULTMODE); }
Функция изменяет цветовую палитру для режимов _MRES4COLOR и _MRESNOCOLOR. В этих режимах цветовая палитра содержит четыре цвета - цвет фона, выбираемый отдельно и три цвета, устанавливаемых функцией _selectpalette(). Функция имеет следующий прототип:
short _selectpalette( short palette_number );
Единственный параметр функции имеет различное значение в разных режимах видеоадаптера.
В режиме _MRES4COLOR параметр palette_number выбирает одну из четырех возможных цветовых палитр:
Номер палитры Индекс 1 Индекс 2 Индекс 3 (palette_number)
0 зеленый красный коричневый
1 синий малиновый светло- серый
2 светло- светло- желтый зеленый красный
3 светло- светло- белый синий малиновый
В режиме _MRESNOCOLOR, для видеоадаптера CGA с цветным дисплеем используется следующая цветовая палитра:
Номер палитры Индекс 1 Индекс 2 Индекс 3 (palette_number)
0 голубой красный светло- серый
1 светло- светло- белый голубой красный
Если вместо адаптера CGA подключен EGA, то доступны три цветовых палитры:
Номер палитры Индекс 1 Индекс 2 Индекс 3 (palette_number)
0 зеленый красный коричневый
2 светло- светло- желтый зеленый красный
3 светло- светло- желтый синий красный
Функция _selectpalette() возвращает номер предыдущей используемой цветовой палитры.
Функция изменяет цвет фона выводимых символов. Прототип функции приведен ниже:
long _setbkcolor( long color );
В текстовых режимах параметр color должен содержать индекс устанавливаемого цвета фона (см. таблицу 15.1). Например, если палитра устанавливаемая по умолчанию не изменялась, то чтобы напечатать символы на красном фоне, надо вызвать функцию _setbkcolor( 4L ). При использовании функции фон отображенных ранее символов не изменяется.
В графических режимах параметр color должен содержать константу, соответствующую устанавливаемому цвету (см. таблицу 15.1). Например, если палитра устанавливаемая по умолчанию не изменялась, то чтобы напечатать символы на красном фоне, надо вызвать функцию _setbkcolor( _RED ). Константы определены во включаемом файле graph.h следующим образом:
// универсальные цветовые значения
#define _BLACK 0x000000L // черный #define _BLUE 0x2a0000L // голубой #define _GREEN 0x002a00L // зеленый #define _CYAN 0x2a2a00L // синий #define _RED 0x00002aL // красный #define _MAGENTA 0x2a002aL // малиновый #define _BROWN 0x00152aL // коричневый #define _WHITE 0x2a2a2aL // белый #define _GRAY 0x151515L // серый #define _LIGHTBLUE 0x3F1515L // светло-голубой #define _LIGHTGREEN 0x153f15L // светло-зеленый #define _LIGHTCYAN 0x3f3f15L // светло-синий #define _LIGHTRED 0x15153fL // светло-красный #define _LIGHTMAGENTA 0x3f153fL // светло-малиновый #define _YELLOW 0x153f3fL // желтый #define _BRIGHTWHITE 0x3f3f3fL // интенсивно-белый
#define _LIGHTYELLOW _YELLOW
Данные константы представляют цвета в формате, соответствующем регистрам таблицы цветов цифро-аналогового преобразователя адаптера VGA. Каждая константа состоит из трех байт, причем у каждого байта только шесть младших байта значащие.
Следует особо подчеркнуть, что в текстовом режиме после вызова функции цвет фона уже выведенных символов не изменяется, а в графическом режиме сразу меняется цвет всех фоновых символов экрана.
В текстовом режиме функция _setbkcolor() возвращает старый индекс цвета фона, а в графическом - универсальное значение цвета фона (см. таблицу 15.1).
В графическом режиме видеоадаптера функция _setcolor() устанавливает текущий цвет, используемый функциями _setpixel(), _lineto(), _rectangle(), _ellipse(), _arc(), _pie().
Прототип функции _setcolor() приведен ниже:
short _setcolor( short color );
Параметр color должен содержать индекс цвета. По умолчанию используется цвет с наибольшим индексом в палитре цветов.
Функция возвращает предыдущий индекс цвета. В случае ошибки функция возвращает -1.
Функция определяет маску, используемую при рисовании линий функцией _lineto():
void _setlinestyle( unsigned short mask );
Единственный параметр функции является набором из 16 бит. Каждый бит соответствует пикселу на отображаемой линии. При этом если бит параметра равен единице, то соответствующий ему пиксел на линии отображается текущим цветом. А если бит параметра равен нулю, то пиксел не отбражается.
Если функция _setlinestyle() не вызывалась, то по умолчанию маска равна 0xFFFF, и, следовательно, все пикселы линии отображаются на экране.
Функция устанавливает цвет пиксела в заданной позиции экрана. Приведем прототип этой функции:
short _setpixel( short x, short y );
Цвет пиксела устанавливается предварительно функцией _setcolor(). Координаты пиксела задаются параметрами x и y.
Функция возвращает предыдущий цвет пиксела или -1, если произошла ошибка.
Функция устанавливает цвет символов, выводимых функцией _outtext():
short _settextcolor( short index );
Параметр содержит индекс нового цвета символов из таблицы 15.1. Если к номеру индекса прибавить 0x10, то выводимые символы будут мигать.
Функция возвращает предыдущий индекс цвета символов.
Ниже приведен пример использования функций определения и установки цвета фона и цвета текста _getbkcolor(), _setbkcolor(), _gettextcolor(), _settextcolor():
// Пример использования функций _getbkcolor(), _setbkcolor(), // _gettextcolor(), _settextcolor().
#include <conio.h> #include <stdio.h> #include <graph.h>
void main(void) { char buffer[80]; short text_color, old_text_color; long background_color, old_background_color; struct rccoord old_pos;
// сохраняем текущие цвета символов и фона, // а также положение курсора
old_text_color = _gettextcolor(); old_background_color = _getbkcolor(); old_pos = _gettextposition();
// очищаем экран
_clearscreen( _GCLEARSCREEN );
// устанавливаем по очереди первые 25 из 32 возможных цветов фона
for(background_color = 0; background_color < 26; background_color++) { _setbkcolor(background_color ); _settextposition((short)background_color, 1); _settextcolor(_BRIGHTWHITE); sprintf(buffer, "Фон: %3d. Текст:", background_color); _outtext(buffer); // устанавливаем по очереди первые 23 из 32 возможных цветов текста
for(text_color = 0; text_color < 24; text_color++) { _settextcolor(text_color); sprintf(buffer, " %d", text_color); _outtext(buffer); } } getch();
// восстанавливаем цвета символов и фона, // а также позицию курсора
_settextcolor(old_text_color); _setbkcolor(old_background_color); _clearscreen(_GCLEARSCREEN); _settextposition(old_pos.row, old_pos.col); }
Для установки формы курсора, удобно использовать функцию _settextcursor() из стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0. Фактически функция реализована через функцию 01h прерывания 10h.
Формат функции приведен ниже:
short _settextcursor( short shape);
Параметр shape задает новую форму курсора. Старший байт определяет верхную, а младший - нижную границы курсора (см. INT 10h, функция 01h).
Возвращаемая функцией величина определяет предыдущую форму курсора, или если она равна -1 - сообщает об ошибке.
Следующий пример демонстрирует использование функций _gettextcursor() и _settextcursor():
#include <stdio.h> #include <graph.h>
void main(void) { short old_cursor; char top = 0, bottom = 0; int error;
// запоминаем текущую форму курсора
old_cursor = _gettextcursor(); _displaycursor( _GCURSORON );
// если вводится отрицательное значение для любой границы, // то программа завершается
for(;top >= 0 && bottom >= 0 ;) {
// очищаем экран дисплея
_clearscreen( _GCLEARSCREEN ); printf("Введите верхнюю границу курсора:"); scanf("%d", &top); printf("Введите нижнюю границу курсора:"); scanf("%d", &bottom);
// изменение формы курсора
error = _settextcursor((top << 8) | bottom); _clearscreen( _GCLEARSCREEN ); if( error == -1) puts("Ошибка."); else printf("Предыдущая форма курсора:" "\n верхняя граница = %d," "\n нижняя граница = %d.", error >> 8, error & 0xFF);
// ожидаем нажатия на клавиатуру
getch(); }
// восстанавливаем прежнюю форму курсора _settextcursor( old_cursor ); }
Как и функция 02h прерывания INT 10h, функция _settextposition() из стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0 управляет положением курсора на экране:
struct rccoord _settextposition( short row, short column );
Параметры функции задают новое положение курсора на экране: первый параметр - row задает строку (Y координата), а второй параметр - column задает колонку (X координата).
Функция возвращет в структуре rccoord предыдущие координаты курсора (см. функцию _gettextposition()).
Ниже приведен пример использования функций _gettextposition() и _settextposition():
#include <stdio.h> #include <graph.h>
void main(void) { short i, j; struct rccoord old_cur_pos;
// сохраняем старые координаты курсора
old_cur_pos = _gettextposition(); _clearscreen(_GCLEARSCREEN);
for(i = 0; i < 9; i++) for(j = 0; j < 12; j++){
// изменяем координаты курсора
_settextposition(2*j+1, 9*i+1); printf(".(%d,%d)", 9*i+1, 2*j+1); }
getch();
// восстанавливаем положение курсора
_settextposition(old_cur_pos.row, old_cur_pos.col); _clearscreen(_GCLEARSCREEN); }
Функция задает окно на экране дисплея, в котором будет помещаться вся выводимая текстовая информация.
Вывод текста в окно происходит сверху вниз. После заполнения всего окна его содержимое автоматически прокручивается (свертывается) вверх.
Функция _settextwindow() не воздействует на выполнение функции _outtext() (для этого надо воспользоваться функцией _setviewport()).
Приведем прототип функции:
void _settextwindow( short y_up, short x_left, short y_down, short x_right );
Параметры (x_left, y_up) определяют верхний левый угол окна, а параметры (x_right, y_down) - правый нижний угол относительно верхнего левого угла экрана.
Работу функции иллюстрирует следующий пример:
// Пример использования функции _settextwindow().
#include <time.h> #include <stdio.h> #include <conio.h> #include <graph.h>
void main(void) {
clock_t end, wait = 0;
_clearscreen(_GCLEARSCREEN);
// определяем окно в центре экрана
_settextwindow(8, 34, 17, 46);
// функция _settextposition() задает координаты курсора // относительно левого верхнего угла окна
_settextposition(5, 5);
// функция _outtext() осуществляет запись строк символов в окно
while(!kbhit()) { _outtext("0123456789"); for(end = clock() + wait++; clock() < end;); }
_settextwindow(10, 36, 15, 44);
// очищаем новое окно
_clearscreen(_GWINDOW); _settextposition(3, 4); printf("End!"); }
Это одна из наиболее важных функций. Она позволяет изменить режим работы видеоадаптера. Ее формат имеет следующий вид:
short _setvideomode( short mode );
Параметр функции - mode - определяет новый режим и может быть равен одной из констант, представленных в таблице 15.2. Данные константы определены во включаемом файле graph.h.
Константа Режим Характеристики
_TEXTBW40 0, 1 текстовый, 40x25, 16 градаций серого цвета _TEXTC40 0, 1 текстовый, 40x25, 16 цветов _TEXTBW80 2, 3 текстовый, 80x25, 16 градаций серого цвета _TEXTC80 0, 1 текстовый, 80x25, 16 цветов _MRES4COLOR 4, 5 графический, 320x200, 4 цвета _MRESNOCOLOR 4, 5 графический, 320x200, 4 градации серого цвета _HRESBW 6 графический, 640x200, 2 градации серого цвета _TEXTMONO текстовый, 80x25, монохромный _HERCMONO Hercules графический, 720x348, монохромный _MRES16COLOR 0Dh графический, 320x200, 16 цветов _HRES16COLOR 0Eh графический, 640x200, 16 цветов _ERESNOCOLOR 0Fh графический, 640x350, монохромный _ERESCOLOR 10h графический, 640x350, 16 цветов _VRES2COLOR 11h графический, 640x480, 2 цвета _VRES16COLOR 12h графический, 640x480, 16 цветов _MRES256COLOR 13h графический, 320x200, 256 цветов _ORESCOLOR Olivetti графический, 640x400, 1 из 16 видеоадаптер фирмы Olivetti _DEFAULTMODE режим, используемый видеоадаптером по умолчанию _MAXRESMODE графический режим с наивысшим разрешением доступным на данном видеоадаптере _MAXCOLORMODE графический режим с наибольшим числом цветов поддерживаемых видеоадаптером
Таблица 15.2 Режимы работы видеоадаптеров.
Характеристики последних трех режимов, перечисленных в таблице, зависят от типа используемого видеоадаптера и дисплея.
Функция _setvideomode() возвращает число текстовых строк в установленном режиме работы видеоадаптера. Если произошла ошибка, например запрашиваемый режим не поддерживается видеоадаптером, функция возвращает ноль.
В таблице 15.3 перечислены режимы, используемые для констант _MAXRESMODE и _MAXCOLORMODE в зависимости от конфигурации видеоситемы.
Видеоадаптер _MAXRESMODE _MAXCOLORMODE дисплей
Данная функция, также как и функция _setvideomode(), позволяет изменить режим работы видеоадаптера. Но для текстовых режимов она позволяет устанвить нестандартное число строк.
Функция имеет следующий прототип:
short _setvideomoderows( short mode, short rows );
Первый параметр функции - mode, определяет режим, в который переводится видеоадаптер. Этот параметр может быть равен одной из следующих констант: _DEFAULTMODE, _ERESCOLOR, _ERESNOCOLOR, _HERCMONO, _HRES16COLOR, _HRESBW, _MAXCOLORMODE, _MAXRESMODE, _MRES4COLOR, _MRES16COLOR, _MRES256COLOR, _MRESNOCOLOR, _ORESCOLOR, _TEXTBW40, _TEXTBW80, _TEXTC40, _TEXTC80, _TEXTMONO, _VRES2COLOR, _VRES16COLOR. Эти константы описаны в таблице 16.1:
Константа Режим Характеристики
_TEXTBW40 0, 1 текстовый, 40x25, 16 градаций серого цвета
_TEXTC40 0, 1 текстовый, 40x25, 16 цветов
_TEXTBW80 2, 3 текстовый, 80x25, 16 градаций серого цвета
_TEXTC80 0, 1 текстовый, 80x25, 16 цветов
_MRES4COLOR 4, 5 графический, 320x200, 4 цвета
_MRESNOCOLOR 4, 5 графический, 320x200, 4 градации серого цвета
_HRESBW 6 графический, 640x200, 2 градации серого цвета
_TEXTMONO текстовый, 80x25, монохромный
_HERCMONO Hercules графический, 720x348, монохромный
_MRES16COLOR 0Dh графический, 320x200, 16 цветов
_HRES16COLOR 0Eh графический, 640x200, 16 цветов
_ERESNOCOLOR 0Fh графический, 640x350, монохромный
_ERESCOLOR 10h графический, 640x350, 16 цветов
_VRES2COLOR 11h графический, 640x480, 2 цвета
_VRES16COLOR 12h графический, 640x480, 16 цветов
_MRES256COLOR 13h графический, 320x200, 256 цветов
_ORESCOLOR Olivetti графический, 640x400, 1 из 16 видеоадаптер фирмы Olivetti
_DEFAULTMODE режим, используемый видеоадаптером по умолчанию
_MAXRESMODE графический режим с наивысшим разрешением доступным на данном видеоадаптере
_MAXCOLORMODE графический режим с наибольшим числом цветов поддерживаемых видеоадаптером
Таблица 16.1 Режимы работы видеоадаптеров.
Если устанавливается текстовый режим видеоадаптера, то второй параметр функции (rows), задает число строк на экране дисплея.
Второй параметр может быть равен константе _MAXTEXTROWS. В этом случае устанавливается максимально возможное для данной видеосистемы число строк. У видеоадаптера VGA это 50, EGA - 43, а у других адаптеров - 25 строк в текстовых режимах.
Функция возвращает число строк на экране дисплея или 0, если произошла ошибка (запрашиваемый режим не поддерживается видеоадаптером).
Функция перемещает начало логических координат (точку (0, 0)) в точку экрана, имеющую физические координаты (x, y). Прототип функции имеет следующий вид:
struct xycoord _setvieworg( short x, short y );
Функция возвращает предыдущее положение начала логических координат относительно физической системы координат.
Мы будем использовать две различные системы координат - физическую и логическую.
Начало физической системы координат находится в левом верхнем углу экрана дисплея. Оси координат x и y направлены соответственно слева направо и сверху вниз.
Логическая система координат представляет собой прямоугольную область. Ее начало координат расположено в левом верхнем углу прямоугольной области, а оси координат направлены следующим образом: одна - вправо, другая - вниз. По умолчанию, логическая система координат совпадает с физической. Для ее изменения предназначены функции _setviewport() и _setvieworg(). Подавляющее большинство основных графических функций стандартной библиотеки трансляторов Microsoft Quick C 2.5 и C 6.0 применяют логическую систему координат.
Прототип функции _setviewport() приведен ниже:
void _setviewport( short x_first, short y_first, short x_second, short y_second );
Параметры функции x_first, y_first и x_second, y_second задают прямоугольную область экрана, в которую направляется последующий вывод графической информации. При этом верхний левый угол области является началом координат созданной логической системы координат.
Видеоадаптер VGA имеет возможность гашения экрана дисплея:
На входе: AH = 12h;
BL = 36h - управление гашением экрана дисплея;
AL = 0 - включение экрана,
1 - гашение экрана.
На выходе: AL = 12h.
Данная функция возвращает в регистре AL значение 12h, если компьютер имеет видеоадаптер VGA.
Графический контроллер осуществляет обмен данными между видеопамятью и процессором. Графический контроллер может выполнять над данными, поступающими в видеопамять, простейшие логические операции: И, ИЛИ, ИСКЛЮЧАЮЩЕЕ ИЛИ, циклический сдвиг.
Это индексный регистр доступен через порт 3C7h только для записи. Запись в данный регистр индекса элемента цветовой таблицы позволяет прочитать его содержимое через регистр данных цветовой таблицы.
D7-D0 Индекс регистра таблицы цветов (0-255).
Данные из регистров таблицы цветов читаются через порт 3C9h, как три 6-битовых числа. После чтения третьего числа значение индексного регистра (LTRIR) автоматически увеличивается на единицу, что позволяет прочитать всю таблицу цветов, загрузив регистр индекса только один раз.
Особо подчеркнем, что во время операций чтения или записи таблицы цветов прерывания должны быть запрещены.
После записи в регистр LTWIR индекса регистра таблицы цветов можно записать в него новое значение через регистр данных таблицы цветов (см. ниже).
D7-D0 Индекс регистра таблицы цветов (0-255).
Данные записываются в регистры таблицы цветов через порт 3C9h, как три 6-битовых числа. После записи третьего числа значение индексного регистра (LTWIR) автоматически увеличивается на единицу, что позволяет прочитать таблицу цветов, загрузив регистр индекса только один раз.
При чтении процессором данных из видеопамяти они также запоминаются в регистрах-защелках, расположенных на плате видеоадаптера. Когда затем выполняется цикл записи, то над данными, находящимися в этих регистрах, и над данными, поступающими от процессора могут производится следующие логические операции:
Запись неизмененных данных процессора в видеопамять.
Циклический сдвиг записываемых данных процессора.
Выполненеие булевой операции И между записываемыми данными и данными в регистрах-защелках.
Выполненеие булевой операции ИЛИ между записываемыми данными и данными в регистрах-защелках.
Выполненеие булевой операции ИСКЛЮЧАЮЩЕЕИЛИ между записываемыми данными и данными в регистрах-защелках.
Таким образом, видеоадаптер может выполнять часть работы по обработке видеоданных.
Рисунок 6.16 иллюстрирует выполнение графическим контроллером операции записи данных в видеопамять:
Рисунок 6.16 Запись данных в видеопамять.
Байт, записываемый прцесоором в видеопамять (11100001b) поступает в графический контроллер. В соответствии со значением регистра циклического сдвига и выбора функции (регистры адаптеров описаны в следующем разделе), происходит циклический сдвиг на один бит содержимого записываемого в видеопамять байта. Затем результат складывается по логике ИЛИ с содержимым регистров-защелок. Какая булева функция используется - ИЛИ, И, ИСКЛЮЧАЮЩЕЕ ИЛИ также определяется регистром циклического сдвига и выбора функции.
Дальнейшие преобразования происходят в соответствии со значениями регистра разрешения установки/сброса и регистра установки/сброса:
Если бит регистра разрешения установки/сброса, управляющий данным цветовым слоем равен нулю, то байт, записываемый в видеопамять не изменяется.
Если бит регистра разрешения установки/сброса, управляющий данным цветовым слоем равен единице, то в него записывается байт, все биты которого устанавливаются в соответствии со значением регистра установки/сброса для данного цветового слоя.
Затем в соответствии с состоянем регистра битовой маски происходит запись данных в видеопамять:
Если данный бит регистра битовой маски содержит единицу, то соответствующие биты для каждого из цветовых слоев поступают от процесора.
Если данный бит регистра битовой маски содержит ноль, то соответствующие биты для каждого из цветовых слоев поступают из регистров-защелок.
Заметим, что хотя процессор может читать данные только из одного цветового слоя, запись данных в регистры-защелки происходит из всех четырех цветовых слоев. Эту особенность можно использовать для быстрого копирования областей экрана.
MS-DOS предоставляет программистам несколько функций для работы с дисплеем.
Позволяет программе отображать на экране одновременно графику и текст. Адаптер переходит в графический режим и вектор прервания 43h устанавливается так, что используется таблица знакогенератора пользователя.
В таком режиме может отображаться до 43 строк текста на экране. (Для этого необходим улучшенный цветной дисплей.)
На входе: AH = 11h;
AL = 21h - установка вектора прерывания 43h;
ES:BP = адрес таблицы символов;
CX = количество байт, кодирующих один символ в таблице символов;
BL = количество отображаемых на экране строк текста:
1 - 14 строк, 2 - 25 строк, 3 - 43 строки, 0 - число строк содержится в регистре DL.
На выходе: Не используются.
На входе: AH = 11h;
AL = 23h установка вектора прерывания 43h;
BL = количество отображаемых строк текста:
2 - 25 строк, 3 - 43 строки.
На выходе: Не используются.
На входе: AH = 11h;
AL = 22h установка вектора прерывания 43h;
BL = количество отображаемых строк текста:
1 - 14 строк, 2 - 25 строк.
На выходе: Не используются.
На входе: AH = 11h;
AL = 24h установка вектора прерывания 43h;
BL = количество отображаемых строк текста:
1 - 14 строк, 2 - 25 строк, 3 - 43 строки.
На выходе: Не используются.
Функция 04h позволяет определить подключено ли световое перо или нет. Если подключено, можно определить его координаты. Функция позволяет узнать позицию светового пера и в текстовых, и в графических координатах.
Заметим, что световое перо EGA программно не полностью совместимо с CGA, в результате чего программы поддерживающие возможность использования светового пера для видеоадаптера CGA будут работать неправильно с видеоадаптером EGA. Видеоадаптер VGA не имеет светового пера.
На входе: AH = 04h.
На выходе: AH = 0 - световое перо не подключено (все остальные регистры не содержат полезной информации);
AH = 1 - световое перо подключено;
CH = координаты вертикальной позиции курсора в пикселах (графические режимы с низким разрешением);
CX = координаты вертикальной позиции курсора в пикселах (графические режимы с высоким разрешением);
BX = координаты горизонтальной позиции курсора в пикселах;
DH = координаты вертикальной позиции курсора в номерах строк;
DL = координаты горизонтальной позиции курсора в номерах колонок.
Приведем пример использования этой функции:
mov ah,4 int 10h ; определяем положение светового пера
cmp ah,0 ; переходим на метку not_pen, если jz not_pen ; перо не подключено
mov light_pen_col,dl ; сохраняем координаты светового пера mov light_pen_row,dh
Функция 05h позволяет изменить активную страницу видеопамяти. Активная страница видеопамяти отображается на экране.
На входе: AH = 05h - выбор активной страницы видеопамяти;
AL = номер страницы видеопамяти, которая станет активной.
На выходе: Не используются.
Функция 01h позволяет изменить вертикальные размеры курсора путем задания верхней и нижней границ курсора (см. рис 9.1). Горизонтальные размеры курсора всегда одинаковы и равны ширине одного символа.
На входе: AH = 00h - изменение размеров курсора;
CH = верхняя граница курсора:
D3-D0 верхняя граница курсора D5-D4 00b - обычный курсор 01b - невидимый курсор 10b - мигающий курсор 11b - быстро мигающий курсор D7-D6 не используются;
CL = нижняя граница курсора (0-31).
На выходе: Не используются.
Курсор отображается только в текстовых режимах работы видеоадаптера.
При выборе режима работы видеоадаптера BIOS устанавливает следующие значения для верхней и нижней границ курсора:
Для монохромного и улучшенного цветного дисплеев верхняя граница = 11h, а нижняя = 12h.
Для цветного дисплея верхняя граница = 6h, а нижняя = 7h.
Рисунок 9.1 Изменение положения курсора.
Функция 02h задает текущее положение курсора на экране дисплея.
Если видеопамять разделена на несколько страниц, то каждая из них имеет свой курсор, координаты которого можно устанавливать отдельно.
Координаты курсора определяют не только место на экране, где он отображается, но также и позицию, начиная с которой соответствующие функции BIOS будут выводить на экран строки или отдельные символы.
Координаты курсора определяют не только место на экране, где он отображается, но также и позицию, начиная с которой соответствующие функции BIOS будут выводить на экран строки или отдельные символы.
На входе: AH = 02h - установка позиции курсора;
BH = номер страницы видеопамяти;
DH = номер строки (0-24);
DL = номер столбца (0-79).
На выходе: Не используются.
В большинстве дисплеев в качестве устройств отображения используются электронно-лучевая трубка (ЭЛТ), газоразрядная или жидкокристалическая панель. Мы будем рассматривать только ЭЛТ.
ЭЛТ состоит из электронной пушки (или из трех пушек для цветного дисплея), отклоняющей системы и экрана, покрытого слоем люминофора. Все эти устройства помещены в вакумный баллон. Электронная пушка служит источником электронов, направляемых при помощи отклоняющей системы в нужную часть экрана, где электроны взаимодействуют с покрытием экрана. В результате взаимодействия испускается свет.
Изображение на ЭЛТ формируется за счет пробега луча электронов слева направо по горизонтальным линиям экрана. Чтобы глаз не замечал смены кадров, пробег луча по всему экану должен происходить с частотой, большей чем 25Гц.
Луч электронов начинает пробегать по экрану с верхнего левого угла до правого верхнего угла. Когда луч доходит до правой стороны, он гасится и перемещается на следующую горизонтальную линию, находящуюся под предыдущей линией. После того, как луч пробежит по всему экрану, он гасится и перемещается в верхний левый угол. Затем процесс повторяется снова. След от луча на экране образует растр.
Рисунок 6.2 Экран электронно-лучевой трубки.
Изменяя силу тока в луче электронов при формировании им растра, можно менять интенсивность свечения отдельных элементов (пикселов) экрана. Данные в видеопамяти как раз и определяют, как модулируется луч электронов во время сканирования экрана.
Для решения задач управления лучом электронов служит большинство регистров контроллера электронно-лучевой трубки.
Функция решает проблемы, возникающие при использовании программ для CGA на компьютерах, оснащенных видеоадаптерами VGA в улучшенных режимах, когда размер символа по сравнению с использующимся в CGA увеличен. При разрешнии эмуляции курсора CGA, его размеры устанавливаются, как будто символы имеют высоту 8 пикселов.
На входе: AH = 12h;
BL = 34h - управление эмуляцией курсора CGA;
AL = разрешение/запрещение эмуляции курсора:
0 - разрешение эмуляции,
1 - запрещение эмуляции;
На выходе: AL = 12h.
Данная функция возвращает в регистре AL значение 12h, если компьютер имеет видеоадаптер VGA.
Адрес Размер Содержание
0000:0410 1 байт флаги конфигурации: биты D5 и D4 определяют тип текущего первичного дисплея:
D5 D4 видеоадаптер
0 0 EGA 0 1 CGA 40х25 1 0 CGA 80х25 1 1 MDA
0000:0449 1 байт текущий режим работы видеоадаптера
0000:044A слово число символов в строке
0000:044С слово размер страницы видеопамяти в байтах
0000:044E слово значение регистра начального адреса (SAR)
0000:0450 8 слов координаты курсоров для каждой страницы видеопамяти, младший байт определяет столбец, а старший строку экрана в которой находится курсор
0000:0460 слово содержимое регистров начальной и конечной линии курсора (CSR _ старший и CER _ младший байты соответственно)
0000:0462 1 байт номер активной страницы видеопамяти
0000:0463 слово адрес порта контроллера ЭЛТ (3B4 или 3D4)
0000:0465 1 байт установка регистра режима CGA (регистр MCR)
0000:0466 1 байт установка цветовой палитры CGA (регистр CSR)
0000:0484 1 байт число текстовых строк _ 1
0000:0485 слово высота символов в пикселах
0000:0487 1 байт первый байт информации о EGA:
7 6 5 4 3 2 1 0 _________________ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ _________________ _ ___ _ _ _ _ ___ если бит равен единице, то _ _ _ _ _ _ разрешена эмуляция курсора CGA; _ _ _ _ _ _ _ _ _ _ _ _____ равен единице, видеоадаптер _ _ _ _ _ подсоединен к монохрому дисплею; _ _ _ _ _ _ _ _ _ _______ единица в этом бите означает, _ _ _ _ что BIOS будет ожидать обратного _ _ _ _ вертикального хода луча для _ _ _ _ записи в видеопамять; _ _ _ _ _ _ _ _________ бит установлен, если первичным _ _ _ видеоадаптером является EGA; _ _ _ _ _ ___________ не используется; _ _ _ ______________ объем видеопамяти: _ _ 0 0 _ 64К байт, _ 0 1 _ 128К байт, _ 1 0 _ 192К байт, _ 1 1 _ 256К байт; _ _ _________________ единица означает, что последняя операция выбора режима видеоадаптера не очистила видеопамять
0000:0488 1 байт второй байт информации о EGA:
7 6 5 4 3 2 1 0 _________________ ¦ ¦ ¦ _________________ _______ _______ _ ___ положение переключателей на плате _ EGA _ ______________ значение регистра управления дополнительным устройством
0000:04A8 двойное слово адрес таблицы окружения следующий
0000:0500 1 байт состояние печати экрана
00h _ печать закончена
01h _ экран печатается
0FFh _ ошибка во время печати
A000:0000_FFFF видеопамять в графических режимах
B000:0000_7FFF видеопамять в монохромном текстовом режиме
B800:0000_7FFF видеопамять в цветных текстовых режимах и в графическом режиме CGA
C000:0000_3FFF BIOS EGA/VGA
Адрес Регистр
3D4, Регистры контроллера ЭЛТ 3D5 (CRT Controller Register's - CRT_CR)
3D8 Регистр установки режима
3D9 Регистр установки цвета
3DA Регистр состояния (Input Status Register - ISR)
3DB Регистр очистки тригера-защелки светового пера (Clear Light Pen Latch Register- CLPLR)
3DC Установка тригера-защелки светового пера (Set Light Pen Latch Register - SLPLR)
Карта портов ввода/вывода CGA.
Адрес Регистр
3C2 регистр определения различных режимов работы (Miscellaneous Output Register - MOR);
регистр состояния 0 (Input Status Register 0 - ISR0)
3BA регистр управления дополнительным устройством (Feature Control Register)
регистр состояния 1 (Input Status Register 1 - ISR1)
3BB регистр очистки защелки светового пера (Clear Light Pen Latch Register- CLPLR)
3BC установка защелки светового пера (Set Light Pen Latch Register - SLPLR)
3C4, регистры синхронизатора 3C5 (Sequencer Register's - SR)
3B4, регистры контроллера ЭЛТ 3B5 (CRT Controller Register's - CRT_CR)
3CA, регистры графического контроллера 3CC, (Graphics Controller Register's - GCR) 3CE, 3CF
3C0 регистр контроллера атрибутов (Attribute Controller Register - ACR)
3C3 регистр разрешения работы системы VGA (VGA Enable Register - VGA_ER)
3C6, регистры цифро-аналогового преобразователя (ЦАП) VGA 3C7, (VGA Video DAC Register - VGA_DAC_R) 3C8, 3C9
Карта портов ввода/вывода (монохромный режим).
Адрес Регистр
3C2 регистр определения различных режимов работы (Miscellaneous Output Register - MOR);
регистр состояния 0 (Input Status Register 0 - ISR0).
3DA регистр управления дополнительным устройством (Feature Control Register)
регистр состояния 1 (Input Status Register 1 - ISR1)
3DB регистр очистки защелки светового пера (Clear Light Pen Latch Register- CLPLR)
3DC установка защелки светового пера (Set Light Pen Latch Register - SLPLR)
3C4, регистры синхронизатора 3C5 (Sequencer Register's - SR)
3D4, регистры контроллера ЭЛТ 3D5 (CRT Controller Register's - CRT_CR)
3CA, регистры графического контроллера 3CC, (Graphics Controller Register's - GCR) 3CE, 3CF
3C0 регистр контроллера атрибутов (Attribute Controller Register - ACR)
3C3 регистр разрешения работы системы VGA (VGA Enable Register - VGA_ER)
3C6, регистры ЦАП VGA 3C7, (VGA Video DAC Register - VGA_DAC_R) 3C8, 3C9
Карта портов ввода/вывода (цветной режим).
D4-D0 Конец импульса гашения луча горизонтальной развертки. Гашение луча горизонтальной развертки происходит, когда биты D4-D0 равны счетчику длины отображаемой части горизонтальной развертки.
D6-D5 Биты смещения используются в текстовых режимах, чтобы разрешить отображение символов до разрешения вывода. Если величина битов смещения слишком маленькая, то символы на левой стороне экрана могут быть потеряны, а если она слишком большая, то символы на левой стороне экрана могут дублироваться по несколько раз.
D6 D5
0 0 - нет смещения
0 1 - смещение на один символ
1 0 - смещение на два символа
1 1 - смещение на три символа
D7 Бит D7 равен единице для VGA и нулю для EGA.
При установке режима работы видеоадаптера, BIOS загружает в регистр EHBR следующие значения:
Режим | 0,1,4,5,D | 2,3 | 6,E | 7 | F | 10 |
Содержимое регистра | 37h | 2Fh | 2Dh | 3Ah | 1Fh | 17h |
Если используется улучшенный цветной дисплей, то эти значения отличаются:
Режим | 0,1 | 2,3 |
Содержимое регистра | 2Dh | 37h |
В момент, когда младшие 5 битов регистра для EGA или все 8 битов для VGA равны счетчику горизонтальных линий, заканчивается сигнал гашения вертикальной развертки.
D4-D0 Конец импульса горизонтального обратного хода луча. Когда биты D4-D0 равны счетчику символов в строке, то обратный горизонтальный хода луча завершается.
D6-D5 Смещение импульса горизонтального обратного хода луча относительно отображаемого участка горизонтальной развертки. Биты используются EGA.
D6 D5
0 0 - нет смещения
0 1 - смещение на один символ
1 0 - смещение на два символа
1 1 - смещение на три символа
D7 Для EGA с объемом видеопамяти меньшим 256К байт, бит D7 используется для управления горизонтальным панорамированием (горизонтальной сверткой), когда слои видеопамяти сцеплены. Если D7 равен нулю, то после обратного хода луча первый адрес видеопамяти для обновления экрана будет четным. Для VGA бит D7 является пятым битом регистра конца импульса гашения луча горизонтальной развертки (EHBR).
Данный регистр видеоадаптеров EGA и VGA доступен только для записи.
Регистр устанавливает конец обратного вертикального хода луча, а также выполняет некоторые другие функции.
D3-D0 Конец обратного вертикального хода луча. D4 Сброс вертикального прерывания. D5 Разрешения вертикального прерывания. D6 Изменение скорости регенирации экрана. (Только VGA.) D7 Защита от записи. (Только VGA.)
D7 Этот бит позволяет решить некоторые проблеммы совместимости между VGA и видеоадаптерами, построенными на основе микросхемы 6845 (например CGA). Если бит D7 равен единице, то регистры контроллера ЭЛТ, имеющие индексы от 0 до 7, будут защищены от записи в них.
D6 Если бит равен единице, то во время обратного горизонтального хода луча будет генерироваться пять циклов регенерации видеопамяти вместо обычных трех.?
D5 Если бит равен нулю, то при каждом обратном вертикальном ходе луча на линии IRQ2 будет возникать прерывание. Сигнал прерывания сбрасывается записью нуля в бит D4 данного регистра.
D4 Запись нуля в данный бит вызывает сброс вертикального прерывания и переустановку флага незаконченного вертикального прерывания.
D3-D0 Когда значение этих битов поразрядно равны четырем младшим битам счетчика горизонтальных линий, сигнал обратного вертикального хода луча будет окончен.
Регистр задает нижнюю линию сканирования символа, в которой кончается курсор.
D4-D0 Соответствует номеру последней линии курсора.
D7-D5 Не используются.
По умолчанию в регистр конечной линии курсора BIOS загружает следующие значения (которые зависят от режима работы видеоадаптера):
Режим | 0,1,2,3 | 4,5,6 |
Содержимое регистра | 7 | 0 |
Изменяя значение регистров начальной и конечной линии курсора можно менять его положение и размер.
Приведем программу, которая запрашивает с клавиатуры новые значения для регистров начальной и конечной линий курсора, и записывающая их:
// изменение размеров курсора
#include <stdio.h> #include "sysp.h" #include "sysgraph.h"
void main(void) {
char top = 0, bottom = 0; unsigned crt_address; BIOS_VAR _far *bios_var_ptr;
// получаем указатель на область переменных видеофункций BIOS
bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410);
// определяем адрес порта индексного регистра контроллера ЭЛТ
crt_address = bios_var_ptr->crt_address;
printf("Введите верхнюю границу курсора:"); scanf("%d", &top); printf("Введите нижнюю границу курсора:"); scanf("%d", &bottom);
// изменение формы курсора
// выбираем регистр начальной линии курсора
WriteReg(crt_address++, 0x0A);
// записываем в регистр значение переменной top
WriteReg(crt_address--, (unsigned char) top);
// выбираем регистр конечной линии курсора
WriteReg(crt_address++, 0x0B);
// записываем в регистр значение переменной bottom
WriteReg(crt_address, (unsigned char)bottom);
getch(); }
Данная программа, а также часть программ, приведенных ниже, использует для доступа к регистрам видеоадаптера функции ReadReg и WriteReg:
/** *.Name WriteReg * *.Title Запись в порт. * *.Descr Функция выводит данные в порт. * *.Proto WriteReg(unsigned reg, unsigned char data) * *.Params unsigned reg - номер регистра, * * unsigned char data - данные, записываемые в регистр. * *.Return Не ипользуется. * *.Sample get_curs.c **/
WriteReg(unsigned reg, unsigned char data) { _asm { mov dx,reg mov al,data out dx,al } }
/** *.Name ReadReg * *.Title Чтение регистра. * *.Descr Функция читает данные из определенного порта. * *.Proto unsigned char ReadReg(unsigned reg) * *.Params unsigned reg - номер регистра. * *.Return считанные данные. * *.Sample get_curs.c **/ unsigned char ReadReg(unsigned reg) {
unsigned char data;
_asm { mov dx,reg in al,dx mov data,al } return(data); }
Вместо этих функций для доступа к регистрам можно использовать функции inp и outp, из стандартных библиотек трансляторов Microsoft Quick C 2.5 и C 6.0.
Этот регистр, также как и регистр CSR, является доступным для чтения и для записи.
Регистр задает последнюю линию сканирования символа, в которой кончается курсор.
D4-D0 Соответствует номеру последней линии курсора для VGA (см. рисунок 8.4). Для EGA - номеру следующей линии.
D6-D5 Отклонение курсора. Задает смещение курсора относительно позиции, определенной регистром CLR.
00 - нет отклонения
01 - отклонение вправо на один символ
10 - отклонение вправо на два символа
11 - отклонение вправо на три символа
D7 Не используется.
При установке режима работы видеоадаптера BIOS загружает в регистр конечной линии курсора следующие значения:
Режим | 0,1,2,3 | 4,5,6,D,E,F,10 | 7 |
Содержимое регистра | 07 | 00 | 0Ch |
Изменяя значение регистров начальной и конечной линии курсора, можно менять его положение и размер. На левой части рисунка, приведенного ниже, регистр начальной линии курсора равен 0Ah, регистр конечной линии курсора равен 0Bh. На правой части рисунка значение регистров изменено: регистр начальной линии равен 4, а регистр конечной линии - 5.
Рисунок 8.4 Изменение положения курсора.
Следующая программа позволяет прочитать значение регистров начальной и конечной линии курсора:
#include <stdio.h> #include "sysp.h" #include "sysgraph.h"
void main(void) {
char top = 0, bottom = 0; unsigned crt_address; BIOS_VAR _far *bios_var_ptr;
// получаем указатель на область переменных видеофункций BIOS
bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410);
// определяем адрес порта индексного регистра контроллера ЭЛТ
crt_address = bios_var_ptr->crt_address;
// считываем значения регистров начальной и // конечной линии курсора
// выбираем регистр начальной линии курсора
WriteReg(crt_address++, 0x0A);
// считываем значение регистра
top = (unsigned char) ReadReg(crt_address--);
// выбираем регистр конечной линии курсора
WriteReg(crt_address++, 0x0B);
// считываем значение регистра
bottom = (unsigned char) ReadReg(crt_address);
// отображаем на экране значение регистров
printf("\nРегистр начальной линии курсора содержит %x\n" "\nРегистр конечной линии курсора содержит %x\n", top, bottom);
getch(); }
Контроллер атрибутов в графических и текстовых режимах работы видеоадаптера управляет цветами. Значениям цветовых атрибутов ставится в соответствие определенный цвет при помощи таблицы цветовой палитры (Color Lock-up Table). Таблица цветовой палитры ставит в соответствие четырем битам, взятым из видеопамяти, 6 битов цветовой информации. Если к видеоадаптеру EGA подключен цветной дисплей, то используются только четыре младших бита из шести.
Для видеоадаптера EGA эта информация поступает непосредственно на дисплей, а для VGA - преобразуется дальше в соответствии с таблицей цветов и преобразуется тремя цифро-аналоговыми преобразователями в RGB сигнал и только после этого передается на дисплей.
Таким образом, изменяя данные, записанные BIOS в таблицу цветовой палитры при выборе определенного режима работы видеоадаптера, можно менять используемую палитру цветов.
На рисунках 6.17 и 6.18 показана работа контроллера атрибутов в графическом и текстовом режимах.
Рисунок 6.17 Контроллер атрибутов в текстовых режимах.
В текстовых режимах видеоадаптеров, цвет символа и его фона определяется его байтом атрибутов. Цвет фона символа, как видно из рисунка, задают четыре старших бита байта атрибутов. Значение этих четырех бит служит индексом в таблице цветовой палитры. Элемент таблицы с данным индексом впоследствии определяет цвет фона символа.
Аналогично битам, определяющим цвет фона символа, четыре младших бита задают цвет самого символа.
Рисунок 6.18 Контроллер атрибутов в графических режимах.
В отличае от текстовых режимов, в графических режимах цвет каждого пиксела определяется отдельно. На рисунке 6.18 четыре бита, считанные из цветовых слоев видеопамяти определяют один пиксел. Значене этих бит служат индексом для таблицы цветовой палитры. Элементы таблицы определяют цвет данного пиксела.
Контоллер атрибутов подробно описан в разделе "Регистры видеоадаптеров EGA и VGA".
Контроллер ЭЛТ выполняет следующие функции:
Вырабатывает сигналы, управляющие работой ЭЛТ (развертка и гашение).
Определяет формат экрана и символов текста (разрешающую способность экрана и размер символов).
Определяет форму курсора.
Управляет световым пером.
Управляет вертикальной сверткой (скроллингом) содержимого экрана.
Так как контроллер ЭЛТ выполняет жизненно важные для дисплея функции, то изменять содержиме регистров этого контроллера очень опасно. В некоторых случаях может даже произойти физическое разрушение экрана (например, повреждение люминофора).
Регистры контроллера ЭЛТ загружаются BIOS значениями, зависящими от типа дисплея, видеоадаптера и текущего режима работы.
Мы не рекомендуем вам без особой необходимости изменять содержимое этих регистров. Практически все что необходимо, можно сделать при помощи функций BIOS, не подвергая дорогостоящий видеоадаптер и дисплей излишнему риску.
Большая часть регистров CGA доступна только для записи, что создает определенные проблемы, особенно для мультизадачных систем.
Доступ к большинству регистров видеоадаптеров осуществляется в два этапа: через один порт ввода/вывода выбираетя номер интересующего вас регистра, а затем через другой порт ввода/вывода осуществляется обмен данными. Это позволяет сэкономить большое число портов процессора.
Ниже, в таблице 7.1, приведен список адресов регистров видеоадаптера CGA.
Адрес | Регистр |
3D4, | Регистры контроллера ЭЛТ |
3D5 | (CRT Controller Register's - CRT_CR) |
3D8 | Регистр установки режима |
3D9 | Регистр установки цвета |
3DA | Регистр состояния (Input Status Register - ISR) |
3DB | Регистр очистки тригера-защелки светового пера (Clear Light Pen Latch Register- CLPLR) |
3DC | Установка тригера-защелки светового пера (Set Light Pen Latch Register - SLPLR) |
Таблица 7.1 Карта портов ввода/вывода CGA.
В таблице 7.2 приведены адреса памяти в зависимости от режима работы:
Номер режима работы | Адрес памяти |
0,1,2,3,4,5,6 | B000:8000-B000:FFFF |
Таблица 7.2 Распределение памяти в разных режимах.
Адрес | Регистр |
3C2 | регистр определения различных режимов работы (Miscellaneous Output Register - MOR); |
регистр состояния 0 (Input Status Register 0 - ISR0). | |
3DA | регистр управления дополнительным устройством Feature Control Register) |
регистр состояния 1 (Input Status Register 1 - ISR1) | |
3DB | регистр очистки защелки светового пера (Clear Light Pen Latch Register- CLPLR) |
3DC | установка защелки светового пера (Set Light Pen Latch Register - SLPLR) |
3C4, | регистры синхронизатора |
3C5 | (Sequencer Register's - SR) |
3D4, | регистры контроллера ЭЛТ |
3D5 | (CRT Controller Register's - CRT_CR) |
3CA, | регистры графического контроллера |
3CC, | (Graphics Controller Register's - GCR) |
3CE, | |
3CF | |
3C0 | регистр контроллера атрибутов (Attribute Controller Register - ACR) |
3C3 | регистр разрешения работы системы VGA (VGA Enable Register - VGA_ER) |
3C6, | регистры ЦАП VGA |
3C7, | (VGA Video DAC Register - VGA_DAC_R) |
3C8, | |
3C9 |
Номер режима работы | Адрес памяти |
0,1,2,3,4,5,6 | B000:8000-B000:FFFF |
7 | B000:0000-B000:7FFF |
0Dh,0Eh,0Fh,10h,11h,12h,13h | A000:0000-A000:FFFF |
Регистр может быть использован для отображения большего, чем обычно, количества символов в строке. Например, для перевода видеоадаптера в режим отображения 132 симвов в строке.
В графических режимах регистр OFR задает логическую длину (в 16-битных словах или 32-битных двойных словах) горизонтальной линии развертки. Если линия num развертки начинается по адресу adr, то следующая линия развертки num+1 начинается по адресу adr+offset, где offset это значение регистра OFR.
В текстовых режимах регистр содержит смещение между соседними строками текста, заданное в 16-битных словах.
Использование регистраа OFR иллюстрируется рисунком 8.7. На верхней части рисунка видеоадаптер находится в стандартном текстовом режиме с разрешением 80 символов в строке. При этом значение регистра логической ширины экрана равно 40. На нижней части рисунка представлен результат увеличения содержимого регистра до 41. Логическая ширина экрана в этом случае увеличивается до 82 символов в строке. Последние два символа каждой строки не помещаются на экране. Для их отображения надо выполнить горизонтальную свертку экрана.
Рисунок 8.7 Логическая ширина экрана.