6. Регистры видеоадаптера CGAВ этой главе мы опишем все основные регистры видеоадаптера CGA, которые могут быть полезны при написании программ. Необходимо заметить, что хотя программирование видеоадаптеров на уровне регистров позволяет увеличить скорость работы программ и решить некоторые задачи, которые нельзя решить при помоши функций BIOS, это может вызвать ряд проблем при переносе ваших программ на другие машины. Рассмотрим совместимость видеоадаптера CGA и видеоадаптеров EGA и VGA. Видеоадаптер CGA создан на основе микросхемы Motorola 6845, а видеоадаптеры EGA и VGA используют специализированные БИС-ы. Хотя EGA и VGA имеют регистры, соответствующие регистрам CGA, некоторые из них располагаются по другим адресам и могут выполнять дополнительные функции. Например видеоадаптеры EGA и VGA могут вызывать аппаратное прерывание по линии IRQ2 в начале каждого обратного вертикального хода луча. Кроме того, в каждом новом видеоадаптере расширяется набор используемых регистров. В результате такой не полной совместимости, программы непосредственно программирующие регистры видеоадаптера могут перестать правильно работать при переносе их на компьютер с другим типом видеоадаптера. 6.1. Краткий обзорБольшая часть регистров CGA доступна только для записи, что создает определенные проблемы, особенно для мультизадачных систем. Доступ к большинству регистров видеоадаптеров осуществляется в два этапа: через один порт ввода/вывода выбираетя номер интересующего вас регистра, а затем через другой порт ввода/вывода осуществляется обмен данными. Это позволяет сэкономить большое число портов процессора. Ниже, в таблице 7.1, приведен список адресов
регистров видеоадаптера CGA.
Таблица 7.1 Карта портов ввода/вывода CGA. В таблице 7.2 приведены адреса памяти в
зависимости от режима работы:
Таблица 7.2 Распределение памяти в разных режимах. 6.2. Регистры контроллера ЭЛТРегистры контроллера ЭЛТ управляют сигналами синхронизации, необходимыми для формирования растра, определяют формат данных на экране, форму курсора, а также управляют световым пером. Большнство из этих регистров не представляют интереса для их непосредственного программирования. Более того, их неправильное использоване может послужить причиной физического разрушения дисплея. Поэтому мы подробно рассмотрим лишь наиболее полезные и безопасные регистры контроллера. Для видеоадаптеров, построенных на основе
микросхемы Motorola 6845 - MDA, CGA и Hercules, контроллер ЭЛТ
содержит 18 регистров. В таблице 7.3 приведен
список всех регистров контроллера ЭЛТ и их
индексы, используемые для доступа к ним.
Таблица 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] Так как адреса портов индексного регистра и регистра данных контроллера ЭЛТ являются смежными, то адрес порта регистра данных можно получить, прибавив единицу к адресу порта индексного регистра. Общая длина линии горизонтальной развертки (Horizontal Total Register - HTR) (индекс 0)Этот регистр относится к группе регистров контроллера ЭЛТ, которые управляют генерацией синхросигналов для дисплея. Необходимость модификации данной группы регистров возникает только при программировании нестандартных режимов работы видеоадаптеров. Регистр HTR определяет число знакомест на одной линии сканирования, включая обратный ход луча. Для CGA количество знакомест по горизонтали будет на одно больше, чем значение, записанное в регистре. Длина отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER) (индекс 1)Данный регистр используется адаптерами CGA и Hercules. Регистр задает длину отображаемого участка горизонтальной развертки. Величина регистра равна числу символов в строке экрана. Положение горизонтальной синхронизации (Horizontal Sync Position - SHBR) (индекс 2)Регистр CGA, определяющий начало обратного хода луча. Изменяя содержимое регистра можно смещать изображение на экране влево и вправо. Ширина горизонтального синхросигнала (Horizontal Sync Pulse Width Register - HSPWR) (индекс 3)Для видеоадаптеров MDA, CGA и Hercules регистр определяет продолжительность обратного хода луча в символах. Число горизонтальных линий растра (VTR) (индекс 4)Определяет число текстовых строк в растре. Выравнивание растра (Vertical Total Adjust Register - VTAR) (индекс 5)Определяет количество текстовых строк в растре, отведенных под рамку экрана. Длина отображаемой части вертикальной развертки (Vertical Displayed - VDR) (индекс 6)Регистр CGA, задающий число отображаемых текстовых строк. Положение вертикальной синхронизации (Vertical Sync Position Register - VSPR) (индекс 7)Регистр видеоадаптера CGA, определяющий начало обратного вертикального хода луча. Режим соединения (Interlase Mode Register - IMR) (индекс 8)Регистр CGA. Биты D4 и D5 задают режим соединения. Биты D6 и D7 определяют отклонение экрана. Регистр всегда содержит 2. Высота символов текста
|
Режим | 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 ); }
Регистр адреса светового пера (LPAR)
Это 16-битовый регистр, который имеется в видеоадаптерах CGA и EGA, доступен только для чтения. Регистр LPAR дает возможность определить положение светового пера на экране. Регистр содержащий старший байт адреса светового пера имеет индекс 10h, а регистр содержащий младший байт - индекс 11h.
LPAR сохраняет адрес видеопамяти, которая регенерировалась в момент включения светового пера.
6.3. Регистр выбора режима. (Mode Select Register)
Этот регистр, доступный для записи через порт 3D8h, используется видеоадаптером CGA, для установки режима работы.
- D0 Используется в текстовых режимах. При D0 равном нулю, отображается 40 символов в строке, а при D0 равном единице - 80 символов.
- D1 Для графических режимов с разрешением 320 пикселов по горизонтали, бит D1 равен единице. Во всех остальных режимах бит равен нулю.
- D2 Если бит равен единице, то запрещается раздельный цветовой сигнал. Это может улучшить качество изображения, если вы используете монохромный композитный дисплей.
- D3 При D3, равном нулю, выходной видеосигнал не генерируется. Экран дисплея становится черным. Рекомендуется гасить экран во время обратного вертикального хода луча. В противном случае возможно возникновение "снега".
- D4 Бит D4 установлен в 1 для графического режима с разрешением 640 пикселов по горизонтали, и сброшен в 0 во всех остальных режимах.
- D5 Если бит равен нулю, то бит D7 байта атрибутов символа определяет интенсивность фона. Если бит равен единице, то бит D7 управляет миганием символа.
- D7-D6 Не используются.
6.4. Регистр выбора цвета. (Color Select Register)
Этот регистр, доступный для записи через порт 3D9h, используется видеоадаптером CGA для установки цвета рамки экрана и установки цветовой палитры. Цвет рамки может быть выбран из 16 возможных цветов. А цветовая палитра устанавливается либо стандартной, либо дополнительной.
Для режимов 4 и 5 цвет рамки соответствует цвету фона (пикселы со значением 0), а для режима 6 - пикселам со значением 1.
- D0 Синяя составляющая цвета рамки.
- D1 Зеленая составляющая цвета рамки.
- D2 Красная составляющая цвета рамки.
- D3 Интенсивность цвета рамки.
- D4 В текстовых режимах управляет интенсивностью фона, а в графических режимах - интенсивностью пикселов.
- D5 Бит D5 выбирает текущую палитру цветов для графических режимов.
- D7-D6 Не используются.
6.5. Регистр состояния (Input Status Register - ISR0)
Регистр позволяет получить различную информацию о состоянии видеоадаптера. Содержимое регистраможно прочитать через порт, имеющий адрес 3DAh. Регистр состояния доступен только для чтения.
Регистр состояния имеет следующий формат:
- D0 Бит разрешения отображения.
- D1 Бит тригера светового пера.
- D2 Бит переключателя светового пера.
- D3 Бит обратного вертикального хода луча.
- D7-D4 Биты не используются.
Ниже подробно рассмотрено назначение отдельных битов данного регистра.
- D7-D4 Биты не используются.
- D3 Бит обратного вертикального хода луча. Бит принимает значение 1 во время обратного вертикального хода луча по кадру.
- D2 Бит переключателя светового пера. Если переключатель светового пера находится в положении ON (включено), то бит D2 равен единице. Если же переключатель находится в положении OFF (выключено), то бит D2 равен нулю.
- D1 Бит триггера светового пера. Бит равен единице, если триггер светового пера установлен.
- D0 Бит разрешения отображения. Бит принимает нулевое значение во время интервала активности дисплея, тоесть когда адаптер читает данные из видеопамяти и отображает их на экране. Бит равен единице во время горизонтального и вертикального обратного хода луча. Если процессор обращается к видеопамяти во время интервала активности, то видеоадаптер CGA может создавать на экране эффект, называемый "снег", так как происходит конфликт между видеоадаптером CGA и процессором за право доступа к памяти. Сразу заметим, что в видеоадаптере EGA и более новых адаптерах этот недостаток устранен.
Для устранения "снега" на видеоадаптере CGA, возникает необходимость синхронизовать доступ процессора к видеопамяти с периодом вертикального или горизонтального обратного хода луча. Этого можно достичь тестированием данного регистра.
6.6. Регистр сброса триггера-защелки светового пера (Light Pen Latch Reset Register - LPLRR)
Доступ к регистру производится через порт 3DBh. Любая операция записи (OUT) в этот регистр сбрасывает триггер-защелку светового пера.
6.7. Регистр установки триггера-защелки светового пера (Light Pen Latch Set Register - LPLRR)
Доступ к регистру производится через порт 3DCh. Любая операция записи (OUT) в этот регистр вызывает установку триггера-защелки светового пера.