шении в перпендикулярном направлении.
Вместо вызова подпрограммы fastdot(), точки помещаются непос-
редственно на экран дисплея. Регистры EGA сбрасываются только
один раз в конце и функция работает гораздо быстрее функции, ос-
нованной на вызове fastdot().
Листинг 9-4. Программа BRES.C
---------------------------------------------------------------
/* bres.c */
/* Чертит серию линий для демонстрации функции line() */
#include
#include
#include
#include "ega.h"
void line(int, int, int, int, int); /* добавить это в ega.h */
main()
{
int x1, y1, x2, y2 ;
int step = 10, color = 13, scan_lines ;
struct Ega_info info ;
if(get_ega_info(&info) >= 128) /* активный EGA? память? */
{
set_crt_mode(info.high_res_grahics) ;
scan_lines = (PEEK_BYTE(0x40, 0x84) + 1)
* PEEK_WORD(0x40, 0x85) ;
y2 = (scan_lines - 1) - ((scan_lines - 1) % step) ;
for (y1 = 0, x1 = 0, x2 = 0;
y1 <= y2;
y1 += step, x2 += step)
line(x1,y1,x2,y2,color) ;
getch() ; /* ждать нажатия клавиши */
set_crt_mode(info.text_mode);
}
else
- 9-18 -
puts("\nАдаптер EGA не активен или не установлен.\n") ;
}
void line(x1,y1,x2,y2,color)
int x1,y1,x2,y2,color ;
/* Быстрая функция линии - использует алгоритм Бресенгама */
/* Координаты строк(Y) и столбцов(X) считаются не равными */
#define sign(x) (((x) < 0) ? (-1) : (1))
#define qabs(x) (((x) < 0) ? -(x) : (x))
{
int dx = qabs(x2 - x1) ; /* прогон */
int dy = qabs(y2 - y1) ; /* подъем */
int s1 = sign(x2 - x1) ; /* для увеличения/уменьшения */
int s2 = sign(y2 - y1) ;
int dx2, dy2, bytes_per_line = GET_CRT_COLS() ;
registr error_term, i ;
unsigned char far *rgen = (char far *)(0xA0000000L) ;
unsigned char exchange = (char)0 ;
/* Большее значение подъема или прогона определяет,
** что увеличивать в цикле
*/
if(dy > dx)
{ int temp = dx; dx = dy; dy = temp; exchange = (char)1; }
dx2=(dx << 1); /* использовать повторно, вычислить сейчас */
dy2=(dy << 1);
error_term=(dy - dx) << 1; /* инициализировать error_term */
EGA_GRFX(0, color) ; /* использовать регистр EGA
установить/сбросить */
EGA_GRFX(1, 0xF) ; /* разрешить все битовые массивы */
for (i=1; i<=dx; ++i) /* все элементы изображения на линии */
{
EGA_BIT_MASK(0x80 >> (x1 & 7) ) ;
rgen[ ((x1 >> 3) + (y1 * bytes_per_line)) ] += 0x1 ;
while (error_term >= 0) /* цикл до следующего элемента */
{
if (exchange)
x1 += s1 ;
else
y1 += s2 ;
error_term -= dx2 ;
}
if (exchange)
y1 += s2 ;
else
x1 += s1 ;
error_term += dy2 ;
}
EGA_GRFX(1, 0) ; /* запретить регистр установить/сбросить */
EGA_BIT_MASK(0xFF) ; /* сбросить маску бита */
}
---------------------------------------------------------------
Для хранения графического образа на экране программа должна
знать высоту и ширину дисплея в элементах изображения. Ширина
дисплея в элементах изображения указывается как GET_CRT_COLS() x
- 9-19 -
х 8 элементов/байт. Высота должна быть точно определена из табли-
цы, содержащей количество вертикальных линий развертки для каждо-
го режима. Однако, это более быстрый, но менее точный способ. И
число строк символов, и размер точки (байта на символ) можно зап-
рограммировать, кроме того, любой из них можно изменить. Но высо-
та прямоугольника для символа в байтах и число строк развертки
определяют количество строк. Так как слово с адресом 0х40:0х85
содержит байты на символ и байт с адресом 0:40х0:84 содержит ко-
личество строк, они могут быть использованы для вычисления числа
строк развертки для любого видеорежима. Оператор языка Си
scan_lines = (PEEK_BYTE(0x40, 0x84) + 1)
* PEEK_WORD(0x40, 0x85) ;
вычисляет приблизительное значение общего числа линий развертки.
Значение вычисляется приблизительно, так как число строк изменя-
ется и не всегда на 1. Как только станут известны данные EGA,
программа чертит серию линий, которые не зависят от используемого
графического режима EGA.
Использование регистра установки/сброса
В программе, представленной в листинге 9-4, функция line()
использует другой метод определения цвета точек на дисплее, неже-
ли подпрограмма fastdot(). Подпрограмма fastdot() применяет для
определения цвета регистр маски бита. Но так как определение
маски для регистра маски матрицы не очищает предыдущую точку, то
эта точка должна быть сначала сброшена при помощи установки ре-
гистра маски бита в 0xF с последующей установкой цвета для новой
точки. Другими словами, для установки определенного цвета точки
доступ и к маске матрицы, и к памяти EGA должен быть осуществлен
дважды.
Функция line() использует регистр установки/сброса и для оп-
ределения цвета разрешает выполнить установку/сброс регистра. Ре-
гистр установки/сброса установит байт в 0xFF в каждом битовом
массиве EGA, бит которого в этом регистре равен единице, и сбро-
сит байт в 0 в каждом битовом массиве, бит которого равен нулю.
Следовательно, предыдущее содержание регистров-защелок заменяется
номером цвета, соответствующего значению, установленному в ре-
гистре установки/сброса. Регистр маски матрицы не влияет на ре-
гистр установки/сброса, но регистр маски бита полезен для защиты
смежных элементов изображения.
Чтобы использовать регистр установки/сброса, Вы сначала долж-
ны разрешить его с помощью регистра разрешения установки/сброса.
Регистр установки/сброса и регистр разрешения установки/сброса
являются частью графического контроллера EGA. Состояние BIOS по
умолчанию для регистра разрешения установки/сброса 0, это озна-
чает, что регистр установки/сброса выключен. Каждый бит из четы-
рехбитового значения, направляемого регистру разрешения уста-
новки/сброса, соответствует битовой матрице EGA. Если бит в ре-
гистре разрешения установки/сброса 0, соответствующая битовая
матрица защищена от изменения регистром установки/сброса.
Регистр установки/сброса доступен направлениям индекса 0 в
порт 0х3CЕ и последующим направлением четырехбитового кода цвета
в порт 0x3CF. Регистр установки/сброса оказывает влияние только
на битовые матрицы, разрешенные регистром разрешения установ-
- 9-20 -
ки/сброса. Регистр разрешения установки/сброса доступен направле-
нием индекса 1 в порт 0х3СЕ с последующим направлением четырехби-
товой маски матрицы в порт 0x3CF.
Обратите внимание на оператор rgen[((x1 >> 3) + (y1 * bytes_
per_line))]+@ 0x1 ; в программе 9-4. Поскольку дисплейный буфер
EGA линейный, к нему легко обратиться как к матрице. Выражение
внутри скобок вычисляет смещение буфера изменяемого байта. Похо-
же, что правая сторона оператора прибавляет 1 к байту, что цент-
ральный процессор и пытается проделать. Тем не менее, действи-
тельной целью является предохранение смежных элементов
изображения, содержащихся в байте. Когда используется регистр
маски бита, необходимо сначала считать дисплейный буфер для за-
полнения регистров-защелок таким образом, чтобы другие биты в
этом байте были защищены. В отличие от метода установки цвета с
помощью регистра маски бита, при использовании регистра установки
/сброса байт, посылаемый центральным процессором, служит только
для установки адреса изменяемого байта.
Таким образом, выражение +=1 выполняет две функции: оно счи-
тывает дисплейный буфер в целях установки регистров-защелок, а
также возвращает байт, который включает регистр установки/сброса.
В процессе трансляции компилятором языка Си операции в команду
процессора 80х86 1 может принимать любое значение, которое снача-
ла считывает, а затем сохраняет байт в дисплейной памяти EGA.
Использование режимов записи EGA
EGA имеет три режима записи: 0, 1 и 2. Изменение режима запи-
си меняет реакцию аппаратных средств EGA на направление централь-
ным процессором байта в дисплейный буфер. Каждый режим записи оп-
тимизирован для различного использования. Режим записи 0 является
режимом записи общего назначения, режим записи 1 оптимизирован
для копирования областей памяти EGA и режим записи 2 наилучшим
образом используется для закрашивания. Изменение режима записи
может существенно ускорить выполнение операции.
Режим записи 0 является режимом, применяемым EGA BIOS. Это
наиболее общий режим записи. В режиме 0 цвет элемента изображения
может быть установлен с помощью как регистра маски матрицы, так и
регистра установки/сброса. Регистр маски матрицы используется EGA
BIOS и подпрограммой fastdot(). Функция line() применяет регистр
установки/сброса для определения цвета. При использовании регист-
ра маски матрицы отдельные элементы изображения могут быть уста-
новлены посылаемым центральным процессором байтом с соответствую-
щими битами, установленными в 1. Тем не менее, смежные элементы
изображения в байте должны быть защищены с помощью регистра маски
бита. При применении регистра установки/сброса биты посылаемого
центральным процессором байта не соответствуют элементам изобра-
жения. Байт записывается только для определения смещения изменяе-
мых элементов изображения. Цвет определяется в регистре уста-
новки/сброса, а регистр маски бита позволяет управлять отдельными
элементами изображения.
Режим записи 2 очень похож на режим записи 0. В режиме 2
байт, посылаемый центральным процессором, скорее устанавливает
цвет, чем отдельные элементы изображения. Регистр маски бита поз-
воляет управлять отдельными элементами изображения и, если ре-
гистр маски бита не установлен, весь байт элементов изображения
заполняется цветом, значение которого посылается центральным про-
- 9-21 -
цессором. Режим записи определяется в битах 0 и 1 байта, направ-
ляемого регистром режима графических чипов 1 и 2. Регистр режима