7. Регистры видеоадаптеров EGA и VGAВ этой главе мы опишем все основные регистры видеоадаптеров EGA и VGA, которые могут быть полезны при написании программ. Необходимо указать, что хотя программирование видеоадаптеров на уровне регистров позволяет увеличить скорость работы программ и решить некоторые задачи, которые нельзя решить при помоши функций BIOS, это может вызвать ряд проблем при переносе ваших программ на другие машины. Дело в том, что не все адаптеры совместимы на уровне регистров. Например, оригинальный видеоадаптер CGA создан на основе микросхемы Motorola 6845, а видеоадаптеры EGA и VGA используют более совершенный аналог этой микросхемы. Хотя EGA и VGA имеют регистры, соответствующие регистрам CGA, некоторые из них располагаются по другим адресам и могут выполнять какие-либо дополнительные функции. Кроме того, в каждом новом видеоадаптере расширяется набор используемых регистров. Существуют модели видеоадаптеров EGA, VGA, Super VGA поддерживающие режим совместимости, когда они эмулируют адаптеры более низкого уровня (например MDA, Hercules, CGA). При этом эмуляция обычно происходит на уровне регистров, что гарантирует полную их совместимость. Режимы совместимости, если они поддерживаются, описаны в руководстве этого видеоадаптера. На практике, для управления видеоадаптерами, рекомендуется преимущественно использовать функции BIOS. Это избавит вас от неприятных минут, когда ваша работающая программа, при переносе на другую машину перестанет правильно выполняться. 7.1. Краткий обзорВидеоадаптеры EGA и VGA содержат большое количество регистров. EGA имеет около шестидесяти регистров, а VGA и Super VGA еще больше. Большая часть регистров EGA доступна только для записи, что создает определенные проблемы, особенно для мультизадачных систем. Из-за этого некоторые фирмы-изготовители видеоадаптеров выпускают совместимые с EGA платы видеоадаптеров, для регистров которых разрешена также и операция чтения. В новых адаптерах VGA и Super VGA практически все регистры доступны как для записи так и для чтения. Условимся, что в тех случаях, когда VGA имеет отличия от EGA, мы будем на это специально указывать. Доступ к большинству регистров видеоадаптеров осуществляется в два этапа: через один порт ввода/вывода выбирается номер интересующего вас регистра, а затем через другой порт ввода/вывода осуществляется обмен данными. Это позволяет сэкономить большое число портов процессора. Заметим, что в различных режимах работы
видеоадаптера, его регистры могут иметь
различные адреса. В таблицах 8.1 и 8.2 приведен
список адресов регистров в монохромных и цветных
режимах.
Таблица 8.1 Карта портов ввода/вывода (монохромный режим).
Таблица 8.2 Карта портов ввода/вывода (цветной режим). Адресное пространство видеопамяти также
различается в разных режимах работы
видеоадаптера. В таблице 8.3 приведены адреса
памяти в зависимости от режима работы.
Таблица 8.3 Распределение видеопамяти в различных режимах. Функция Get_Seg_Vmem, приведенная ниже, при помощи функции 0Fh прерывания INT 10h определяет текущий режим работы видеоадаптера и возвращает сегмент начала видеопамяти. Если видеоадаптер работает в нестандартном режиме, функция возвращает ноль. #include "sysp.h" unsigned Get_Seg_Vmem(void) { unsigned char mode; unsigned seg_address; // определяем текущий режим видеоадаптера _asm { mov ah,0Fh int 10h mov mode,al } // если видеоадаптер находится в режимах 0, 1, 2, 3, // 4, 5, 6 то видеопамять начинается с сегмента B800h if((mode >= 0) && (mode <= 6)) seg_address = 0xB800; // если видеоадаптер находится в режиме 7, // то видеопамять начинается с сегмента B000h else if(mode == 7) seg_address = 0xB000; // если видеоадаптер находится в режимах 0Dh - 13h, // то видеопамять начинается с сегмента A000h else if((mode >= 0x0D) && (mode <= 0x13)) seg_address = 0xA000; // если видеоадаптер не находится в стандартном режиме // возвращаем ноль else seg_address = 0x0; return(seg_address); } Ниже подробно рассмотрены регистры видеоадаптеров EGA и VGA. Регистры сгруппированы по признаку выполняемых ими функций. Мы выделили следующие группы регистров:
7.2. Внешние регистрыЭти регистры называются внешними, так как в видеоадаптере EGA они не принадлежат центральной микросхеме, содержащей контроллер атрибутов, контроллер ЭЛТ, графический контроллер и преобразователь последовательности. В адаптере VGA все регистры находятся на одной микросхеме, но эти регистры традиционно называют "внешними". Заметим, что в отличие от остальных регистров, внешние регистры адресуются непосредственно по адресам своих портов, без использования индексного регистра. Регистр определения различных режимов работы
|
D3 | D2 | Режим |
0 | 0 | 640 столбцов (или 320 столбцов) |
0 | 1 | 720 столбцов |
1 | 0 | внешний генератор (доступен через разъем дополнительного устройства) |
1 | 1 | зарезервированно |
Таблица 8.5 Установка битов D3 и D2.
- D1 Разрешение доступа к видеопамяти. Данный бит может быть запретить доступ процессора к видеопамяти для операций чтения и записи. Если бит равен нулю, то доступ к видеопамяти запрещен. Хотя процессор при запрещении доступа к видеопамяти не может обращаться к ней, циклы регенерации все равно будут выполняться. И содержимое видеопамяти не разрушится.
- D0 Выбор адресов ввода/вывода. Бит D0 определяет адрес регистра управления дополнительным устройством (Feature Control Register), регистра состояния 1 (Input Status Register 1) и регистров контроллера ЭЛТ (CRT Controller). Когда данный бит равен нулю, происходит выбор адресного пространства монохромного режима (3Bхh). Если бит равен единице, то используется адресное пространство цветного режима работы видеоадаптера (3Dхh).
Данные, первоначально записываемые BIOS в этот
регистр зависят от режима работы видеоадаптера:
Режим | 0-6,0Dh,0Eh | 7 | Fh | 10h |
Содержимое регистра | 23h | 0A6h | 0A2h | 0A7h |
Регистр управления дополнительным
устройством
(Feature Control Register - FCR)
Для видеоадаптера EGA биты D1 и D0 данного регистра передают сигналы на разъем дополнительного устройства, соответственно, на линии FC0 (вывод 21) и FC1 (вывод 20) разъема. Этот регистр не используется для VGA, но бит D3 должен содержать ноль.
Адрес порта ввода/вывода данного регистра зависит от режима видеоадаптера. В монохромном режиме адрес порта 3BAh, а в цветном - 3DAh.
Регистр доступен только для записи, но VGA позволяет прочитать его содержимое через порт 3CAh.
Регистр состояния 0
(Input Status Register 0 - ISR0)
Данный регистр, имеющий адрес 3C2h, доступен только для чтения.
Регистр позволяет получить различную информацию от видеоадаптера EGA. Формат регистра приведен ниже:
3-D0 Не используются. 4 Состояние переключателей. 5 Бит 0 дополнительного устройства (FEAT0). 6 Бит 1 дополнительного устройства (FEAT1). 7 Бит прерывания от ЭЛТ.
- D7 Бит прерывания от ЭЛТ. Бит установлен в 1, когда произошло вертикальное прерывание (по линии IRQ2) из-за обратного вертикального хода луча по кадру (погашеный луч перемещается из правого нижнего угла экрана в левый верхний). Этот бит устанавливается в начале обратного вертикального хода луча и сбрасывается записью в регистр конца вертикального хода луча.
- D6 Бит 1 дополнительного устройства. Используется только EGA. Бит регистра подключен к 17-му выводу разъема дополнительного устройства.
- D5 Бит 0 дополнительного устройства. Используется только EGA. Бит регистра подключен к 19-му выводу разъема дополнительного устройства.
- D4 Состояние переключателей. При помощи данного бита регистра, BIOS EGA считывает состояние четырех переключателей, находящихся на плате видеоадаптера и определяющих его конфигурацию. Номер считываемого переключателя задается двумя битами выбора частоты (Бтиы D2 и D3) регистра определения различных режимов работы (MOR), согласно следующей таблице:
Бит D3 | Бит D2 | Считываемый переключатель |
0 | 0 | переключатель 1 |
0 | 1 | переключатель 2 |
1 | 0 | переключатель 3 |
1 | 1 | переключатель 4 |
Таблица 8.6 Установка битов D3 и D2.
Если бит D4 установлен в единицу, то переключатель, заданный битами D2 и D3 регистра определения различных режимов работы, находится в положении ON. Если бит сброшен в ноль, то переключатель находится в положении OFF.
Для EGA эти четыре переключателя определяют, какой дисплей используется с видеоадаптером и какой дополнительный видеоадаптер может быть подключен к компьютеру (cм. главу "Системы с двумя дисплеями").
Ниже показаны правильные варианты установки переключателей для различных конфигураций видеосистемы.
4 3 2 1 _________ Первичный: EGA с цветным дисплеем (40х25). ON ¦Ё Ё¦ OFF ¦ Ё Ё ¦ Дополнительный: MDA. _________ 4 3 2 1 _________ Первичный: EGA с цветным дисплеем (80х25). ON ¦Ё ¦ OFF ¦ Ё Ё Ё¦ Дополнительный: MDA. _________ 4 3 2 1 _________ Первичный: EGA с улучшенным цветным дисплеем. ON ¦ Ё Ё Ё¦ OFF ¦Ё ¦ Дополнительный: MDA. _________ 4 3 2 1 _________ Первичный: EGA с улучшенным цветным дисплеем. ON ¦ Ё Ё ¦ OFF ¦Ё Ё¦ Дополнительный: MDA. _________ 4 3 2 1 _________ Первичный: EGA с монохромным дисплеем. ON ¦ Ё Ё¦ OFF ¦Ё Ё ¦ Дополнительный: CGA с цветным дисплеем _________ (40х25). 4 3 2 1 _________ Первичный: EGA с монохромным дисплеем. ON ¦ Ё ¦ OFF ¦Ё Ё Ё¦ Дополнительный: CGA с цветным дисплеем _________ (80х25) 4 3 2 1 _________ Первичный: MDA. ON ¦Ё Ё Ё Ё¦ OFF ¦ ¦ Дополнительный: EGA с цветным дисплеем _________ (40х25). 4 3 2 1 _________ Первичный: MDA. ON ¦Ё Ё Ё ¦ OFF ¦ Ё¦ Дополнительный EGA с цветным дисплеем _________ (80х25). 4 3 2 1 _________ Первичный: MDA. ON ¦Ё Ё Ё¦ OFF ¦ Ё ¦ Дополнительный: EGA с улучшенным цветным _________ дисплеем. 4 3 2 1 _________ Первичный: MDA. ON ¦Ё Ё ¦ OFF ¦ Ё Ё¦ Дополнительный: EGA с улучшенным цветным _________ дисплеем. 4 3 2 1 _________ Первичный: CGA с цветным дисплеем 40х25 ON ¦Ё Ё Ё¦ OFF ¦ Ё ¦ Дополнительный: EGA с монохромным дисплеем. _________ 4 3 2 1 _________ Первичный: CGA с цветным дисплеем 80х25 ON ¦Ё Ё ¦ OFF ¦ Ё Ё¦ Дополнительный: EGA с монохромным дисплеем. _________
VGA использует бит D4 для определения типа используемого дисплея (цветной или монохромный).
Особенно подчеркнем, что положение этих переключателей может быть считано также из байта памяти с адресом 0000:0488h:
- D3-D0 Биты, соответствующие переключателям. Если бит установлен в единицу, то соответствующий переключатель находится в положении ON. Если бит сброшен в ноль, то переключатель находится в положении OFF.
- D7-D4 Не используются.
Следующая программа считывает значение регистра состояния 0, выделяет биты D5 и D6, поступающие с разъема дополнительного устройства и отображает значения этих битв на экране диспля.
// чтение битов дополнительного устройства // (битов D5 и D6 регистра состояния 0) #include <stdio.h> #include "sysp.h" #include "sysgraph.h" void main(void) { int feature_bits; unsigned crt_address; BIOS_VAR _far *bios_var_ptr; // читаем содержимое регистра состояния 0 и выделяем // биты D5 и D6 feature_bits = (ReadReg(0x3C2) & 0x60) >> 5; printf("Биты дополнительного устройства: %x\n", feature_bits); }
Функция ReadReg, используемая в программе, описана ранее.
Регистр состояния 1
(Input Status Register 1 - ISR0)
Регистр позволяет получить различную информацию о состоянии видеоадаптера.
Для видеоадаптера CGA Содержимое регистраможно считать через порт, имеющий адрес 3DAh. Для адаптеров EGA и VGA данный регистр, имеет адрес 3BAh в монохромных режимах и адрес 3DAh - в цветных. Регистр состояния 1 доступен только для чтения.
Приведем формат регистра состояния 1:
D0 Бит разрешения отображения. D1 Бит тригера светового пера. D2 Бит переключателя светового пера. D3 Бит обратного вертикального хода D5-D4 Диагностические биты. D7-D6 Биты не используются.
- D7, D6 Биты не используются.
- D5, D4 Диагностические биты, применяемые для получения двух из шести цветовых выходных сигналов передаваемых на дисплей (для EGA). Какие два сигнала из шести будут диагностироваться, определяют с помощью регистра разрешения цветового слоя контролленра атрибутов (Таблица 8.7):
Регистр разрешения Регистр состояния 1 цветового слоя D5 D4 D5 D4 0 0 красный синий 0 1 второй красный второй зеленый 1 0 второй синий зеленый 1 1 не используется не используется
Таблица 8.7 Считывание диагностических битов EGA.
Таблица 8.8 показывает, как можно считать два из восьми цветовых сигналов вырабатываемых контроллером атрибутов видеоадаптера VGA:
Регистр разрешения Регистр состояния 1 цветового слоя D5 D4 D5 D4 0 0 P2 P0 0 1 P5 P4 1 0 P3 P1 1 1 P7 P6
Таблица 8.8 Считывание диагностических битов VGA.
Фактически биты D5 и D4 представляют возможность прочитать содержимое регистров таблицы цветовой палитры для видеоадаптера EGA. Следует отметить, что некоторые адаптеры, совместимые с EGA, не поддерживают эти биты. По-этому их использование может наложить некоторые ограничения на работу программы.
- D3 Бит обратного вертикального хода луча. Бит принимает значение 1 в течение обратного вертикального хода луча по кадру. Данный бит также установлен в случае, если разрешено прерывание IRQ2 EGA, и другое устройство выдает запрос на это прерывание.
Биты D2 и D1 относятся к управлению световым пером. Для видеоадаптеров VGA и Super VGA эти биты не используются, так как такие адаптеры не поддерживают световое перо.
- D2 Бит переключателя светового пера. Если переключатель светового пера находится в положении ON (включено), то бит D2 равен единице. Если же переключатель находится в положении OFF (выключено), то бит D2 равен нулю.
- D1 Бит триггера светового пера. Бит равен единице, если триггер светового пера установлен. Этот бит будет сохранять единицу до записи нуля через порт с адресом 3BBh для монохромного режима, или через порт 3DBh - для цветного режима.
- D0 Бит разрешения отображения. Бит принимает значение единицы во время интервала активности дисплея (когда адаптер читает данные из видеопамяти), и равен нулю во время горизонтального и вертикального обратного хода луча.
Во многих случаях возникает необходимость синхронизовать выполнение некоторых действий с периодом вертикального или горизонтального обратного хода луча. Этого можно достичь обработкой прерывания IRQ2 или тестированием регистра состояния 1.
Ниже представлена программа, использующая функцию WaitVert, для определения частоты кадров. Функция WaitVert задерживает выполнение программы до начала обратного вертикального хода луча.
// программа определения частоты кадров #include <time.h> #include <stdio.h> #include <bios.h> #define NUM 200 void WaitVert(void); void main() { time_t t_start, t_end; int i; float fr; // определяем время запуска процесса t_start = clock(); // ожидаем когда процесс вертикальной разверти выполнится NUM раз for(i = 0; i < NUM; i++) WaitVert(); // определяем время завершения процесса t_end = clock(); // вычисляем частоту кадров fr = NUM/(((float)t_end - t_start) / CLK_TCK); printf( "\nЧастота кадров = %4.1f \n", (float)fr ); } /** *.Name WaitVert * *.Title Определение начала обратного вертикального хода луча. * *.Descr Функция ожидает начало обратного вертикального хода луча. * Использование функции позволяет синхронизировать работу * программы с периодами работы видеоадаптера. * *.Proto void WaitVert(void) * *.Params Отсутствуют. * *.Return Не используются. * *.Sample get_vert.c **/ void WaitVert(void) { unsigned count; _asm { ; устанавливаем регистр es на сегмент с нулевым адресом mov ax,0h mov es,ax ; определяем адрес порта индексного регистра ; контроллера ЭЛТ (3B4h/3D4h в ; зависимости от режима работы видеоадаптера - ; монохромный или цветной) mov dx,es:[463h] ; вычисляем адрес порта регистра состояния 1 (ISR1); ; это достигается добавлением к адресу порта ; индексного регистра 6, так как адрес порта регистра ; состояния 1 равен 3BAh или 3DAh в зависимости от режима ; работы видеоадаптера (монохромный или цветной) add dl,6 ; читаем содержимое порта регистра состояния 1 in al,dx ; тестируем бит D3 регистра состояния 1 ; бит D3 = 1 во время обратного вертикального хода луча test al,8 jz wait_on wait_off: in al,dx ; тестируем бит D3 test al,8 ; ожидаем конец обратного вертикального хода луча jnz wait_off wait_on: in al,dx test al,8 ; ожидаем начало обратного вертикального хода луча jz wait_on ; ; здесь могут распологаться операции, которые необходимо ; выполнить во время обратного вертикального хода луча ; } }
Регистр разрешения работы системы VGA
(VGA Enable Register - VGA_ER)
Данный регистр имеет адрес 3С3h. Регистр используется только для VGA. Биты D1-D7 зарезервированны, а бит D0 управляет работой VGA. Если он равен нулю, то запрещен доступ к видеопамяти и портам ввода/вывода видеоадаптера (кроме самого регистра VGA_ER).
Регистр сброса триггера-защелки светового пера (Light Pen Latch Reset Register - LPLRR)
Доступ к регистру производится через порт 3DBh для цветного режима и через 3BBh для монохромного. Регистр используется только видеоадаптерами CGA и EGA. Любая операция записи (OUT) в этот регистр сбрасывает триггер-защелку светового пера.
Регистр установки триггера-защелки светового пера (Light Pen Latch Set Register - LPLRR)
Доступ к регистру производится через порт 3DCh для цветного режима и через 3BCh для монохромного. Регистр используется только видеоадаптерами CGA и EGA. Любая операция записи (OUT) в этот регистр вызывает установку триггера-защелки светового пера.
7.3. Регистры контроллера ЭЛТ
Регистры контроллера ЭЛТ управляют сигналами синхронизации, необходимыми для формирования растра, определяют формат данных на экране, форму курсора, а также для видеоадаптеров CGA и EGA управляют световым пером.
Большинство из этих регистров не предсталяют интереса для их непосредственного программирования. Более того, их неправильное использоване может послужить причиной физического разрушения дисплея. Поэтому мы подробно рассмотрим лишь наиболее полезные и безопасные регистры контроллера.
Назначение и формат ряда регистров контроллера ЭЛТ различаются для видеоадаптеров EGA, VGA и для видеоадаптеров MDA, Hercules и CGA. Кроме того, они могут различаться и для видеоадаптерв одного типа, но разных фирм-производителей. В результате могут возникнуть проблем совместимости на компьютерах, оснащенных другим видеоадаптером. Если вы все-таки решитесь их перепрограммировать, то обращайтесь к описанию вашего адаптера.
Регистры контроллера ЭЛТ составляют самую многочисленную группу регистров видеоадаптеров. Для видеоадаптеров EGA и VGA группа содержит 24 регистра.
В таблице 8.9 приведен список всех регистров
контроллера ЭЛТ и их индексы, используемые для
доступа к ним.
Индекс | Регистр контроллера ЭЛТ |
0 | общая длина линии горизонтальной развертки (Horizontal Total Register - HTR) |
1 | длина отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER) |
2 | начало импульса гашения луча горизонтальной развертки (Start Horizontal Blank Register - SHBR) |
3 | конец импульса гашения луча горизонтальной развертки (End Horizontal Blank Register - EHBR) |
4 | начало импульса горизонтального обратного хода луча (Start Horizontal Retrace Register - SHRR) |
5 | конец импульса горизонтального обратного хода луча (End Horizontal Retrace Register - EHRR) |
6 | число горизонтальных линий растра (Vertical Total Register - VTR) |
7 | дополнительный регистр (Overflow Register - OVR) |
8 | предварительная установка горизонтальной развертки (Preset Row Scan Register - PRSR) |
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 | начало обратного вертикального хода луча (Vertical Retrace Start Register - VRSR) |
11h | конец обратного вертикального хода луча (Vertical Retrace End Register - VRER) |
10h | старший байт адреса светового пера (Light Pen Address Register - LPAR, high byte) |
11h | младший байт адреса светового пера (Light Pen Address Register - LPAR, low byte) |
12h | начало гашения вертикальной развертки (Vertical Display End Register - VDER) |
13h | логическая ширина экрана (Offset Register - OFR) |
14h | положение подчеркивания символа (Underline Location Register - ULR) |
15h | начало импульса гашения вертикальной развертки (Start Vertical Blank Register - SVBR) |
16h | конец импульса гашения вертикальной развертки (End Vertical Blank Register - EVBR) |
17h | управление режимом (Mode Control Register - MCR) |
18h | регистр сравнения линий (Line Compare Register - LCR) |
Таблица 8.9 Регистры EGA и VGA контроллера ЭЛТ.
В отличие от внешних регистров, адресация к регистрам контроллера ЭЛТ происходит через два порта. В первый порт (индексный) записывается индекс регистра, к которому осуществляетя доступ, а через второй порт (порт данных) можно производить обмен данными (запись или чтение). Заметим, что у видеоадаптера EGA большинство регистров контроллера ЭЛТ доступны только для записи.
У видеоадаптеров MDA и Hercules индексный порт имеет
адрес 3B4h, а порт данных - адрес 3B5h. Для CGA адреса
портов другие. Индексный порт имеет адрес 3D4h, а
порт данных - адрес 3D5h. Адреса портов контроллера
ЭЛТ для видеоадаптеров EGA и VGA зависят от режима
работы видеоадаптера (монохромный или цветной). В
монохромном режиме адрес порта индексного
регистра равен 3B4h, а регистра данных - 3B5h. В
цветном режиме адреса соответственно равны 3D4h и
3D5h:
Тип адаптера | Адрес порта индексного регистра | Адрес порта регистра данных |
MDA и Hercules | 3B4h | 3B5h |
CGA | 3D4h | 3D5h |
EGA и VGA (монохромный режим) | 3B4h | 3B5h |
EGA и VGA (цветной режим) | 3D4h | 3D5h |
Таблица 8.10 Адреса портов индексного регистра и регистра данных.
Использование видеоадаптерами различного адресного пространства для портов контроллера ЭЛТ необходимо, чтобы создать возможность одновременного подключения к компьютеру двух видеоадаптеров.
Адрес порта индексного регистра записан в области переменных видеофункций BIOS, по адресу 0000:0463. Приведем фрагмент программы, определяющей адрес индексного порта контроллера ЭЛТ:
; устанавливаем es на нулевой сегмент xor ax,ax mov es,ax ; записываем в dx адрес порта индексного регистра контроллера ЭЛТ mov dx,es:[463]
Так как адреса портов индексного регистра и регистра данных контроллера ЭЛТ является смежными, то адрес порта регистра данных можно получить, прибавив единицу к адресу порта индексного регистра.
Общая длина линии горизонтальной развертки (Horizontal Total Register - HTR) (индекс 0)
Этот регистр относится к группе регистров контроллера ЭЛТ, которые управляют генерацией синхросигналов для дисплея. Необходимость модификации данной группы регистров возникает только при программировании нестандартных режимов работы видеоадаптера.
Кроме регистров, контроллер ЭЛТ использует еще два внутренних счетчика для управления синхросигналами. Счетчик числа горизонтальных знакомест экрана увеличивается при выводе очередного сивола на экран (регенерация экрана) и сбрасывается, когда его значение становится равным регистру общей длины линии горизонтальной развертки. Счетчик числа горизонтальных линий развертки увеличивается после окончания обратного горизонтального хода луча и сбрасывается, когда достигает величины, хранящейся в регистре числа горизонтальных линий растра.
Регистр HTR определяет число знакомест на одной линии сканирования, включая обратный ход луча и рамку экрана.
Для EGA число знакомест по горизонтали будет на два, а для VGA на пять больше, чем значение, хранящееся в регистре.
При установке режима работы видеоадаптера, BIOS
загружает в регистр HTR следующие значения:
Режим | 0,1,4,5,D | 2,3,6,E | 7, | F | 10 |
Содержимое регистра | 37h | 70h | 60h | 5Bh |
Если используется улучшенный цветной дисплей,
то эти значения отличаются:
Режим | 0,1 | 2,3 |
Содержимое регистра | 2Dh | 5Bh |
Длина отображаемой части горизонтальной развертки (Horizontal Display Enable End Register - HDER) (индекс 1)
Регистр задает длину отображаемого участка горизонтальной развертки. Величина, записанная в регистр на единицу меньше, чем число символов в строке экрана.
При установке режима работы видеоадаптера, BIOS загружает в регистр HDER следующие значения:
Режим | 0,1,4,5,D | 2,3,6,7,E,F,10 |
Содержимое регистра | 27h | 4Fh |
Начало импульса гашения луча горизонтальной развертки (Start Horizontal Blank Register - SHBR) (индекс 2)
Регистр используется видеоадаптерами EGA и VGA для определения начала импульса гашения луча горизонтальной развертки.
При установке режима работы видеоадаптера, BIOS
загружает в регистр SHBR следующие значения:
Режим | 0,1,4,5,D | 2,3 | 6,E | 7,F | 10 |
Содержимое регистра | 2Dh | 5Ch | 59h | 56h | 53h |
Если используется улучшенный цветной дисплей,
то эти значения отличаются:
Режим | 0,1 | 2,3 |
Содержимое регистра | 2Bh | 53h |
Конец импульса гашения луча горизонтальной развертки (End Horizontal Blank Register - EHBR) (индекс 3)
- 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 |
Начало импульса горизонтального обратного хода луча (Start Horizontal Retrace Register - SHRR) (индекс 4)
Для EGA и VGA регистр задает момент начала импульса горизонтального обратного хода луча.
При установке режима работы видеоадаптера, BIOS
загружает в регистр SHRR следующие значения:
Режим | 0,1 | 4,5,D | 2,3 | 6,E | 7 | F,10 |
Содержимое регистра | 31h | 30h | 5Fh | 5Eh | 51h | 50h |
Если используется улучшенный цветной дисплей,
то эти значения отличаются:
Режим | 0,1 | 2,3 |
Содержимое регистра | 28h | 51h |
Конец импульса горизонтального обратного хода луча (End Horizontal Retrace Register - EHRR) (индекс 5)
- 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).
Число горизонтальных линий растра (VTR) (индекс 6)
Регистр определяет общее число линий горизонтальной развертки в кадре вертикальной развертки, включая гашение вертикального хода луча и обратный вертикальный ход луча.
Для видеоадаптера EGA, регистр VTR содержит девять битов. Девятый бит находится в дополнительном регистре (OVR). Регистр VTR видеоадаптера VGA содержит десять битов. Десятый бит, также как и девятый, расположен в дополнительном регистре (OVR).
Дополнительный регистр (OVR) (индекс 7)
Многие регистры контроллера ЭЛТ, видеоадаптера 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.
Предварительная установка горизонтальной
развертки
(Preset Row Scan Register - PRSR) (индекс 8)
Регистр позволяет производить плавную вертикальную прокрутку содержимого экрана дисплея в текстовых режимах (свертку). В графических режимах регистр должен содержать нулевое значение.
- D4-D0 Биты предварительной установки строчной
развертки. Эти биты задают для самой верхней
строки текста на экране номер линии в матрице
символов, начиная с которой начинают
отображаться символы (см. рисунок 8.1). Как видно из
рисунка самая верхняя строка текста
отображается не полностью. Плавную прокрутку
экрана можно производить увеличивая или
уменьшая
значение этих битов. - D6-D5 Биты управления побайтовым панорамированием. Используются только VGA. Они являются двумя дополнительными битами регистра горизонтального панорамирования контроллера атрибутов и позволяют сдвигать экран более, чем на 8 пикселов.
- D7 Не используется.
Следующий рисунок иллюстрирует использование регистра предварительной установки горизонтальной развертки для вертикальной свертки содержимого экрана. В левой части рисунка показно начальное состояние экрана диспля, когда регистр содержит нулевое значение для битов D0-D4. Справа показан экран дисплея после увеличения значения регистра до трех. При этом изображение на экране дисплея сдвигается на три пиксела вверх, в результате чего часть верхней строки пропадает.
Рисунок 8.1 Плавная прокрутка экрана.
После установки режима работы видеоадаптера данный регистр содержит нулевое значение.
Высота сиволов текста
(Max Scan Line Register - MSLR) (индекс 9)
Этот регистр определяет количество линий сканирования на один символ или, другими словами, высоту символов в пикселах. Регистр используется только в текстовых режимах работы видеоадаптеров.
- D4-D0 Максимальная линия сканирования. Эти биты задают высоту символа в пикселах (см. рисунок 8.2 и 8.3).
- D5 Бит 9 регистра начала импульса гашения вертикальной развертки (SVBR - индекс 15h). Только для VGA.
- D6 Бит 9 регистра сравнения линий (LCR индекс 18h). Только для VGA.
- D7 Бит управления двойным сканированием. Поддерживается только адаптерами VGA. Если бит D7 равен единице, то в режимах с разрешением по вертикали 200 пикселов, для каждой линии растра применяется двойное сканирование, что фактически увеличивает разрешающую способность по вертикали до 400 пикселов.
На следующих двух рисунках показано использование регистра высоты символов текста. На первом рисунке, при использовании шрифта 8х8 пикселов, регистр высоты символов содержит число семь. Для второго рисунка, значение регистра равно тринадцати (используется шрифт 8х14). Как виднно из рисунков, значение регистра на один меньше, чем высота символов отображаемых на экране.
Рисунок 8.2 Изменение высоты символов текста.
Рисунок 8.3 Изменение высоты символов текста.
Начальная линия курсора
(Cursor Start Register - CSR) (индекс 0Ah)
Этот регистр является доступным как для чтения, так и для записи.
Регистр задает линию сканирования символа, в которой начинается курсор. Вместе с регистром конечной линии курсора (CER) он определяет размер и форму курсора.
D4-D0 Начальная линия курсора. (см. рисунок 8.4). D5 Бит гашения курсора. Реализован только на VGA. Если D5 содержит единицу, курсор гаснет. D7-D6 Не используются.
При установке режима работы видеоадаптера, BIOS загружает в регистр CSR следующие значения:
Режим | 0,1,2,3 | 4,5,6,D,E,F,10 | 7 |
Содержимое регистра | 06 | 00 | 0Bh |
Конечная линия курсора
(Cursor End Register - CER) (индекс 0Bh)
Этот регистр, также как и регистр 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(); }
Регистры начального адреса
Это группа из двух регистров: регистр старшего байта начального адреса (Start Address Register - SAR, high byte) (индекс 0Ch) и регистр младшего байта начального адреса (Start Address Register - SAR, low byte) (индекс 0Dh).
Регистры SAR содержат адрес данных видеопамяти, которые будут отображаться в верхнем левом углу экрана дисплея. Регистры начального адреса можно использовать для перемещения изображения по экрану (панорамирования) и для переключения активной страницы памяти.
Если вы хотите использовать регистры для переключения страниц видеопамяти, то в данные регистры надо записать смещение страницы, которую вы желаете отобразить на экране, относительно начала видеопамяти.
На рисунке 8.5 показано, как происходит панарамирование экрана при изменении регистров начального адреса. В верхней части рисунка регистры начального адреса содержат ноль. В этом случае видеопамять отображается на экране с начала. В нижней части значение регистров начального адреса увеличено до 77. Как видно из рисунка, в этом случае видеопамять отображается на экране начиная с данных, имеющих смещение 77 от начала видеопамяти. При этом снизу экрана возникает изображение, ранее не помещавщееся на экране.
Рисунок 8.5 Процесс панорамирования экрана.
Регистры начального адреса доступны для чтения и для записи. При установке режима работы видеоадаптера регистры обнуляются.
Регистры, определяющие положение курсора
Два регистра - регистр старшего байта позиции курсора (Cursor Location Register - CLR_h, high byte) (индекс 0Eh) и регистр младшего байта позиции курсора (Cursor Location Register - CLR_l, low byte) (индекс 0Fh) определяют положение курсора на экране (cм. рисунок 8.6). Регистры доступны как для записи, так и для чтения.
Рисунок 8.6 Отображение курсора на экране.
Программа, приведенная ниже считывает значения из регистров позиции курсора (на момент запуска программы) и отображает их на экране дисплея:
// чтение регистра положения курсора #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 ); }
Начало обратного вертикального хода луча (VRSR) (индекс 10h)
Регистр определяет начало обратного вертикального хода луча. Для EGA этот регистр содержит 9, а для VGA - 10 битов. Дополнительные биты расположены в регистре OVR.
Данный регистр доступен только для записи.
Конец обратного вертикального хода луча (VRER) (индекс 11h)
Данный регистр видеоадаптеров EGA и VGA доступен только для записи.
Регистр устанавливает конец обратного вертикального хода луча, а также выполняет некоторые другие функции.
D3-D0 Конец обратного вертикального хода луча. D4 Сброс вертикального прерывания. D5 Разрешения вертикального прерывания. D6 Изменение скорости регенирации экрана. (Только VGA.) D7 Защита от записи. (Только VGA.)
- D7 Этот бит позволяет решить некоторые проблеммы совместимости между VGA и видеоадаптерами, построенными на основе микросхемы 6845 (например CGA). Если бит D7 равен единице, то регистры контроллера ЭЛТ, имеющие индексы от 0 до 7, будут защищены от записи в них.
- D6 Если бит равен единице, то во время обратного горизонтального хода луча будет генерироваться пять циклов регенерации видеопамяти вместо обычных трех.?
- D5 Если бит равен нулю, то при каждом обратном вертикальном ходе луча на линии IRQ2 будет возникать прерывание. Сигнал прерывания сбрасывается записью нуля в бит D4 данного регистра.
- D4 Запись нуля в данный бит вызывает сброс вертикального прерывания и переустановку флага незаконченного вертикального прерывания.
- D3-D0 Когда значение этих битов поразрядно равны четырем младшим битам счетчика горизонтальных линий, сигнал обратного вертикального хода луча будет окончен.
Регистр адреса светового пера (LPAR)
Это 16-битовый регистр, который имеется в видеоадаптерах CGA и EGA, доступен только для чтения. Регистр LPAR дает возможность определить положение светового пера на экране. Регистр содержащий старший байт адреса светового пера имеет индекс 10h, а регистр содержащий младший байт - индекс 11h.
LPAR сохраняет адрес видеопамяти, которая регенерировалась в момент включения светового пера.
Завершение отображения вертикальной развертки (VDER) (индекс 12h)
Регистр определяет момент, когда заканчивается видемая часть вертикальной развертки и происходит гашение луча. Регистр содержит число, на единицу меньшее, чем количество горизонтальных линий растра.
Для видеоадаптера EGA регистр VDER содержит 9, а для VGA - 10 бит. Девятыи и десятый биты доступны через дополнительный регистр (OVR).
Логическая ширина экрана (OFR) (индекс 13h)
Регистр может быть использован для отображения большего, чем обычно, количества символов в строке. Например, для перевода видеоадаптера в режим отображения 132 симвов в строке.
В графических режимах регистр OFR задает логическую длину (в 16-битных словах или 32-битных двойных словах) горизонтальной линии развертки. Если линия num развертки начинается по адресу adr, то следующая линия развертки num+1 начинается по адресу adr+offset, где offset это значение регистра OFR.
В текстовых режимах регистр содержит смещение между соседними строками текста, заданное в 16-битных словах.
Использование регистраа OFR иллюстрируется рисунком 8.7. На верхней части рисунка видеоадаптер находится в стандартном текстовом режиме с разрешением 80 символов в строке. При этом значение регистра логической ширины экрана равно 40. На нижней части рисунка представлен результат увеличения содержимого регистра до 41. Логическая ширина экрана в этом случае увеличивается до 82 символов в строке. Последние два символа каждой строки не помещаются на экране. Для их отображения надо выполнить горизонтальную свертку экрана.
Рисунок 8.7 Логическая ширина экрана.
Положение подчеркивания символа (ULR) (индекс 14h)
Регистр ULR используется только в текстовых режимах. Он определяет положение подчеркивания символа. Подчеркивание предстовляет собой одну из линий в матрице символа. Подчеркивание отображается, если установлен атрибут подчеркивания. Отображение подчеркивания можно запретить, записав в регистр ULR величину большую, чем высота символов.
- D4-D0 Определяют положение подчеркивания символа (0-13).
- D5 Для VGA установка этого бита означает, что для каждого знакоместа счетчик адреса регенерации будет увеличиваться на 4 вместо 1.
- D6 Установка для VGA этого бита выбирает адресацию видеопамяти по двойным словам.
- D7 Не используется.
Программа, приведенная ниже, использует регистры контроллера ЭЛТ для перевода видеоадаптеров EGA и VGA в нестандартный текстовый режим, имеющий разрешение по вертикали 43 строки. Данная программа переводит видеоадаптер в текстовый режим с разрешением по вертикали 43 символа и затем отображает на экране диспля 43 строки текста.
#include <graph.h> void Set43Line(void); void main(void) { int i; // устанавливаем текстовый режим, принятый по умолчанию; // функция _setvideomode определена в графической библиотеке // трансляторов Microsoft Quick C 2.5 и C 6.0 _setvideomode(_DEFAULTMODE); // перепрограммируем видеоадаптер для отображения 43 строк Set43Line(); // выводим на экран дисплея 43 строки текста for(i = 0; i < 43; i++) printf("text line number %d\n", i); getch(); // восстанавливаем режим с 25 текстовыми строками _setvideomode(_DEFAULTMODE); } /** *.Name Set43Line * *.Title Установка текстового режима, использующего 43 строки. * *.Descr Переводит адаптеры EGA и VGA в режим отображения 43 * строк текста. * *.Proto void Set43Line(void) * *.Params Отсутствуют. * * *.Return Не используется. * *.Sample 43line.c **/ void Set43Line(void) { #define CHAR_SIZE 8 // новая высота символов _asm { ; устанавливаем регистр es на начало оперативной памяти xor ax,ax mov es,ax ; получаем адрес порта индексного регистра контроллера ЭЛТ ; (3B4h/3D4h), ; в монохромных режимах для адресации к индексному регистру ; используется порт с адресом 3B4h, а в цветных - порт 3D4h mov dx,es:[463h] ; выбираем для обмена регистр максимальной линии сканирования ; этот регистр задает высоту символов на экране дисплея mov al,9 out dx,al ; вычисляем адрес порта регистра данных контроллера ЭЛТ, ; в монохромных режимах для адресации к регистру данных ; используется порт с адресом 3B5h, а в цветных - порт 3D5h inc dx ; биты D4-D0, регистра максимальной линии сканирования содержат ; число, меньшее на единицу, чем высота символов в пикселах mov al,CHAR_SIZE-1 out dx,al ; вычисляем адрес порта индексного регистра контроллера ЭЛТ dec dx ; выбираем для обмена регистр положения подчеркивания mov al,14h out dx,al ; вычисляем адрес порта регистра данных контроллера ЭЛТ inc dx ; определяем положение подчеркивания символов mov al,CHAR_SIZE out dx,al ; вычисляем адрес порта индексного регистра контроллера ЭЛТ dec dx ; выбираем для обмена регистр завершения отображения ; вертикальной развертки ; регистр завершения отображения вертикальной развертки ; содержит восемь младших бит, определяющих число отображаемых ; горизонтальных линий растра минус один mov al,12h out dx,al ; вычисляем адрес порта регистра данных контроллера ЭЛТ inc dx ; для отображения 43 текстовых символов, при высоте символов ; 8 пикселов, необходимо иметь 43 * 8 = 344 горизонтальных ; линий растра ; помещаем в регистр завершения отображения вертикальной ; развертки младшие 8 бит числа 344 mov al,(43 * CHAR_SIZE - 1 - 256) out dx,al ; устанавливаем новые значения переменных BIOS ; число символов в строке равно восьмидесяти mov WORD PTR es:[44Ah],80 ; число строк текста минус один mov BYTE PTR es:[484h],(350/CHAR_SIZE)-1 ; высота символов в пикселах mov WORD PTR es:[485h],CHAR_SIZE ; загружаем нулевую таблицу знакогенератора, расположенную во втором ; цветовом слое, набором символов (размера 8х8 пикселов) из ПЗУ BIOS ; процесс загрузки шрифтов более подробно описан в разделе "Загрузка ; таблиц знакогенератора" из главы "Дополнительные средства BIOS для ; управлния EGA и VGA" mov ax,1112h xor bl,bl int 10h } }
Начало импульса гашения вертикальной развертки (SVBR) (byltrc 15h)
Регистр определяет момент начала гашения луча в прцессе вертикальной развертки.
Для EGA регистр имеет 9, а для VGA - 10 битов. Девятый бит и для EGA и для VGA расположен в дополнительном регистре (OVR). Десятый бит для VGA расположен в регистре высоты символов текста (MSLR).
Конец импульса гашения вертикальной развертки (EVBR) (индекс 16h)
В момент, когда младшие 5 битов регистра для EGA или все 8 битов для VGA равны счетчику горизонтальных линий, заканчивается сигнал гашения вертикальной развертки.
Управление режимом (MCR) (индекс 17h)
Регистр содержит набор битов, управляющих контроллером ЭЛТ.
- D7 Если бит равен нулю, то горизонтальный и вертикальный обратный ход луча невозможен.
- D6 Если данный бит равен единице, то установлен байтовый режим, а если он равен нулю - двух-байтовый. Двух-байтовый режим поддерживает разделение данных между двумя цветовыми слоями. VGA дополнительно поддерживает четырех-байтовый режим (см. регистр ULR).
D6 D5 | 1х | 00 | 01 |
MA0 | MA13 | MA15 | |
MA1 | MA0 | MA0 | |
MA2 | MA1 | MA1 | |
MA3 | MA2 | MA2 | |
MA4 | MA3 | MA3 | |
MA5 | MA4 | MA4 | |
MA6 | MA5 | MA5 | |
MA7 | MA6 | MA6 | |
MA8 | MA7 | MA7 | |
MA9 | MA8 | MA8 | |
MA10 | MA9 | MA9 | |
MA11 | MA10 | MA10 | |
MA12 | MA11 | MA11 | |
MA13 | MA12 | MA12 | |
MA14 | MA13 | MA13 | |
MA15 | MA14 | MA14 |
Таблица 8.11 Преобразование адреса.
Бит D5 равен нулю только для видеоадаптеров EGA с объемом видеопамяти 64К байт. При этом происходит сцепление слоев в графических режимах с высоким разрешением.
- D4 Если бит равен единице, то все выходные линии контроллера ЭЛТ переводятся в третье состояние. Этот бит используется только при тестировании видеоадаптера.
- D3 Если бит равен нулю, то счетчик адреса регенерации изображения увеличивается на единицу на каждое знакоместо экрана, а если бит равен единице, то на каждые два знакоместа.
- D2 Бит может использоваться для увеличения в два раза вертикальной разрешающей способности. Если бит равен нулю, то счетчик числа линий экрана увеличивается после каждого обратного горизонтального хода луча, а если бит равен единице, то после каждых двух.
- D1 Используется при эмуляции графических режимов видеоадаптера Hercules. Запись в этот бит нуля приводит к замещению бита D14 адресного регистра битом D1 из регистра счетчика горизонтальных строк.
- D0 Используется при эмуляции графических режимов CGA. Запись в этот бит нуля приводит к выделению в видеопамяти двух областей по 8 Кбайт. Одна содержит даннные для четных, а другая для нечетных строк экрана. Это достигается путем замещения бита D13 адресного регистра битом D0 из регистра счетчика горизонтальных строк.
Регистр сравнения линий (Line Compare Register - LCR) (индекс 18h)
Обеспечивает разделение экрана на две независимые части. При этом одну из них можно свертывать, содержимое другой части экрана остается на месте.
Данный регистр используют совместно с регистром начального адреса. Когда счетчик горизонтальных линий сканирования достигает значения, записанного в регистре LCR, происходит сброс счетчика адреса регенерируемой видеопамяти в ноль. В результате экран разбивается на две части, где в верхней отображаются данные, на которые указывает регистр начального адреса, а в нижней - данные, находящиеся в начале видеопамяти. На рисунке 8.8 иллюстрируется процесс разделения экрана:
Рисунок 8.8 Процесс разделения экрана.
Содержимое верхнего окна можно перемещать, изменяя содержимое регистра начального адреса.
Заметим, что у видеоадаптера EGA регистр сравнения линий состоит из 9 бит. Доступ к девятому биту возможен через дополнительный регистр (OVR) контроллера ЭЛТ. Видеоадаптер VGA имеет дополнительно еще и десятый бит, расположенный в регистре MSLR.
При изменении режима работы видеоадаптера, BIOS записывает в регистр сравнения линий значение 0FFh.
Следующая программа выводит на экран дисплея 25 строк текста, а затем, после нажатия любой клавиши, разделяет экран на две части.
// пример разделения экрана дисплея на две части при помоши // регистра сравнения линий контроллера ЭЛТ #include <dos.h> #include <stdio.h> void Split(unsigned); void main(void) { int i; // выводим на экран дисплея 25 строк текста for(i = 0; i < 25; i++) printf("Строка номер %d.",i); getch(); // разделяем экран по линии 200 Split(200); getch(); // после завершения программы // значения регистров не восстанавливаются! } /** *.Name Split * *.Title Разделение экрана. * *.Descr Функция разделяет экран на две части. Функция работает * только на EGA и VGA. * *.Proto void Split(unsigned split_line) * *.Params unsigned split_line - линия горизонтальной развертки, * в которой происходит разделение экрана дисплея. * *.Return Не используется. * *.Sample split.c **/ void Split(unsigned split_line) { _asm { ; устанавливаем регистр es на начало оперативной памяти xor ax,ax mov es,ax ; получаем адрес порта индексного регистра контроллера ЭЛТ ; (3B4h/3D4h), ; в монохромных режимах для адресации к индексному регистру ; используется порт с адресом 3B4h, а в цветных - порт 3D4h mov dx,es:[463h] ; вычисляем адрес порта регистра состояния 1, ; в монохромных режимах для адресации к регистру состояния 1 ; используется порт с адресом 3BAh, а в цветных - порт 3DAh add dx,6 ; ожидаем начало обратного вертикального хода луча in al,dx nop ; если бит D3 равен единице, то происходит обратный ; вертикальный ход луча test al,8 jz wait_on wait_off: in al,dx ; задержка nop test al,8 jnz wait_off wait_on: in al,dx nop test al,8 jz wait_on ; вычисляем адрес порта индексного регистра контроллера ЭЛТ ; (3B4h/3D4h) sub dx,6 ; выбираем для обмена регистр сравнения линий mov al,18h out dx,al ; вычисляем адрес порта регистра данных контроллера ЭЛТ, ; в монохромных режимах для адресации к регистру данных ; используется порт с адресом 3B5h, а в цветных - порт 3D5h inc dx ; определяем линию горизонтальной развертки, в которой происходит ; разделение экрана дисплея mov ax,split_line ; у видеоадаптера EGA регистр сравнения линий состоит из 9 бит, ; доступ к девятому биту происходит через дополнительный регистр ; контроллера ЭЛТ; ; видеоадаптер VGA имеет еще и десятый бит, расположенный в регистре ; высоты символов текста ; записываем младшие 8 битов в регистр сравнения линий out dx,al ; вычисляем адрес порта индексного регистра контроллера ЭЛТ dec dx ; вызываем функцию чтения конфигурации видеосистемы, ; данная функция подробно описана в главе ; "Дополнительные средства BIOS для управлния EGA и VGA" mov ax,1A00h int 10h ; если после вызова функции регистр al не равен 1Ah, то используемый ; видеодаптер не VGA cmp al,1Ah je vga jmp ega vga: ; считываем в al состояние дополнительного регистра mov al,7 out dx,al inc dx in al,dx ; модифицируем бит D4 дополнительного регистра mov bx,split_line mov cl,4 shl bh,cl and bh,00010000b and al,11101111b or al,bh out dx,al ; сбрасываем бит D6 регистра высоты символов текста dec dx mov al,9 out dx,al inc dx in al,dx and al,10111111b out dx,al jmp quit_split ega: mov bx,split_line mov cl,4 shl bh,cl and bh,00010000b cmp dx,3B4h ; монохромный режим? je default_1Fh ; если да, то переходим ; на метку default_1Fh ; определяем наличие улучшенного цветного дисплея по положению ; переключателей на плате EGA mov al,es:[488h] and al,0Fh ; положение переключателей "off off on on" ? cmp al,3 je default_1Fh ; положение переключателей "off on on off" ? cmp al,9 je default_1Fh ; для видеосистем с монохромным или цветным дисплеями, ; дополнительный регистр по умолчанию содержит 11h or bh,1 jmp set_overflow ; для видеосистем с улучненным цветным дисплеем или в монохромных ; текстовых режимах дополнительный регистр по умолчанию содержит ; значение 1Fh default_1Fh: or bh,0Fh ; устанавливаем дополнительный регистр set_overflow: mov al,07h out dx,al inc dx mov al,bl out dx,al quit_split: } }
7.4. Регистры синхронизатора
Синхронизатор управляет всеми временными
параметрами видеоадаптера, а также разрешением и
запрещением доступа к отдельным цветовым слоям.
Синхронизатор имеет пять регистров, они
перечислены в таблице 8.12. У видеоадаптера EGA все
пять регистров доступны только для записи, а у VGA
и Super VGA также и для чтения.
Индекс регистра | Регистр синхронизатора |
0 | регистр сброса синхронизатора (Reset Register - RR) |
1 | регистр режима синхронизации (Clock Mode Register - CMR) |
2 | регистр разрешения записи цветового слоя (Color Plane Write Enable Register - CPWER) |
3 | регистр выбора знакогенератора (Character Generator Select Register - CGSR) |
4 | регистр определения структуры памяти (Memory Mode Register - MMR) |
Таблица 8.12 Регистры синхронизатора.
Доступ к регистрам осуществляется через индексный порт с адресом 3C4h и через порт данных с адресом 3C5h.
Как и в случае описания регистров контроллера ЭЛТ мы будем подробно рассказывать только о безопасных и наиболее полезных регистрах синхронизатора.
Регистр сброса синхронизатора (Reset Register - RR) (индекс 0)
Если регистр переведен в состояние сброса, то все процессы видеоадаптера приостанавливаются. В результате могут быть разрушены данные в видеопамяти.
- D0 Бит асинхронного сброса. После записи в этот бит нуля происходит немедленный сброс и остановка синхронизатора. В результате могут быть потеряны видеоданные.
- D1 Бит синхронного сброса. Нулевое значение сбрасывает и останавливает синхронизатор в конце исполняемого цикла.
- D7-D2 Не используются.
Для нормальной работы видеоадаптера биты D0 и D1 должны быть равны единице. Перед доступом к регистру режима синхронизации синхронизатор должен быть переведен в состояние синхронного сброса (бит D1 равен 0).
Регистр режима синхронизации (Clock Mode Register - CMR) (индекс 1)
Регистр управляет временными циклами синхронизатора. При изменении его содержимого необходимо соблюдать осторожность. Изменяя отдельные биты регистра, сохраняйте значения остальных битов.
Перед модификацией регистра CMR надо сбросить бит D1 в регистре сброса синхронизатора, переведя таким образом синхронизатор в режим сброса и остановки.
- D0 Бит задает ширину символов в текстовых монохромных режимах с разрешением 720 пикселов по горизонтали. Если бит равен нулю, то ширина матрицы символов равна 9 пикселов, если единице - 8 пикселов.
- D1 Бит используется EGA для определения числа
циклов, используемых процессором, для доступа к
видеопамяти . При D1
равном единице, процессор может получить три из каждых пяти циклов, а при D1 равном нулю - только один из пяти циклов. Остальные циклы используются адаптером для обновления экрана. - D4-D2 Не используются.
- D5 Для VGA: если этот бит равен единице, то экран гаснет и процессор получает монополию на доступ к видеопамяти. Это несколько ускоряет процесс обмена процессора с видеопамятью.
- D7-D6 Не используются.
Ниже приведены значения регистра CMR,
устанавливаемые BIOS при установке режима работы
адаптера:
Режим | 00,01,04,05,0Dh | 02,03,06,0Eh | 0Fh,10h |
Содержимое регистра | 0Bh | 01 | 05 |
Регистр разрешения записи цветового слоя
(Color Plane Write Enable - CPWE) (индекс 2)
При помощи данного регистра можно запретить запись процессором данных в любые цветовые слои видеопамяти. На рисунке 8.9 показан механизм запрещения записи данных в отдельные слои видеопамяти. Рассмотрим процесс записи данных процессором в видеопамять:
- ПЕРВЫЙ ШАГ. Процессор передает видеоадаптеру данные для записи в видеопамять. Они проходят через графическиий контроллер и попадают в синхронизатор. Графический контроллер производит над записываемыми в видеопамять данными операции, определяемые состоянием его регистров (смотри главу "Исполнение видеоадаптером операции записи" из раздела "Графический контроллер").
- ВТОРОЙ ШАГ. Синхронизатор записывает поступившие ему данные в видеопамять в соответствии с содержимым регистра разрешения записи цветового слоя. Регистр разрешения записи цветового слоя содержит четыре бита, управляющие записью в цветовые слои видеопамяти. Если бит этого регистра, управляющий цветовым слоем равен нулю, то данный цветовой слой не изменяется. Если бит регистра равен единице, то в данный слой видеопамяти записываются значения, поступившие от графического контроллера.
Рисунок 8.9 Разрешение записи в цветовые слои.
Биты регистра разрешения записи цветового слоя имеют следующие значения:
- D0 Если бит равен единице, то можно записывать данные в нулевой цветовой слой.
- D1 Если бит равен единице, то можно записывать данные в первый цветовой слой.
- D2 Если бит равен единице, то можно записывать данные в второй цветовой слой.
- D3 Если бит равен единице, то можно записывать данные в третий цветовой слой.
- D7-D4 Не используются.
При установке режима работы адаптера BIOS
загружает в регистр CPWE следующие значения:
Режим | 0,1,2,3,4,5,7 | 6 | D,E,F,10 |
Содержимое регистра | 03 | 01 | 0Fh |
Регистр выбора знакогенератора (Character Generator Select Register - CGSR) (индекс 3)
Видеоадаптер EGA позволяет загрузить в память четыре, а VGA - восемь таблиц знакогенератора, каждая из которых опрделяет 256 символов.
Одновременно могут использоваться символы одной или двух таблиц знакогенератора. Это позволяет отображать до 512 различных символов.
Если разрешено одновременное использование двух различных таблиц знакогенератора, то бит D3 байта атрибутов определяет какая таблица будет использоваться при отображении символа с этим атрибутом.
Регистр выбора знакогенератора определяет два набора символов, расположенных во втором цветовом слое, символы которых могут одновременно отображаться на экране. Данный регистр используется только в текстовых режимах.
- D1-D0 Выбор таблицы знакогенератора, используемой адаптерами EGA/VGA при выводе символа на экран, когда бит D3 байта атрибутов символа сброшен в ноль.
- D3-D2 Выбор таблицы знакогенератора, используемой адаптерами EGA/VGA при выводе символа на экран, когда бит D3 байта атрибутов символа установлен в единицу.
- D4 Выбор таблицы знакогенератора, используемой адаптером VGA при выводе символа на экран, когда бит D3 байта атрибутов символа сброшен в ноль.
- D5 Выбор таблицы знакогенератора, используемой адаптером VGA при выводе символа на экран, когда бит D3 байта атрибутов символа установлен в единицу.
- D7-D6 Не используются.
Для выбора активных (используемых в данный
момент для отображения символов) таблиц
знакогенератора надо установить биты D0-D5 в
соответствии со следующей таблицей:
D5 D3 D2 | Номер таблицы знакогенератора, используемой если бит D3 байта атрибутов равен 1 |
D4 D1 D0 | Номер таблицы знакогенератора, используемой если бит D3 байта атрибутов равен 0 |
0 0 0 | первая таблица знакогенератора |
0 0 1 | вторая таблица знакогенератора |
0 1 0 | третья таблица знакогенератора |
0 1 1 | четвертая таблица знакогенератора |
1 0 0 | пятая таблица знакогенератора (VGA) |
1 0 1 | шестая таблица знакогенератора (VGA) |
1 1 0 | седьмая таблица знакогенератора (VGA) |
1 1 1 | восьмая таблица знакогенератора (VGA) |
Таблица 8.13 Выбор таблиц знакогенератора.
Если нужна только одна активная таблица знакогенератора, то значеня битов D5 D3 D2 и битов D4 D1 D0 должны совпадать.
Для установки номеров активных таблиц знакогенератора рекомендуется использовать соответствующую функцию BIOS.
Регистр определения структуры памяти (Memory Mode Register - MMR) (индекс 4)
Регистр инициализируется BIOS при выполнении операции выбора режима работы видеоадаптера и определяет структуру видеопамяти в этом режиме.
- D0 Для EGA бит устанавливается в единицу, при использовании в текстовом режиме функции выбора знакогенератора. Для VGA этот бит обычно сброшен в ноль.
- D1 Для EGA данный бит равен единице, если объем видеопамяти больше 64К байт.
- D2 Если D2 содержит ноль, то доступ по четным адресам происходит к нулевому цветовому слою, а по нечетным - к первому.
- D7-D3 Не используются.
При выборе режима работы адаптера, BIOS загружает
в регистр CPWE следующие значения:
Режим | 0,1,2,3,7 | 4,5 | 6,0Dh,0Eh | 0Fh,10h |
Содержимое регистра | 03 | 02 | 06 | 00 |
7.5. Регистры графического контроллера
Как мы уже указывали, графический контроллер поддерживает обмен данными между процессором и видеопамятью. При этом он может выполнять простейшие логические операции над записываемыми в видеопамять данными. Грфический контроллер передает также данные из цветовых слоев видеопамяти - контроллеру атрибутов в случае использования графического режима работы видеоадаптера.
Графический контроллер содержит девять регистров. Обращение к ним происходит через индексный порт с адресом 3CEh и порт данных с адресом 3CFh. Список регистров приведен в таблице 8.14.
Адаптер EGA имеет еще два порта с адресами 3CAh и
3CCh, используемых при инициализации
видеоадаптера.
Индекс регистра | Регистр графического контроллера |
0 | регистр установки/сброса (Set/Reset Register - SRR) |
1 | регистр разрешения установки/сброса (Set/Reset Enable Register - SRER) |
2 | регистр сравнения цветов (Color Compare Register - CCR) |
3 | регистр циклического сдвига и выбора функции (Data Rotate & Function Select - DRFS) |
4 | регистр выбора читаемого слоя (Read Plane Select Register - RPSR) |
5 | регистр режима работы (Mode Register - MDR) |
6 | регистр смешанного назначения (Miscellaneous Register - MIR) |
7 | регистр маскирования цветовых слоев (Color Don't Care Register - CDCR) |
8 | регистр битовой маски (Bit Mask Register - BMR) |
Таблица 8.14 Регистры графического контроллера.
Большинство регистров графического контроллера могут использоваться при программировании, поэтому регистры графического контроллера будут описаны полностью.
Ниже, на рисунке 8.10, демонстрируются функции, выполняемые графическим контроллером. Рассмотрм функционирование графического адаптера.
Байт, записываемый процесором в видеопамять (11100001b), поступает в графический контроллер. В соответствии со значением регистра циклического сдвига и выбора функции, происходит циклический сдвиг на один бит содержимого записываемого в видеопамять байта. Затем результат складывается по логике ИЛИ с содержимым регистров-защелок. Какая булева функция используется - ИЛИ, И, ИСКЛЮЧАЮЩЕЕ ИЛИ также определяется регистром циклического сдвига и выбора функции.
Дальнейшие преобразования происходят в соответствии со значениями регистра разрешения установки/сброса и регистра установки/сброса:
- Если бит регистра разрешения установки/сброса, управляющий данным цветовым слоем равен нулю, то байт, записываемый в видеопамять не изменяется.
- Если бит регистра разрешения установки/сброса, управляющий данным цветовым слоем равен единице, то в него записывается байт, все биты которого устанавливаются в соответствии со значением регистра установки/сброса для данного цветового слоя.
Затем в соответствии с состоянем регистра битовой маски происходит запись данных в видеопамять:
- Если данный бит регистра битовой маски содержит единицу, то соответствующие биты для каждого из цветовых слоев поступают из видеопамяти.
- Если данный бит регистра битовой маски содержит ноль, то соответствующие биты для каждого из цветовых слоев поступают от регистров-защелок.
Рисунок 8.10 Функции графического контроллера.
Теперь рассмотрим регистры графического контроллера более подробно.
Регистр установки/сброса
(Set/Reset Register - SRR) (индекс 0)
Использовав данный регистр совместно с регистром разрешения установки/сброса (Set/Reset Enable Register), можно определить данные, размещаемые в цветовых слоях видеопамяти при выполнении процессором записи любых данных в видеопамять. Данные процессора при этом игнорируются.
Приведем формат регистра установки/сброса:
- D0 Данные, записываемые в цветовой слой 0.
- D1 Данные, записываемые в цветовой слой 1.
- D2 Данные, записываемые в цветовой слой 2.
- D3 Данные, записываемые в цветовой слой 3.
- D7-D4 Зарезервировано.
По умолчанию во все биты регистра записываются нулевые значения.
Возможности использования данного регистра разъясняются при описании регистра разрешения установки/сброса.
Регистр разрешения установки/сброса
(Set/Reset Enable Register - SRER) (индекс 1)
Регистр разрешения установки/сброса позволяет при операции записи в видеопамять для одних цветовых слоев использовать данные от процессора, а для других - из регистра установки/сброса (см. рисунок 8.11).
Если биты регистра, управляющие цветовыми слоями, содержат единицы, то при выполнении операции записи, в соответствующие цветовые слои записывается информация из регистра установки/сброса. В остальные слои видеопамяти заносятся данные от процессора.
Теперь приведем формат регистра разрешения установки/сброса:
- D0 Разрешение использования данных из регистра установки/сброса для цветового слоя 0.
- D1 Разрешение использования данных из регистра установки/сброса для цветового слоя 1.
- D2 Разрешение использования данных из регистра установки/сброса для цветового слоя 2.
- D3 Разрешение использования данных из регистра установки/сброса для цветового слоя 3.
- D7-D4 Зарезервированно.
По умолчанию во все биты регистра записываются нулевые значения.
Заметим, что возможность использования регистров установки/сброса можно реализовать только в нулевом режиме записи. Режим записи устанавливается регистром режима работы графического контроллера (Mode Register, индекс 5). В нулевом режиме записи, если запрещено выполнение операции маскирования пикселов (регистр битовой маски содержит значение 0FFh), то каждый байт, записываемый процессором в видеопамять определяет параметры 8 пикселов в одном или нескольких цветовых слоях. Более подрбное описание регистра режима работы графического контроллера и регистра битовой маски приведено ниже.
Рассмотрим на рисунке 8.11 применение регистров установки/сброса. Пусть графический контроллер находится в нулевом режиме работы, и регистр битовой маски равен 0FFh (используются только данные от процессора). В этом случае можно использовать регистры установки/сброса.
Допустим, что после преобразования данных, записываемых процессором в видеопамять, в соответствии со значением регистра циклического сдвига и выбора функций, данные имеют следующий вид:
- байт 11110000b передается в третий слой видеопамяти,
- байт 00000011b передается во второй слой видеопамяти,
- байт 00110011b передается в первый слой видеопамяти,
- байт 00110011b передается в нулевой слой видеопамяти.
Данные, непосредственно поступающие в видеопамять зависят от значения регистра разрешения установки/сброса. Биты D3 и D0, регистра разрешения установки/сброса равны нулю, поэтому в третий слой и нулевой слой видеопамяти данные заносятся без изменения. Биты D2 и D1 регистра разрешения установки/сброса равны единице, значит во второй и первый слои видеопамяти записываются данные в соответствии со значением битов D2 и D1 регистра установки/сброса. То есть во второй слой записывается байт 00000000b, а в первый - 11111111b.
Рисунок 8.11 Использование регистров установки/сброса.
Регистр сравнения цветов
(Color Compare Register - CCR) (индекс 2)
Регистр CCR используется программами, осуществляющими поиск на экране пикселов с определенным цветом. Без использования регистра CCR за один цикл чтения видеопамяти процессор может считать данные только из одного цветового слоя. Программирование данного регистра позволяет за один цикл чтения произвести чтение всех четырех цветовых слоев, сравнение считанных значений с искомыми и возвращение результата.
Ниже приведен формат регистра сравнения цветов:
- D0 Искомая величина для нулевого цветового слоя.
- D1 Искомая величина для первого цветового слоя.
- D2 Искомая величина для второго цветового слоя.
- D3 Искомая величина для третьего цветового слоя.
- D7-D4 Не используются.
После выполнения BIOS устаноки режима работы видеоадаптера все биты регистра содержат нулевые значения.
Операция поиска пикселов данного цвета иллюстрируется рисунком 8.12.
Рисунок 8.12 Использование регистра CCR.
Как видно из рисунка, в случае совпадения сравниваемых битов соответствующий бит результата равен единице.
Заметим, что перед использованием регистра CCR для операции поиска пикселов определенного цвета необходимо установить регистр режима работы (Mode Register - MDR) и регистр маскирования цветовых слоев (Color Don't Care Register - CDCR), описанные ниже.
Регистр циклического сдвига и выбора функции
(Data Rotate & Function Select - DRFS) (индекс 3)
Регистр DRFS выполняет две различные функции, отраженные в его названии:
- Циклический сдвиг данных, записываемых процессором в видеопамятять.
- Выполнение над записываемыми в видеопамять данными и содержимым регистров-защелок некоторых логических операций.
- D2-D0 Счетчик сдвига.
- D4-D3 Биты выбора логической функции.
- D7-D5 Не используются.
После выполнения BIOS установки режима работы видеоадаптера биты регистра DRFS содержат нулевые значения.
При выполнении операции циклического сдвига
биты счетчика сдвига могут иметь следующие
значения. Чтобы разрешить операцию циклического
сдвига надо использовать нулевой режим записи.
D2 D1 D0 | Данные циклически сдвигаются вправо на следующее количество битов |
0 0 0 | ноль, сдвиг не происходит |
0 0 1 | один бит |
0 1 0 | два бита |
0 1 1 | три бита |
1 0 0 | четыре бита |
1 0 1 | пять битов |
1 1 0 | шесть битов |
1 1 1 | семь битов |
Таблица 8.15 Циклический сдвиг.
Теперь рассмотрим возможности графического контроллера по выполнению логических операций над записываемыми в видеопамять данными.
Во время выполнения процессором операции
чтения из видеопамяти одновременно происходит
запись данных из всех четырех цветовых слоев (по
считываемому адресу) в регистры-защелки. Каждому
цветовому слою видеопамяти соответствует один
8-битовый регистр-защелка. Когда процессор начнет
записывать в видеопамять (возможно уже по
другому адресу) данные, можно комбинировать их с
данными из регистров-защелок. Вид выполняемой
логической операции будет зависеть от
содержимого битов выбора логической функции
(таблица 8.16):
D4 D3 | Выполняемая логическая операция |
0 0 | запись немодифицированных данных |
0 1 | И |
1 0 | ИЛИ |
1 1 | ИСКЛЮЧАЮЩЕЕ ИЛИ |
Таблица 8.16 Возможные логические операции.
Следует отметить, что операция циклического сдвига выполняется до выполнения логических функций.
Регистр DRFS можно использовать для быстрого копирования областей видеопамяти с возможной их модификацией.
Рисунок 8.13 иллюстрирует выполнение логической операции ИЛИ. Регистр циклического сдвига и выбора функции содержит число 00010000b. После операции чтения данные из всех четырех слоев записываются в регистрах-защелках. Затем выполняется операция записи. При этом данные процессора в соответствии с состоянием регистра циклического сдвига и выбора функции складываются по логике ИЛИ со значением регистров-защелок и помещаются в видеопамять.
Рисунок 8.13 Логические операции и операция циклического сдвига.
Заметим, что логические операции можно производить только в нулевом и втором режиме записи.
Регистр выбора читаемого слоя
(Read Plane Select Register - RPSR) (индекс 4)
Определяет номер цветового слоя видеопамяти, из которого процессор может читать данные. Заметим, что при выполнении операции сравнения цветов значение этого регистра безразлично.
Приведем формат регистра выбора читаемого слоя.
- D1-D0 Номер читаемого цветового слоя видеопамяти.
- D7-D2 Не используются.
При установке режима работы видеоадаптера BIOS заполняет все биты регистра нулями, что соответствует нулевому цветовому слою.
Операция чтения видеопамяти процессором иллюстрируется на рисунке 8.14. На этом рисунке регистр выбора читаемого слоя разрешает чтение второго слоя видеопамяти. Таким образом при чтении процессором данных из видеопамяти, процессор считывает данные только из второго слоя. Остальные слои будут недоступны для чтения процессором, пока вы не измените состояние регистра читаемого слоя.
Рисунок 8.14 Операция чтения из видеопамяти.
Регистр режима работы
(Mode Register - MDR) (индекс 5)
Регистр управляет несколькими различными функциями графического контроллера. В частности он управляет режимом записи в видеопамять, а также разрешением режима сравнния цветов (см. регистр сравнения цветов графического контроллера).
D1-D0 Режим записи. D2 Не используется. D3 Разрешение режима сравнения цветов. D4 Четный/нечетный режим. D5 Режим регистра сдвига. D6 Управление режимом VGA с 256 цветами. D7 Не используется.
Ниже подробно рассмотрены отдельные биты регистра. Мы не рекомендуем изменять состояние битов D4-D7, так как это может привести к потере изображения на экране дисплея.
- D1, D0 Данные биты определяют режим записи в видеопамять. Возможно использование трех различных режимов записи:
D1 D0 | Номер режима | Режим записи |
0 0 | 0 | режим непосредственной записи |
0 1 | 1 | использование для записи регистров-защелок |
1 0 | 2 | заполнение N-ого цветового слоя битом номер N из данных, записываемых процессором |
1 1 | - | не используется |
- Режим 0 - режим непосредственной записи. Процессор имеет доступ к видеопамяти и возможно использование следующих операциий: установки/сброса, циклического сдвига и всех логических функций. В этом режиме также возможно использование регистра битовой маски.
- Режим 1 - режим записи, использующий регистр-защелку. При чтении данных из видеопамяти происходит запись восьми битов из каждого цветового слоя в регистры-защелки. Затем, при выполнении операции записи содержимое регистров-защелок может быть записано обратно в видеопамять, но уже по другому адресу. Этот режим полезно использовать для быстрого копирования данных из одной области видеопамяти в другую.
- Режим 2. В этом режиме происходит заполнение N-ого цветового слоя битом с порядковым номером N из байта данных, переданного процессором видеоадаптеру для записи. Отсюда следует, что содержимое четырех старших битов записываемого байта (то есть битов D4-D7) значения не имеет.
Процесс записи в видеопамять в каждом из перечисленных выше режимов показан на рисунке 8.14.
Рисунок 8.14 Различные режимы записи в видеопамять.
- D3 Этот бит управляет разрешением использования режима сравнения цветов (см. регистр сравнения цветов графического контроллера). Для перевода видеоадаптера в режим сравнения цветов бит D3 должен содержать единицу.
Остальные биты регистра модифицировать не рекомендуется.
- D4 Данный бит устанавливается в текстовых режмимах. При этом доступ по четным адресам происходит к четным цветовым слоям, а по нечетным адресам - к нечетным цветовым слоям видеопамяти (см. видеопамять в текстовых режимах).
- D5 Используется в режимах 4 и 5 для обработки видеоданных в формате "два бита на пиксел".
- D6 Используется VGA в режиме с 256 цветами (режим 13h).
При установке режима работы видеоадаптера BIOS
загружает в регистр MDR следующие значения, в
зависимости от режима работы видеоадаптера:
Режим | 0,1,2,3,7,F,10 | 4,5 | 6,D,E |
Содержимое регистра | 10h | 30h | 00 |
Регистр смешанного назначения
(Miscellaneous Register - MIR) (индекс 6)
Регистр управляет видеопамятью и регистром-защелкой для адреса знакогенератора. В результате неправильной модификации регистра возможна неправильная работа некоторых функций BIOS и конфликты между видеоадаптерами в системе с двумя дисплеями.
- D0 Бит разрешения графического режима. Бит должен содержать 1 для графического и 0 для текстового режимов. В графическм режиме запрещается генерация символов и разрешается адресация к отдельным пикселам.
- D1 Используется видеоадаптерами EGA, имеющими 64К байт памяти. Если бит установлен, то четыре 16К байтных слоя объединяются в два слоя по 32К байт.
- D3-D2 Эти биты устанавливают начальный и конечный
адреса, на которые отображается видеопамять
адаптера EGA согласно следующей таблице:
D3 D2 адреса видеопамяти
0 0 A000:0000-B000:FFFF
0 1 A000:0000-A000:FFFF
1 0 B000:0000-B000:7FFF
0 1 B800:0000-B000:FFFF - D7-D4 Не используются.
При установке режима работы видеоадаптера BIOS
загружает в регистр MIR следующие значения, в
зависимости от режима работы видеоадаптера:
Режим | 3 | 7 | F | 10 |
Содержимое регистра | Eh | Ah | 07 | 05 |
Регистр маскирования цветовых слоев
(Color Don't Care Register - CDCR) (индекс 7)
Регистр используется в режиме сравнения цветов (см. регистр сравнения цветов - CCR). Если какие-либо биты D3-D0 содержат ноль, то при операции сравнения цветов соответствующие цветовые слои в рассмотрение не принимаются.
- D0 Управление нулевым цветовым слоем.
- D1 Управление первым цветовым слоем.
- D2 Управление вторым цветовым слоем.
- D3 Управление третим цветовым слоем.
- D7-D4 Не используются.
При установке режима работы в регистр
заносятся следующие значения:
Режим | 3 | 7 | F | 10 |
Содержимое регистра | 00 | 00 | 0Fh | 0Fh |
Регистр битовой маски
(Bit Mask Register - BMR) (индекс 8)
Регистр управляет записью данных в видеопамять. Если какой-то бит регистра BMR содержит ноль, то соответствующий бит будет записываться в видеопамять из регистра-защелки. В противном случае данный бит поступает от процессора (см. рисунок 8.15). Этот регистр используется только в нулевом режиме записи.
Рисунок 8.15 Использование регистра битовой маски.
Напомним, что занести данные в регистр-защелку можно, если выполнить операцию чтения из видеопамяти. При этом в каждый регистр-защелку считывается один байт из соответствующего цветового слоя.
По умолчанию, во всех режимах регистр хранит число 0FFh.
7.6. Регистры контроллера атрибутов
Контроллер атрибутов управляет цветовыми характеристиками изображений.
Контроллер атрибутов содержит двадцать один регистр. Регистры перечисленны в таблице 8.17. Доступ к ним осуществляется через один порт - 3C0h (в отличие от предыдущих рассмотренных нами регистров). Этот порт совмещает в себе функции индексного порта и порта данных, регулируемые внутренним триггером. Триггер переключается при каждой операции записи в порт и записываемые данные воспринимаются либо как индекс регистра, либо как данные для обмена с регистром.
Установить триггер в исходное состояние можно,
выполнив чтение из порта 3BAh для монохромного
режима или из порта 3DAh - для цветного режима
работы видеоадаптера. После установки триггера
данные, записываемые в регистр 3C0h, будут
восприниматься, как индекс регистра.
Индекс | Регистры контроллера атрибутов |
0 - 0Fh | регистры цветовой палитры (0-15) (Color Palette Register's - CPR) |
10h | регистр управления режимом (Mode Control Register - MCR) |
11h | регистр цвета рамки экрана (Screen Border Color Register - SBCR) |
12h | регистр разрешения цветового слоя (Color Plane Enable Register - CPER) |
13h | регистр горизонтального панорамирования (Horizontal Panning Register - HPR) |
14h | регистр выбора цвета (Color Select Register - CSR) |
Таблица 8.17 Регистры контроллера атрибутов.
Регистры цветовой палитры (0-15)
(Color Palette Register's - CPR)
Четыре цветовых слоя видеоадаптера EGA позволяют закодировать 16 различных цветов, однако улучшенный цветной дисплей обеспечивает возможность отображения 64 цветов.
16 регистров цветовой палитры предоставляют возможность выбора любых 16 цветов из 64 возможных, которые будут использоваться видеоадаптером EGA в данный моент.
При использовании улучшенного цветного дисплея каждый регистр цветовой палитры содержит шесть битов, соответствующих шести линиям управления дисплея.
Другие дисплеи - цветной (CD) и монохромный (MD), имеют меньшее число линий управления и регистр цветовой палитры также имеет другой формат.
Форматы регистров цветовой палитры для различных дисплеев приведены ниже:
Улучшенный цветной дисплей.
- D0 Голубой.
- D1 Зеленый.
- D2 Краснй.
- D3 Второй голубой.
- D4 Второй зеленый.
- D5 Второй красный.
- D7-D6 Не используются.
Цветной дисплей.
- D0 Голубой.
- D1 Зеленый.
- D2 Краснй.
- D3 Не используется.
- D4 Интенсивность.
- D7-D5 Не используются.
Монохромный дисплей.
- D2-D0 Не используются.
- D3 Видео выход.
- D4 Интенсивность.
- D7-D5 Не используются.
Дисплей VGA.
- D0 P0
- D1 P1
- D2 P2
- D3 P3
- D4 P4
- D5 P5
- D7-D6 Не используются.
Регистр управления режимом
(Mode Control Register - MCR) (индекс 10h)
Регистр управления режимом управляет контроллером атрибутов.
- D0 ноль для текствых режимов, единица - для графических. Бит определяет спсособ раскодирования атрибутов.
- D1 Бит определяет тип атрибутов. Для монохромных атрибутов он должен быть равен единице, а для цветных - нулю.
- D2 Бит используется в монохромных режимах с разрешением по горизонтали 720 пикселов при расширении матриц символов псевдографики с 8 до 9 пикселов по горизонтали. Если бит равен 1, то девятый пиксел в каждой строке будет повторять восьмой. В противном случае девятый пиксел отображаетя цветом фона.
- D3 Бит D3 управляет назначением седьмого бита в байте атртбутов. Если бит установлен, то бит D7 байта атрибутов управляет миганием символа. Если бит D3 равен нулю, то - интенсивностью фона.
- D4 Не используется.
- D5 Доступен только на VGA. Совместно с регистром разделения экрана дисплея контроллера ЭЛТ бит D5 управляет горизонтальным панорамированием экрана. При установке бита D5 запрещается горизонтальное панорамирование стационарной частью экрана.
- D6 Доступен только на VGA. Бит должен быть равен нулю для режима видеоадаптера VGA с 256 цветами (режим 13h).
- D7 Доступен только на VGA. Выбор источника сигнала для видеовыходов Р4 И Р5. Если D7 равен нулю, то линии Р4 и Р5 управляются регистрами палитры, иначе сигналы на Р4 и Р5 поступают из битов D0 и D1 регистра выбора цветов.
По умолчанию регистр содержит следующие
значения:
Режим | 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 Не используются.
7.7. Регистры цифро-аналогового преобразователя VGA
VGA работает с аналоговыми дисплеями, имеющими три раздельных видеовхода. Величина напряжения на каждом из них управляет, соответственно, интенсивностью красного, зеленого и голубого цвета изображения. Аналоговое напряжение для дисплея формируется из двоичной цветовой информации при помощи трех ЦАП.
Цветовая 8-битовая информация, поступающая от контроллера атрибутов (см. рисунок 8.17), преобразуется согласно таблице цветов в три 6-битовые сигнала для трех ЦАП. Такая схема позволяет одновременно отображать на экране 256 различных цветов, каждый из которых можно отдельно выбрать из 26+6+6 = 218 = 262144 возможных цветов.
Рисунок 8.17 Схема управления цветами (VGA).
Таблица цветов фактически является набором из 256 18-битовых регистров. Используя регистры ЦАП, можно получить доступ для чтения и для записи к каждому регистру таблицы цветов.
ЦАП видеоадаптера VGA управляется пятью
регистрами, перечисленными в таблице 8.19.
Адрес | Регистр |
3C6h | регистр маскирования пикселов (Pixel Mask Register - PMR) |
3C7h | регистр состояния ЦАП (для чтения) (DAC State Register - DAC_SR) |
3C7h | индекс читаемого регистра таблицы цветов (для записи) (Look-up Table Read Index Register - LTRIR) |
3C8h | индекс записываемого регистра таблицы цветов (Look-up Table Write Index Register - LTWIR) |
3C9h | регистр данных таблицы цветов (Look-up Table Data Register - LTDR) |
Таблица 8.19 Регистры управления ЦАП.
Регистр маскирования пикселов
(Pixel Mask Register - PMR)
Фирма IBM в руководстве по VGA предупреждает, что доступ к регистру нежелателен. В противном случае могут разрушиться данные в таблице цветов.
Регистр состояния ЦАП
(DAC State Register - DAC_SR)
Регистр адресуется при помоши порта с адресом 3C7h и доступен только для чтения. Прочитав данные из регистра, можно определить, доступны регистры цветовой таблицы для чтения или же они доступны для записи.
- D1-D0 Если биты D0 D1 содержат двоичное число 11B (шестнадцатиричное 3), то регистры цветовой таблицы доступны для записи, если D0 D1 содержат двоичное число 00B (шестнадцатиричное 0), то регистры цветовой таблицы доступны для чтения.
- D7-D2 Не используются.
Индекс читаемого регистра таблицы цветов
(Look-up Table Read Index Register - LTRIR)
Это индексный регистр доступен через порт 3C7h только для записи. Запись в данный регистр индекса элемента цветовой таблицы позволяет прочитать его содержимое через регистр данных цветовой таблицы.
- D7-D0 Индекс регистра таблицы цветов (0-255).
Данные из регистров таблицы цветов читаются через порт 3C9h, как три 6-битовых числа. После чтения третьего числа значение индексного регистра (LTRIR) автоматически увеличивается на единицу, что позволяет прочитать всю таблицу цветов, загрузив регистр индекса только один раз.
Особо подчеркнем, что во время операций чтения или записи таблицы цветов прерывания должны быть запрещены.
Индекс записываемого регистра таблицы цветов
(Look-up Table Write Index Register - LTWIR)
После записи в регистр LTWIR индекса регистра таблицы цветов можно записать в него новое значение через регистр данных таблицы цветов (см. ниже).
- D7-D0 Индекс регистра таблицы цветов (0-255).
Данные записываются в регистры таблицы цветов через порт 3C9h, как три 6-битовых числа. После записи третьего числа значение индексного регистра (LTWIR) автоматически увеличивается на единицу, что позволяет прочитать таблицу цветов, загрузив регистр индекса только один раз.
Регистр данных таблицы цветов
(Look-up Table Data Register - LTDR)
Регистр используется для получения доступа к регистрам таблицы цветов. Для чтения из (записи в) таблицы цветов необходимо три раз прочитать (записать) содержимое регистра данных. При этом каждый раз считывается (записывается) шесть очередных битов. Первые шесть битов отвечают за интенсивность красного, вторые - зеленого и третьи - голубого цвета.
Нельзя прерывать цикл чтения регистров таблицы цветов, состоящий из трех операциий чтения, выполнением операции записи в другой регистр таблицы и наоборот. Во время доступа к данному регистру прерывания должны быть запрещены. Между операциями доступа к регистрам таблицы цвета должен существовать временной интервал не менее 240 наносекунд.
- D5-D0 Данные для обмена с регистрами таблицы цветов.
- D7-D6 Не используется.
Следующая программа записывет новые значения в таблицу цветов непосредственно через регистры цифро-аналогового преобразователя VGA. На экране дисплея отображается пять вертикальных полос различного цвета. Каждая полоса состоит из 64 вертикальных линий. Интенсивность цвета этих линий плавно уменьшается слева на право.
// программа демонстрирует использование регистров таблицы цветов #include <conio.h> #include <stdio.h> #include <graph.h> #include "sysp.h" #include "sysgraph.h" #include <dos.h> void SetVgaDAC(unsigned, unsigned); viod main(void) { struct videoconfig vc; // структура описана в graph.h RGB color_table[256]; unsigned char i, j; unsigned char far *ptr; int error, x_num, y_num; unsigned seg_table,off_table; // записываем в массив color_table новые значения для // регистров таблицы цветов for(j = 0; j < 4; j++) { for(i = 0; i < 64; i++) { (color_table[i+j*64]).red = (j == 0) ? i : 0; (color_table[i+j*64]).green = (j == 1) ? i : (j == 3) ? i : 0; (color_table[i+j*64]).blue = (j == 2) ? i : (j == 3) ? i : 0; } } // устанавливаем режим видеоадаптера номер 13h (256 цветов) // данный режим поддерживается только VGA и Super VGA error = _setvideomode( _MRES256COLOR ); // если режим не установлен, завершаем выполнение программы if(!error) exit(1); ptr = (unsigned char far*) &color_table[0]; // определяем сегмент и смешение массива color_table seg_table = FP_SEG(ptr); off_table = FP_OFF(ptr); // загружаем новые значения в регистры таблицы цветов SetVgaDAC(seg_table,off_table); // выводим на экран вертикальные линии различного цвета, // процессор записывает данные непосредственно в видеопамять // получаем в ptr указатель на начало видеопамяти ptr = (unsigned char far*) (FP_MAKE(0xA000, 0x0)); // записываем данные непосредственно в видеопамять for(y_num = 0; y_num < 200; y_num++) { for(x_num = 0; x_num < 320; x_num++) { *ptr = (unsigned char) x_num; ptr++; } } // ожидаем нажатия на любую клавишу getch(); // устанавливаем режим видеодаптера, используемый по умолчанию _setvideomode( _DEFAULTMODE ); } /** *.Name SetVgaDAC * *.Title Запись регистров таблицы цветов * *.Descr Функция устанавливает новые значения для всех регистров * таблицы цветов. * * *.Proto void SetVgaDAC(unsigned seg_table, unsigned off_table) * *.Params unsigned seg_table - сегмент таблицы, содержащей новые * значения регистров таблицы цветов, * * unsigned off_table - смещение таблицы, содержащей новые * значения регистров таблицы цветов. *.Return Не используется. * *.Sample vga256.c **/ void SetVgaDAC(unsigned seg_table, unsigned off_table) { _asm { ; сохраняем регистры ds и es push ds push es ; устанавливаем регистр es на начало оперативной памяти xor ax,ax mov es,ax ; получаем адрес порта индексного регистра контроллера ЭЛТ ; (3B4h/3D4h), ; в монохромных режимах для адресации к индексному регистру ; используется порт с адресом 3B4h, а в цветных - порт 3D4h mov dx,es:[463h] ; вычисляем адрес порта регистра состояния 1, ; в монохромных режимах для адресации к регистру состояния 1 ; используется порт с адресом 3BAh, а в цветных - порт 3DAh add dx,6 pop es ; ожидаем начало обратного вертикального хода луча in al,dx nop nop ; если бит D3 равен единице, то происходит обратный ; вертикальный ход луча 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 ; устанавливаем индекс первого записываемого регистра ; таблицы цветов mov dx,3C8h ; начинаем модифицировать таблицу цветов с первого регистра mov ax,1 out dx,al ; задержка nop nop ; устанавливаем ds:si на массив данных, записываемых ; в регистры таблицы цветов mov ax,seg_table mov ds,ax mov si,off_table ; загружаем 256 регистров (по 3 байта на регистр) mov cx,(256 * 3) ; выбираем регистр данных таблицы цветов (порт 3C9h) mov dx,3C9h cld ; загружаем все регистры таблицы цветов get_reg: lodsb out dx,al nop nop loop get_reg ; восстанавливаем регистр ds pop ds } }
7.8. Нестандартные режимы видеоадаптера VGA
В этой главе на примере видеоадаптера VGA мы рассмотрим программирование нестандартных режимов. Так как программирование нестандартных режимов видеоадаптеров требует непосредственного доступа к его регистрам, то перед чтением этой главы вам необходимо подробно изучить назначение регистров адаптера.
Мы рассмотрим два наиболее интересных с нашей точки зрения нестандартных режимов VGA: 320х400 и 360х480 пикселов при 256 цветах.
Эти режимы нельзя установить на обычных VGA адаптерах с помощью функций BIOS. С помощью BIOS можно установить только один режим с 256-цветной палитрой - 13h (320х200 пикселов, 256 цветов). Однако если вы воспользуетесь возможностью непосредственного программирования адаптера через регистры, то любой адаптер VGA можно перевести в эти режимы.
Программирование всех трех описанных ниже нестандартных режимов мы проведем в два этапа:
- устанавливаем при помощи BIOS стандартный режим 13h (320х200 пикселов, 256 цветов),
- изменяем содержимое некоторых регистров видеоадаптера, отвечающих за структуру видеопамяти и разрешающую способность.
Такой подход к установке нестандартных режимов позволяет нам программировать не все регистры адаптера, а только те, которые нуждаются в изменении.
Организация видеопамяти
Режим 13h использует простую линейную организацию видеопамяти, в которой по каждому адресу в видеопамяти находится один байт управляющий одним пикселом. Такая организация видеопамяти хотя и облегчает программирование, но не позволяет увеличить разрешающую способность. Дело в том, что в режиме 13h адресное пространство видеопамяти ограничено 64K, которых хватает как раз для того, чтобы получить разрешающую способность 200х320 точек при 256 цветах (200*320 = 64000). Кроме того такая организация видеопамяти не позволяет использовать для копирования видеоданных регистры-защелки, что может существенно повысить скорость работы программ.
Исходя из вышесказонного для нашего нестандартного режима используется другая структура видеопамяти, более схожая со структурой видеопамяти режимов 10h и 12h. На следующем рисунке представлена структура видеопамяти используемая нами во всех описываемых нестандартных режимах:
Рисунок 8.18 Структура видеопамяти в нестандартных, 256-цветовых режимах.
Как видно из рисунка первый пиксел экрана, отображаемый в левом верхнем углу, определяется байт со смещением 0 из нулевого цветового слоя. Второй пиксел определяется байтом со смещением 0 из первого слоя, третий пиксел - байтом со смещением 0 из второго слоя, четвертый пиксел - байтом со смещением 0 из третьего слоя. Пятый пиксел определяется байтом со смещением 1 из нулевого слоя и так далее.
Таким образом для пиксела с координатами x и y байт, который определяет его цвет, расположен со смещением (x + y * PIXEL_PER_LINE) / 4, в цветовой плоскости (x + y * PIXEL_PER_LINE) mod 4. В этой формуле константа PIXEL_PER_LINE должна определять горизонтальную разрешающую способность экрана в данном режиме.
Такая организация видеопамяти, хотя и более неудобна для вычисления адреса пикселов, чем линейная организация памяти режима 13h, но дает другие неоспаримые преимущества.
Во первых, в режиме с разрешением 320х400 пикселов мы можем использовать две страницы видеопамяти, первая из них имеет нулевое смещение, а вторая смещение 8000h от начала видеопамяти. Режим с разрешением 360х480 пикселов позволяет иметь только одну страницу, но так как он использует только 172800 байт из 256 килобайт, то неиспользуемую память можно использовать для хранения пиктограмм и шрифтов.
Во вторых, организация видеопамяти в виде отдельных цветовых слоев позволяет использовать для операций копирования и заполнения областей видеопамяти регистры-защелки. Это дает возможность одновременно копировать четыре байта, и следовательно значительно увеличить скорость работы программ.
Режим 320х400 пикселов, 256 цветов
Мы начнем рассмотрение нестандартных режимов с режима, имеющего разрешение 320х400 пикселов. Программирование этого режима является самым простым и безопасным, так как при его установке нам не придется изменять содержимое регистров контроллера ЭЛТ.
Как мы указывали при описании режимов видеоадаптеров, в режиме 13h используется двойное сканирование. То есть в этом режиме - 320х200 пикселов на самом деле отображается не 200, а 400 линий сканирования. Перепрограммировав несколько регистров адаптера можно перевести его в режим 320х400 пикселов.
Рассмотрим последовательность действий, необходимую для перевода видеоадаптера в нестандартный режим с разрешением 320х400 пикселов:
- Устанавливаем при помощи BIOS стандартный режим 13h (320х200 пикселов, 256 цветов), при этом программируются все регистры видеоадаптера. Затем мы изменим содержимое только нескольких регистров. Такой подход значительно облегчит нам задачу, так как уменьшится количество регистров, которые необходимо изменить.
- Изменяем структуру видеопамяти, чтобы иметь воможность адресоваться к 256 килобайтам. Для этого в регистре определения структуры памяти синхронизатора запрещаем режимы в которых доступ по разным адресам (кратным двум и/или кратным четырем) осуществляется к различным цветовым слоям памяти. А в регистре режима работы графического контроллера сбрасываем в ноль бит управления четным/нечетным режимом. Это запрещает доступ по четным адресам к четным цветовым слоям, а по нечетным адресам - к нечетным цветовым слоям видеопамяти. Затем в регистре смешанного назначения графического контроллера сбрасываем бит управляющий сцеплением четных и нечетных слоев памяти. После этих действий видеопамять по своей структуре напоминает режим 10h, за исключением того, что каждый пиксел управляется одним байтом, расположенном в одной из слоев видеопамяти.
- Очищаем видеопамять (для одной или двух страниц по необходимости), так как при установке режима 13h BIOS очищает только первые 64K из 256K. Остальная видеопамять может содержать мусор который отобразится на экране после перепрограммирования контроллера ЭЛТ.
- Выключаем режим двойного сканирования. Для этого сбрасываем в ноль бит управления двойным сканированием и устанавливаем высоту символов равную единице.
- Переводим контроллер ЭЛТ в режим адресации видеопамяти по байтам. Для этого выключаем режим адресации по двойным словам в регистре положения подчеркивания символа и включаем режим адресации по байтам в регистре управления режимом работы. Теперь по каждому адресу расположено четыре байта в различных цветовых слоях видеопамяти.
Теперь мы приведем программу, которая реализует изложенный алгоритм и переводит видеоадаптер в режим отображающий 256 цветов при разрешающей способности 320х400 пикселов.
/** * Включаемый файл vga_new.h **/ // сегмент видеопамяти для режима 13h #define VGA_SEGMENT 0a000h // регистр определения различных режимов работы #define MOR 3c2h // адрес индексного порта синхронизатора #define SC_INDEX 3c4h // регистр разрешения записи цветового слоя #define CPWER 2 // регистр определения структуры памяти #define MMR 4 // адрес индексного порта графического контроллера #define GC_INDEX 3ceh // регистр выбора читаемого слоя #define RPSR 4 // регистр режима работы #define MDR 5 // регистр смешанного назначения #define MIR 6 // адрес индексного порта контроллера ЭЛТ (цветной режим) #define CRTC_INDEX 3d4h // регистр высоты символов текста #define MSLR 9 // регистр начального адреса #define SAR_h 0ch // регистр положения подчеркивания символа #define ULR 14h // регистр управления режимом #define MCR 17h // режим 320х400 пикселов // число пикселов по вертикали #define SCREEN_HEIGHT 400 // число пикселов по горизонтали #define SCREEN_WIDTH 320 // режим 360х480 пикселов // число пикселов по вертикали #define SCREEN_HEIGHT_H 480 // число пикселов по горизонтали #define SCREEN_WIDTH_H 360 /** * Файл e256mres.c **/ #include "sysp.h" #include "sysgraph.h" #include <dos.h> #include <graph.h> #include "vga_new.h" /** *.Name Set320x400Mode * *.Title Установка режима 320х400 пикселов, 256 цветов. * *.Proto void Set320x400Mode( void ) * *.Params Не используются. * *.Return Не используетя. * *.Sample e256mres.c **/ void Set320x400Mode( void ) { _asm { // сохраняем регистр di push di // устанавливаем стандартный режим 13h (320x200 // пикселов, 256 цветов) mov ax,0013h int 10h // выбираем регистр определенияя структуры памяти mov dx,SC_INDEX mov al,MMR out dx,al // считываем значение регистра определения // структуры памяти inc dx in al,dx // сбрасываем бит D4 and al,11110111b // устанавливаем бит D3, при этом выключается // режим адресации по четным и нечетным адресам к // разным слоям памяти or al,00000100b // записываем в регистр новое значение out dx,al // после загрузки в этот регистр нового значения // структура видеопамяти соответствует режимам 10h // и 12h за исключением того, что каждому пикселу // соответствует один байт видеопамяти // выбираем регистр режима работы графического // контроллера mov dx,GC_INDEX mov al,MDR out dx,al // считываем его значение inc dx in al,dx // выключаем доступ по четным адресам к четным // слоям, а по нечетным адресам к нечетным слоям and al,11101111 out dx,al // выбираем регистр смешанного назначения // графического контроллера dec dx mov al,MIR out dx,al // считываем его значение inc dx in al,dx // сбрасываем бит управляющий сцеплением четных и // нечетных слоев and al,11111101b out dx,al // разрешаем запись днных во все четыре цветовых // слоя, записывая число 0fh в регистр разрешения // записи цветового слоя mov dx,SC_INDEX mov al,CPWER out dx,al inc dx mov al,00001111b out dx,al // очищаем первую страницу видеопамяти, так как // установка ржима 13h очищает только первые 64K mov ax,VGA_SEGMENT mov es,ax xor di,di mov ax,di mov cx,8000h cld rep stosb // выбираем регистр высоты символов текста // контроллера ЭЛТ mov dx,CRTC_INDEX mov al,MSLR out dx,al inc dx in al,dx // запрещаем двойное сканирование and al,01100000b out dx,al // выбираем регистр положения подчеркивания // символа dec dx mov al,ULR out dx,al // выключаем режим адресации видеопамяти по // двойным словам inc dx in al,dx and al,10111111b out dx,al // выбираем регистр управления режимом dec dx mov al,MCR out dx,al // включаем байтовый режим адресации inc dx in al,dx or al,01000000b out dx,al pop di } } /** *.Name WritePixel * *.Title Отображение пиксела. * *.Descr Функция отображает на экране пиксел в заданных * координатах, * определенного цвета. * *.Proto void WritePixel(unsigned x, unsigned y, unsigned * char color) * *.Params x - x-координата пиксела (0-319), * * y - y-координата пиксела (0-399), * * color - цвет пиксела (0-255). * *.Return Не используетя. * *.Sample e256mres.c **/ void WritePixel(unsigned x, unsigned y, unsigned char color) { _asm { push di mov cx,x mov dx,y mov bl,color mov ax,VGA_SEGMENT mov es,ax mov ax,( SCREEN_WIDTH / 4 ) mul dx push cx shr cx,1 shr cx,1 add ax,cx mov di,ax pop cx and cl,3 mov ah,1 shl ah,cl mov dx,SC_INDEX mov al,CPWER out dx,ax mov es:[di],bl pop di } } /** *.Name ReadPixel * *.Title Определение цвета пиксела. * *.Descr Функция возвращает значение байта видеопамяти, * определяющего пиксел * с заданными координатами. * *.Proto unsigned char ReadPixel(unsigned x, unsigned y, * unsigned char color) * *.Params x - x-координата пиксела (0-319), * * y - y-координата пиксела (0-399). * *.Return цвет пиксела (0-255). * *.Sample e256mres.c **/ unsigned char ReadPixel( unsigned x, unsigned y ) { unsigned char color; _asm { push si mov cx,x mov dx,y mov ax,VGA_SEGMENT mov es,ax mov ax,( SCREEN_WIDTH / 4 ) mul dx push cx shr cx,1 shr cx,1 add ax,cx mov si,ax pop ax and al,3 mov ah,al mov dx,GC_INDEX mov al,RPSR out dx,ax mov al,es:[si] mov color,al pop si } return( color ); } /** *.Name Full_Scr * *.Title Закрашивает экран заданным цветом. * *.Proto void Full_Scr( unsigned char color ) * *.Params color - цвет экрана (0-255). * *.Return Не используетя. * *.Sample e256mres.c **/ void Full_Scr( unsigned char color ) { _asm { ;разрешаем запись данных во все четыре цветовых ;слоя push di mov dx,SC_INDEX mov al,CPWER out dx,al inc dx mov al,0fh out dx,al mov ax,VGA_SEGMENT mov es,ax xor di,di mov al,color mov cx,32000 cld rep stosb pop di } } // функция LoadVGA256 загружает регистры таблицы цветов // цифро-аналогового преобразователя новыми значениями void LoadVGA256(void) { RGB color_table[256]; unsigned char i, j; unsigned char far *ptr; unsigned seg_table,off_table; // записываем в массив color_table новые значения для // регистров таблицы цветов for(j = 0; j < 4; j++) { for(i = 0; i < 64; i++) { (color_table[i+j*64]).red = (j == 0) ? i : 0; (color_table[i+j*64]).green = (j == 1) ? i : (j == 3) ? i : 0; (color_table[i+j*64]).blue = (j == 2) ? i : (j == 3) ? i : 0; } } ptr = (unsigned char far*) &color_table[0]; // определяем сегмент и смешение массива color_table seg_table = FP_SEG(ptr); off_table = FP_OFF(ptr); // загружаем новые значения в регистры таблицы цветов SetVgaDAC(seg_table,off_table); // функция SetVgaDAC загружает регистры таблицы цветов // цифро-аналогового преобразователя // исходный текст функции приведен при описании регистра // данных таблицы цветов ЦАП VGA (файл vga256.c) } // // главная функция // void main( void ){ unsigned i; char ch = 13; struct videoconfig vc; // заполняем поля структуры vc printf("\n (C) Frolov G.V., 1992 \n\n"); _getvideoconfig( &vc ); // завершаем программу если нет VGA адаптера if(vc.adapter != _VGA) { printf("Для выполнения программы необходим" " адаптер VGA.\n"); exit(0); } // устанавливаем режим 320х400 пикселов, 256 цветов Set320x400Mode(); // загружаем регистры ЦАП VGA LoadVGA256(); for(i = 0; i < 400; i++) WritePixel(160, (unsigned) i, (unsigned char) (i % 256) ); for(i = 0; i < 320; i++) WritePixel((unsigned) i, 200, (unsigned char) (i % 256) ); ch = getch(); if( ch == 27 ) exit(1); for(i = 0; i < 320; i++) WritePixel((unsigned) i, (unsigned) i, (unsigned char) (i % 256) ); ch = getch(); for(i = 0; ((i < 256) && (ch != 27)); i++) { Full_Scr( (unsigned char) i ); ch = getch(); } // возвращаемся в текстовый режим _setvideomode(_DEFAULTMODE); printf("Привет всем!!!\n"); }
Режим 360х480 пикселов, 256 цветов
Второй рассматриваемый нами нестандартный режим может отображать 256 цветов при разрешающей способности 360х480 пикселов. Программирование этого режима является менее простыми безопасным, чем предыдущего режима, так как нам придется изменять содержимое регистров контроллера ЭЛТ, отвечающих за временные характеристики видеоадаптера. В остальном программирование видеоадаптера осуществляется по тем же правилам, что и в режиме с разрешающей способностью 320х400 пикселов.
Ниже приведена программа, которая переводит видеоадаптер в нестрандартный режим с разрешением 360х480 пикселов:
/** * Файл e256hres.c **/ #include "sysp.h" #include "sysgraph.h" #include <dos.h> #include <graph.h> #include "vga_new.h" /** *.Name Set360x480Mode * *.Title Установка режима 360х480 пикселов, 256 цветов. * *.Proto void Set360x480Mode( void ) * *.Params Не используются. * *.Return Не используетя. * *.Sample e256hres.c **/ void Set360x480Mode( void ) { _asm { // устанавливаем режим 12h, чтобы очистить видеопамять mov ax,12h int 10h // устанавливаем стандартный режим 13h mov ax,0013h int 10h // перепрограммируем регистр определения структуры // памяти: запрещаем адресацию к разным слоям памяти в // зависимости от кратности адреса памяти четырем (бит // D4 - chain4) mov dx,SC_INDEX mov ax,0604h out dx,ax // производим синхронный сброс и остановку // синхронизатора mov ax,0100h out dx,ax // адресуемся к регистру определения различных режимов // работы mov dx,MOR // устанавливаем частоту кадров 60Кц mov al,0e7h out dx,al // запускаем синхронизатор mov dx,SC_INDEX mov ax,0300h out dx,ax // выбираем регистр режима работы графического // контроллера mov dx,GC_INDEX mov al,MDR out dx,al // считываем его значение inc dx in al,dx // выключаем доступ по четным адресам к четным слоям, а // по нечетным адресам к нечетным слоям and al,11101111 out dx,al // выбираем регистр смешанного назначения графического // контроллера dec dx mov al,MIR out dx,al // считываем его значение inc dx in al,dx // сбрасываем бит управляющий сцеплением четных и // нечетных слоев and al,11111101b out dx,al // выбираем регистр конца обратного вертикального хода // луча mov dx,3d4h mov al,11h out dx,al // снимаем защиту от записи с регистров контроллера // ЭЛТ, имеющих индексы от 0 до 7 inc dx in al,dx and al,7fh out dx,al dec dx // программируем регистры контроллера ЭЛТ, втом числе // регистры, определяющие временные параметры режима // устанавливаем регистр общей длины линии // горизонтальной развертки mov ax,06b00h out dx,ax // устанавливаем регистр длины отображаемой части // горизонтальной развертки mov ax,05901h out dx,ax // устанавливаем регистр начала импульса гашения луча // горизонтальной развертки mov ax,05a02h out dx,ax // устанавливаем регистр конца импульса гашения луча // горизонтальной развертки mov ax,08e03h out dx,ax // устанавливаем регистр начала импульса // горизонтального обратного хода луча mov ax,05e04h out dx,ax // устанавливаем регистр конца импульса горизонтального // обратного хода луча mov ax,08a05h out dx,ax // устанавливаем регистр числа горизонтальных линий // растра mov ax,0d06h out dx,ax // устанавливаем дополнительный регистр mov ax,03e07h out dx,ax // устанавливаем регистр высоты символов текста mov ax,04009h out dx,ax // устанавливаем регистр начала обратного // вертикального хода луча mov ax,0ea10h out dx,ax // устанавливаем регистр конца обратного // вертикального хода луча mov ax,0ac11h out dx,ax // устанавливаем регистр начала гашения вертикальной // развертки mov ax,0df12h out dx,ax // устанавливаем регистр логической ширины экрана mov ax,02d13h out dx,ax // устанавливаем регистр положения подчеркивания // символа mov ax,014h out dx,ax // устанавливаем регистр начала импульса гашения // вертикальной развертки mov ax,0e715h out dx,ax // устанавливаем регистр конца импульса гашения // вертикальной развертки mov ax,0616h out dx,ax // устанавливаем регистр управления режимом mov ax,0e317h out dx,ax } } /** *.Name WritePixel_H * *.Title Отображение пиксела. * *.Descr Функция отображает на экране пиксел в заданных * координатах, определенного цвета. * *.Proto void WritePixel_H(unsigned x, unsigned y, unsigned * char color) * *.Params x - x-координата пиксела (0-319), * * y - y-координата пиксела (0-399), * * color - цвет пиксела (0-255). * *.Return Не используетя. * *.Sample e256hres.c **/ void WritePixel_H(unsigned x, unsigned y, unsigned char color) { _asm { push di mov cx,x mov dx,y mov bl,color mov ax,VGA_SEGMENT mov es,ax mov ax,( SCREEN_WIDTH_H / 4 ) mul dx push cx shr cx,1 shr cx,1 add ax,cx mov di,ax pop cx and cl,3 mov ah,1 shl ah,cl mov dx,SC_INDEX mov al,CPWER out dx,ax mov es:[di],bl pop di } } /** *.Name ReadPixel_H * *.Title Определение цвета пиксела. * *.Descr Функция возвращает значение байта видеопамяти, * определяющего пиксел с заданными координатами. * *.Proto unsigned char ReadPixel_H(unsigned x, unsigned y, unsigned char color) * *.Params x - x-координата пиксела (0-319), * * y - y-координата пиксела (0-399). * *.Return цвет пиксела (0-255). * *.Sample e256hres.c **/ unsigned char ReadPixel_H( unsigned x, unsigned y ) { unsigned char color; _asm { push si mov cx,x mov dx,y mov ax,VGA_SEGMENT mov es,ax mov ax,( SCREEN_WIDTH_H / 4 ) mul dx push cx shr cx,1 shr cx,1 add ax,cx mov si,ax pop ax and al,3 mov ah,al mov dx,GC_INDEX mov al,RPSR out dx,ax mov al,es:[si] mov color,al pop si } return( color ); } /** *.Name Full_Scr_H * *.Title Закрашивает экран заданным цветом. * *.Proto void Full_Scr_H( unsigned char color ) * *.Params color - цвет экрана (0-255). * *.Return Не используетя. * *.Sample e256hres.c **/ void Full_Scr_H( unsigned char color ) { _asm { push di ;разрешаем запись данных во все четыре цветовых слоя mov dx,SC_INDEX mov al,CPWER out dx,al mov al,0fh out dx,al mov ax,VGA_SEGMENT mov es,ax xor di,di mov al,color mov cx,43200 cld rep stosb pop di } } // функция LoadVGA256 загружает регистры таблицы цветов // цифро-аналогового преобразователя новыми значениями void LoadVGA256(void) { RGB color_table[256]; unsigned char i, j; unsigned char far *ptr; unsigned seg_table,off_table; // записываем в массив color_table новые значения для // регистров таблицы цветов for(j = 0; j < 4; j++) { for(i = 0; i < 64; i++) { (color_table[i+j*64]).red = (j == 0) ? i : 0; (color_table[i+j*64]).green = (j == 1) ? i : (j == 3) ? i : 0; (color_table[i+j*64]).blue = (j == 2) ? i : (j == 3) ? i : 0; } } ptr = (unsigned char far*) &color_table[0]; // определяем сегмент и смешение массива color_table seg_table = FP_SEG(ptr); off_table = FP_OFF(ptr); // загружаем новые значения в регистры таблицы цветов SetVgaDAC(seg_table,off_table); // функция SetVgaDAC загружает регистры таблицы цветов // цифро-аналогового преобразователя // исходный текст функции приведен при описании регистра // данных таблицы цветов ЦАП VGA (файл vga256.c) } // // главная функция // void main( void ){ unsigned i; char ch = 13; struct videoconfig vc; // заполняем поля структуры vc printf("\n (C) Frolov G.V., 1992\n\n"); _getvideoconfig( &vc ); // завершаем программу если нет VGA адаптера if(vc.adapter != _VGA) { printf("Для выполнения программы нобходим" " адаптер VGA\n"); exit(0); } // устанавливаем режим 360х480 пикселов, 256 цветов Set360x480Mode(); // загружаем регистры ЦАП VGA LoadVGA256(); for(i = 0; i < 480; i++) WritePixel_H(180, (unsigned) i, (unsigned char) (i % 256) ); for(i = 0; i < 360; i++) WritePixel_H((unsigned) i, 240, (unsigned char) (i % 256) ); ch = getch(); if( ch == 27 ) exit(1); for(i = 0; i < 360; i++) WritePixel_H((unsigned) i, (unsigned) i, (unsigned char) (i % 256) ); ch = getch(); for(i = 0; ((i < 256) && (ch != 27)); i++) { Full_Scr_H( (unsigned char) i ); ch = getch(); } // возвращаемся в текстовый режим _setvideomode(_DEFAULTMODE); printf("Привет всем!!!\n"); }