Программирование видеоадаптеров CGA, EGA и VGA© Александр Фролов, Григорий ФроловТом 3, М.: Диалог-МИФИ, 1992, 287 стр. 7.6. Регистры контроллера атрибутовКонтроллер атрибутов управляет цветовыми характеристиками изображений. Контроллер атрибутов содержит двадцать один регистр. Регистры перечисленны в таблице 8.17. Доступ к ним осуществляется через один порт - 3C0h (в отличие от предыдущих рассмотренных нами регистров). Этот порт совмещает в себе функции индексного порта и порта данных, регулируемые внутренним триггером. Триггер переключается при каждой операции записи в порт и записываемые данные воспринимаются либо как индекс регистра, либо как данные для обмена с регистром. Установить триггер в исходное состояние можно,
выполнив чтение из порта 3BAh для монохромного
режима или из порта 3DAh - для цветного режима
работы видеоадаптера. После установки триггера
данные, записываемые в регистр 3C0h, будут
восприниматься, как индекс регистра.
Таблица 8.17 Регистры контроллера атрибутов. Регистры цветовой палитры (0-15)
|
Режим | 0,1,2,3 | 4,5,6,D,E,10 | 7 | F |
Содержимое регистра | 08 | 01 | 0Eh | 0Bh |
Регистр цвета рамки экрана
(Screen Border Color Register - SBCR) (индекс 11)
В текстовых режимах работы видеоадаптеров регистр задает цвет рамки, расположенной вокруг текста. Назначение битов регистра соответствует регистрам цветовой палитры. По умолчанию регистр цвета рамки содержит нулевые значения для всех режимов работы.
К сожалению операция установки цвета рамки работает не правильно на большинстве адаптеров EGA.
Регистр разрешения цветового слоя
(Color Plane Enable Register - CPER) (индекс 12)
- D3-D0 Биты разешения цветовых слоем. Если бит равен нулю, то данные из соответствующего цветвого слоя не поступают в регистры цветовой палитры. Такаим образом достигается эффект маскирования отдельных цветовых слоев.
- D5-D4 Исполььзуются вместе с диагностическими битами регистра состояния 1 для чтения регистров палитры.
- D7-D6 Не используются.
При установке режима работы видеоадаптера BIOS
записывает в регистр следующие значения:
Режим | 0,1,2,3,7,D,E | 4,5 | 6 | F,10 | |
Содержимое регистра | 0Fh | 03 | 03 | 01 | 05 |
Регистр горизонтального панорамирования
(Horizontal Panning Register - HPR) (индекс 13)
Регистр позволяет сдвигать в горизонтальном направлении содержимое экрана на один пиксел. При использовании регистра HPR совместно с регистром начального адреса контроллера атрибутов можно производить горизонтальный сдвиг экрана влево на любое число пикселов.
Формат регистра горизонтального панорамирования представлен ниже:
- D3-D0 Биты задают величину горизонтального сдвига. Соответствие содержимого регистра и величины сдвига для различных режимов приведены в таблице 8.18.
- D7-D4 Не используются.
D3 D2 D1 D0 | Величина сдвига содержимого экрана (в пикселах) | ||
монохромный текстовый | VGA, режим 13h | остальные режимы | |
0 0 0 0 | 8 | 0 | 0 |
0 0 0 1 | 0 | - | 1 |
0 0 1 0 | 1 | 1 | 2 |
0 0 1 1 | 2 | - | 3 |
0 1 0 0 | 3 | 2 | 4 |
0 1 0 1 | 4 | - | 5 |
0 1 1 0 | 5 | 3 | 6 |
0 1 1 1 | 6 | - | 7 |
1 0 0 0 | 7 | - | - |
1 0 0 1 | - | - | - |
1 0 1 0 | - | - | - |
1 0 1 1 | - | - | - |
1 1 0 0 | - | - | - |
1 1 0 1 | - | - | - |
1 1 1 0 | - | - | - |
1 1 1 1 | - | - | - |
Таблица 8.18 Величина горизонтального сдвига в различных режимах работы видеоадаптера.
По умолчанию для всех режимов работы видеоадаптера регистр горизонтального панорамирования содержит нулевые значения для всех битов.
На рисунке 8.16 иллюстрируется операция горизонтального сдвига содержимого экрана при различных значениях регистра HPR. На левой части рисунка регистр горизонтального панорамирования содержит ноль, а на правой части рисунка значение регистра увеличено до трех, при этом изображение на экране сдвигается на три пиксела влево.
Рисунок 8.16 Горизонтальный сдвиг экрана.
Следующая программа позволяет перемещать содержимое экрана по горизонтали и вертикали. Функции HorScroll и VerScroll реализуют, соответственно, горизонтальный и вертикальный сдвиг экрана.
// смещение содержимого экрана по горизонтали и вертикали #include "sysgraph.h" #include <stdio.h> #include <stdlib.h> #include <graph.h> #include "sysp.h" #include <dos.h> void HorScroll(unsigned, unsigned); void VerScroll(unsigned); void SetColumn(unsigned char); void main(void) { struct videoconfig vc; unsigned char i,j; // выбираем текстовый режим работы видеоадаптера, // принятый по умолчанию _setvideomode(_DEFAULTMODE); // устанавливаем логическую ширину экрана в 100 символов SetColumn(100); // отображаем на экране дисплея 24 строки текста for(i = 0; i < 24; i++) printf("\ntext text text"); // производим горизонтальное смещение экрана // на i пикселов при каждом нажатии на клавиатуру for(i = 0; i < 13; i++) { getch(); HorScroll(i,8); } // производим вертикальное смещение экрана // на i пикселов при каждом нажатии на клавиатуру for(i = 0; i < 13; i++) { getch(); VerScroll(i); } getch(); _setvideomode(_DEFAULTMODE); } /** *.Name HorScroll * *.Title Горизонтальный сдвиг содержимого экрана. * *.Descr Функция смещает содержимое экрана влево на определенное * число пикселов. * *.Proto void HorScroll(unsigned offset, unsigned wide) * *.Params unsigned offset - величина смещения в пикселах, * * unsigned wide - ширина символов (8 или 9). * *.Return Не используется. * *.Sample scroll.c **/ void HorScroll(unsigned offset, unsigned wide) { unsigned start_addr_reg, panning_reg; div_t res; res = div(offset,wide); start_addr_reg = res.quot; panning_reg = (wide == 9) ? ((res.rem == 0) ? 8 : res.rem - 1 ) : res.rem; _asm { push ds ; вычисляем адрес регистра состояния 1 (3BAh/3DAh) xor ax,ax mov es,ax mov dx,es:[463h] add dx,6 ; ожидаем начало обратного вертикального хода луча in al,dx nop nop test al,08h jz wait_on wait_off: in al,dx nop nop test al,08h jnz wait_off wait_on: in al,dx nop nop test al,08h jz wait_on ; вычисляем адрес порта индексного регистра контроллера ЭЛТ sub dx,6 ; выбираем для доступа младший байт регистра начального адреса mov al,0Dh out dx,al ; вычисляем адрес порта регистра данных контроллера ЭЛТ inc dx ; устанавливаем новый начальный адрес mov ax,start_addr_reg out dx,al ; снова получаем адрес порта регистра состояния 1 add dx,5 ; сбрасываем внутренний триггер контроллера атрибутов, управляющий ; адресацией его регистров in al,dx nop nop ; выбираем регистр горизонтального панорамирования mov dx,3C0h mov al,13h out dx,al mov ax,panning_reg out dx,al pop ds } } /** *.Name VerScroll * *.Title Вертикальный сдвиг содержимого экрана. * *.Descr Функция смещает содержимое экрана вверх на определенное * число пикселов. * *.Proto void VerScroll(unsigned offset) * *.Params unsigned offset - величина смещения в пикслах. * *.Return Не используется. * *.Sample scroll.c **/ void VerScroll(unsigned offset) { unsigned start_addr_reg, preset_row_reg; div_t res; BIOS_VAR _far *bios_var_ptr; bios_var_ptr = (BIOS_VAR _far *) FP_MAKE(0x0000, 0x0410); res = div(offset,bios_var_ptr -> char_height); start_addr_reg = res.quot * (bios_var_ptr -> columns); preset_row_reg = res.rem; _asm { push ds ; вычисляем адрес регистра состояния 1 (3BAh/3DAh) xor ax,ax mov es,ax mov dx,es:[463h] add dx,6 ; ожидаем начало обратного вертикального хода луча in al,dx nop nop test al,08h jz wait_on wait_off: in al,dx nop nop test al,08h jnz wait_off wait_on: in al,dx nop nop test al,08h jz wait_on ; вычисляем адрес порта индексного регистра контроллера ЭЛТ sub dx,6 ; модифицируем младший байт регистра начального адреса mov al,0Dh out dx,al inc dx mov ax,start_addr_reg out dx,al dec dx ; модифицируем старший байт регистра начального адреса mov al,0Ch out dx,al inc dx mov al,ah out dx,al ; вычисляем адрес порта регистра состояния 1 add dx,5 ; ожидаем вертикальный обратный ход луча wait_next: in al,dx nop nop test al,08h jz wait_next ; определяем адрес порта индексного регистра контроллера ЭЛТ sub dx,6 ; устанавливаем регистр предустановки линии сканирования mov al,8 out dx,al mov ax,preset_row_reg inc dx out dx,al pop ds } } /** *.Name SetColumn * *.Title Установка логической ширины экрана. * *.Descr Функция устанавливает логическую ширину экрана. * *.Proto void SetColumn(unsigned char col) * *.Params unsigned char col - логическая ширина экрана (в символах). * *.Return Не используется. * *.Sample scroll.c **/ void SetColumn(unsigned char col) { _asm { xor ax,ax mov es,ax ; получаем адрес порта индексного регистра ; контроллера ЭЛТ (3B4h/3D4h) mov dx,es:[463h] ; выбираем для обмена регистр логической ширины экрана mov al,13h out dx,al ; вычисляем адрес порта регистра данных контроллера ЭЛТ (3B5h/3D5h) inc dx ; модифицируем переменную BIOS, содержащую число символов в строке mov al,col mov es:[44Ah],al ; регистр логической ширины экрана в текстовых режимах содержит ; смещение между соседними строками текста в словах shr al,1 out dx,al } }
Регистр выбора цвета
(Color Select Register - CSR) (индекс 14)
Регистр используется только видеоадаптером VGA для управления цветом.
- D0 Цвет Р4.
- D1 Цвет Р5. Данные биты могут использоваться вместо линий Р5 и Р4 соответственно (см. регистры палитры и рисунок 6.18).
- D2 Цвет Р6.
- D3 Цвет Р7. Биты используются контроллером атрибутов в качестве двух старших битов, передаваемых ЦАП (см. рисунок 6.18). В режиме 256-цветном режиме VGA данные биты не используются.
- D7-D4 Не используются.