В этой главе мы опишем все основные регистры видеоадаптера CGA, которые могут быть полезны при написании программ. Необходимо заметить, что хотя программирование видеоадаптеров на уровне регистров позволяет увеличить скорость работы программ и решить некоторые задачи, которые нельзя решить при помоши функций BIOS, это может вызвать ряд проблем при переносе ваших программ на другие машины.
Рассмотрим совместимость видеоадаптера CGA и видеоадаптеров EGA и VGA. Видеоадаптер CGA создан на основе микросхемы Motorola 6845, а видеоадаптеры EGA и VGA используют специализированные БИС-ы. Хотя EGA и VGA имеют регистры, соответствующие регистрам CGA, некоторые из них располагаются по другим адресам и могут выполнять дополнительные функции. Например видеоадаптеры EGA и VGA могут вызывать аппаратное прерывание по линии IRQ2 в начале каждого обратного вертикального хода луча. Кроме того, в каждом новом видеоадаптере расширяется набор используемых регистров.
В результате такой не полной совместимости, программы непосредственно программирующие регистры видеоадаптера могут перестать правильно работать при переносе их на компьютер с другим типом видеоадаптера.
Большая часть регистров 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 Распределение памяти в разных режимах.
Регистры контроллера ЭЛТ управляют сигналами синхронизации, необходимыми для формирования растра, определяют формат данных на экране, форму курсора, а также управляют световым пером.
Большнство из этих регистров не представляют интереса для их непосредственного программирования. Более того, их неправильное использоване может послужить причиной физического разрушения дисплея. Поэтому мы подробно рассмотрим лишь наиболее полезные и безопасные регистры контроллера.
Для видеоадаптеров, построенных на основе
микросхемы Motorola 6845 - MDA, CGA и Hercules, контроллер ЭЛТ
содержит 18 регистров. В таблице 7.3 приведен
список всех регистров контроллера ЭЛТ и их
индексы, используемые для доступа к ним.
Индекс |
Регистр контроллера ЭЛТ |
0 |
общая длина линии горизонтальной
развертки (Horizontal Total Register - HTR) |
1 |
длина отображаемой части
горизонтальной развертки (Horizontal Displayed - HDR) |
2 |
положение горизонтальной синхронизации
(Horizontal Sync Position - HSR) |
3 |
ширина горизонтального синхросигнала
(Horizontal Sync Pulse Width Register - HSPWR) |
4 |
число горизонтальных линий растра (Vertical
Total Register - VTR) |
5 |
выравнивание ратстра (Vertical Total Adjust Register -
VTAR) |
6 |
длина отображаемой части вертикальной
развертки (Vertical Displayed - VDR) |
7 |
положение вертикальной синхронизации
(Vertical Sync Position Register - VSPR) |
8 |
режим соединения (Interlase Mode Register - IMR) |
9 |
высота символов текста (Max Scan Line Register - MSLR)
|
0Ah |
начальная линия курсора (Cursor Start Register - CSR)
|
0Bh |
конечная линия курсора (Cursor End Register - CER) |
0Ch |
старший байт начального адреса (Start Address
Register - SAR, high byte) |
0Dh |
младший байт начального адреса (Start address
Register - SAR, low byte) |
0Eh |
старший байт позиции курсора (Cursor Location
Register - CLR, high byte) |
0Fh |
младший байт позиции курсора (Cursor Location
Register - CLR, low byte) |
10h |
старший байт адреса светового пера (Light
Pen Address Register - LPAR, high byte) |
11h |
младший байт адреса светового пера (Light
Pen Address Register - LPAR, low byte) |
Таблица 7.3 Регистры контроллеров ЭЛТ, построенных на основе микросхемы Motorola 6845 или ее аналогов.
Адресация регистров контроллера ЭЛТ происходит через два порта. В первый порт (индексный) записывается индекс регистра, к которому осуществляетя доступ, а через второй порт (порт данных) можно производить обмен данными (запись или чтение).
Учтите, что у видеоадаптера CGA большинство регистров контроллера ЭЛТ являются доступными только для записи. Только регистры SAR и CLR доступны как для записи, так и для чтения.
У видеоадаптеров MDA и Hercules индексный порт имеет адрес 3B4h, а порт данных - адрес 3B5h. Для CGA адреса портов другие. Индексный порт имеет адрес 3D4h, а порт данных - адрес 3D5h.
Использование видеоадаптерами различного адресного пространства для портов контроллера ЭЛТ необходимо, чтобы предоставить возможность одновременного подключения к компьютеру двух видеоадаптеров.
Адрес порта индексного регистра записан в области переменных видеофункций BIOS, по адресу 0000:0463. Приведем фрагмент программы для получения адреса порта индексного регистра контроллера ЭЛТ:
; устанавливаем es на нулевой сегмент xor ax,ax mov es,ax ; записываем в dx адрес порта индексного регистра контроллера ЭЛТ mov dx,es:[463h]
Так как адреса портов индексного регистра и регистра данных контроллера ЭЛТ являются смежными, то адрес порта регистра данных можно получить, прибавив единицу к адресу порта индексного регистра.
Этот регистр относится к группе регистров контроллера ЭЛТ, которые управляют генерацией синхросигналов для дисплея. Необходимость модификации данной группы регистров возникает только при программировании нестандартных режимов работы видеоадаптеров.
Регистр HTR определяет число знакомест на одной линии сканирования, включая обратный ход луча.
Для CGA количество знакомест по горизонтали будет на одно больше, чем значение, записанное в регистре.
Данный регистр используется адаптерами CGA и Hercules. Регистр задает длину отображаемого участка горизонтальной развертки. Величина регистра равна числу символов в строке экрана.
Регистр CGA, определяющий начало обратного хода луча. Изменяя содержимое регистра можно смещать изображение на экране влево и вправо.
Для видеоадаптеров MDA, CGA и Hercules регистр определяет продолжительность обратного хода луча в символах.
Определяет число текстовых строк в растре.
Определяет количество текстовых строк в растре, отведенных под рамку экрана.
Регистр CGA, задающий число отображаемых текстовых строк.
Регистр видеоадаптера CGA, определяющий начало обратного вертикального хода луча.
Регистр CGA. Биты D4 и D5 задают режим соединения. Биты D6 и D7 определяют отклонение экрана. Регистр всегда содержит 2.
Этот регистр определяет число линий сканирования на один символ или, другими словами, высоту символов в пикселах. Регистр используется только в текстовых режимах работы видеоадаптеров.
Приведем формат регистра:
Рисунок 7.1 Использование регистра высоты символов текста.
Регистр задает верхнюю линию сканирования символа. С этой линии начинается курсор. Вместе с регистром конечной линии курсора (CER), он определяет размер и форму курсора.
Приведем формат регистра:
По умолчанию в регистр CSR BIOS загружает, в зависимости от режима работы видеоадаптера, следующие значения:
Режим 0,1,2,3 4,5,6 Содержимое регистра 6 0
Регистр задает нижнюю линию сканирования символа, в которой кончается курсор.
По умолчанию в регистр конечной линии курсора
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.
Это группа из двух регистров: регистр старшего байта начального адреса (Start Address Register - SAR, high byte) (индекс 0Ch) и регистр младшего байта начального адреса (Start Address Register - SAR, low byte) (индекс 0Dh).
Данные регистры содержат адрес данных видеопамяти, которые будут отображаться в верхнем левом углу экрана дисплея. Регистры начального адреса можно использовать для перемещения изображения по экрану (панорамирования) и для переключения активной страницы памяти.
Регистры начального адреса доступны только для записи. После инициализации видеоадаптера регистры обнуляются.
На рисунке 7.2 показано, как происходит панарамирование экрана при изменении регистров начального адреса. В верхней части рисунка регистры начального адреса содержат ноль. В этом случае видеопамять отображается на экране с начала. В нижней части значение регистров начального адреса увеличено до 77. Как видно из рисунка, в этом случае видеопамять отображается на экране начиная с данных, имеющих смещение 77 от начала видеопамяти. При этом снизу экрана возникает изображение, ранее не помещавщееся на экране.
Рисунок 7.2 Использование регистров начального адреса.
Два регистра - регистр старшего байта положения курсора (Cursor Location Register - CLR_h, high byte) (индекс 0Eh) и регистр младшего байта положения курсора (Cursor Location Register - CLR_l, low byte) (индекс 0Fh) определяют положение курсора на экране (см. рисунок 7.3). Они содержат смещение относительно начала видеобуфера байта на котором установлен курсор.
Это единственные регистры видеоадаптера CGA, доступные как для записи, так и для чтения.
Рисунок 7.3 Отображение курсора на экране.
Программа, приведенная ниже, считывает значения из регистров положения курсора.
// чтение регистра положения курсора #include <stdio.h> #include <graph.h> #include "sysp.h" #include "sysgraph.h" void main(void) { int crt_port; unsigned char h_pos, l_pos; BIOS_VAR _far *bios_var_ptr; // получаем указатель на область переменных видеофункций BIOS bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410); // определяем адрес порта индексного регистра контроллера ЭЛТ crt_port = bios_var_ptr -> crt_address; // выбираем старший байт регистра положения курсора WriteReg(crt_port, 0x0E); // считываем значение старшего байта регистра положения курсора h_pos = ReadReg(crt_port + 1); // выбираем младший байт регистра положения курсора WriteReg(crt_port, 0x0F); // считываем значение младшего байта регистра положения курсора l_pos = ReadReg(crt_port + 1); printf("\nТекущий адрес курсора %X:%X\n", (unsigned char) h_pos, (unsigned char) l_pos ); }
Это 16-битовый регистр, который имеется в видеоадаптерах CGA и EGA, доступен только для чтения. Регистр LPAR дает возможность определить положение светового пера на экране. Регистр содержащий старший байт адреса светового пера имеет индекс 10h, а регистр содержащий младший байт - индекс 11h.
LPAR сохраняет адрес видеопамяти, которая регенерировалась в момент включения светового пера.
Этот регистр, доступный для записи через порт 3D8h, используется видеоадаптером CGA, для установки режима работы.
Этот регистр, доступный для записи через порт 3D9h, используется видеоадаптером CGA для установки цвета рамки экрана и установки цветовой палитры. Цвет рамки может быть выбран из 16 возможных цветов. А цветовая палитра устанавливается либо стандартной, либо дополнительной.
Для режимов 4 и 5 цвет рамки соответствует цвету фона (пикселы со значением 0), а для режима 6 - пикселам со значением 1.
Регистр позволяет получить различную информацию о состоянии видеоадаптера. Содержимое регистраможно прочитать через порт, имеющий адрес 3DAh. Регистр состояния доступен только для чтения.
Регистр состояния имеет следующий формат:
Ниже подробно рассмотрено назначение отдельных битов данного регистра.
Для устранения "снега" на видеоадаптере CGA, возникает необходимость синхронизовать доступ процессора к видеопамяти с периодом вертикального или горизонтального обратного хода луча. Этого можно достичь тестированием данного регистра.
Доступ к регистру производится через порт 3DBh. Любая операция записи (OUT) в этот регистр сбрасывает триггер-защелку светового пера.
Доступ к регистру производится через порт 3DCh. Любая операция записи (OUT) в этот регистр вызывает установку триггера-защелки светового пера.