имеет индекс 5. Программа, приведенная в листинге 9-5, демонстри-
рует режим записи 2. Подпрограмма rect() использует режим 2 для
заполнения прямоугольника заданным цветом.
Листинг 9-5. Программа RECT.C
---------------------------------------------------------------
/* rect.c */
/* Эта программа демонстрирует режим записи 2 */
#include
#include
#include
#include "ega.h"
void rect(int,int,int,int,char); /* добавить это в ega.h */
main()
{
int i,j;
struct Ega_info info ;
if(get_ega_info(&info))
set_crt_mode(info.high_res_graphics) ;
else
return(1) ;
printf("\nЦвет #:\n");
for (i=0,j=0;i<16;++i,j+=40)
{
printf(" %2i ",i);
rect(50,j,349,j+39,(char)i);
}
getch();
set_crt_mode(3) ;
}
void rect(row1,col1,row2,col2,color)
int col1,row1,col2,row2 ;
char color ;
{ /* Эта функция генерирует заполненный прямоугольник */
/* Предполагается, что row1 < row2 и col1 < col2 */
unsigned char far *rgen = (char far *)(0xA0000000L) ;
int rows = row2 - row1 ; /* число строк */
int cols = (col2 >> 3) - (col1 >> 3) - 1; /* всего столбцов */
char left = (char)(0xFF >> (col1 & 7)) ; /* левая маска */
char rght = (char)~(0xFF >> (col2 & 7)) ; /* правая маска */
char next_row ;
char byte_per_line = (char)GET_CRT_COLS() ;
register x,y ;
char latch ;
if (cols < 0) /* Находятся ли col1 и col2 в одном байте? */
left &= rght, cols = 0, rght = 0 ;
rgen += bytes_per_line*row1 +(col1 >> 3) ;
next_row = bytes_per_line - cols - 2 ;
EGA_GRFX(5,2); /* установить режим записи 2 */
for(y = 0 ; y < rows ; y++) /* выполнить каждую строку */
- 9-22 -
{
EGA_BIT_MASK(left) ; /* установить левую маску бита */
latch = *(rgen) ; /* защелкнуть битовые матрицы EGA */
*(rgen++) = color ; /* установить цвет, указать для
следующего байта */
EGA_BIT_MASK(0xFF) ; /* отменить маску центра */
for(x = 0; x < cols; x++) /* выполнить каждый столбец */
{
latch = *(rgen) ;
*(rgen++) = color ;
}
EGA_BIT_MASK(rght) ; /* установить правую маску бита */
latch = *(rgen) ; /* защелкнуть битовые матрицы EGA */
*(rgen++) = color ; /* установить цвет */
rgen += next_row ; /* перейти к следующей строке */
}
EGA_BIT_MASK(0xFF) ; /* отменить маску бита */
EGA_GRFX(5,0) ; /* сбросить режим записи */
}
----------------------------------------------------------------
В программе 9-5 режим записи 2 устанавливается макрокомандой
EGA_GRFX(5,2). Вы должны быть внимательными и не посылать значе-
ния, отличные от 0, 1, или 2 для EGA (0, 1, 2 или 3 для VGA), так
как другие биты байта, направляемые регистру режима, имеют значе-
ние для EGA. Регистры маски матрицы и маски бита эффективны в ре-
жиме записи 2, а регистр установки/сброса бесполезен. Режим запи-
си 0, режим записи BIOS по умолчанию, устанавливается с помощью
EGA_GRFX(5,0). Перед использованием других программ или вызовов
BIOS режим записи должен быть сброшен в 0.
Режим записи 1 применяется для быстрого копирования одной об-
ласти памяти EGA в другую. Это очень полезно для прокрутки, муль-
типликации, а также сохранения и восстановления областей на экра-
не. Режим записи 1 позволяет Вам копировать 4 байта в каждой из
четырех битовых матриц за один цикл чтения или записи центрально-
го процессора и во много раз быстрее чтения 4 отдельных байтов из
битовых матриц с последующей записью 4 байтов по новому адресу.
Для копирования 8 элементов смещение изображения памяти EGA,
содержащее 8 элементов изображения, считывается для подготовки
регистров-защелок; затем смещение, содержащее назначение, записы-
вается центральным процессором. Когда центральный процессор запи-
сывает байт, а режим записи установлен в 1, EGA сбрасывает байт
центрального процессора и копирует содержание регистров-защелок в
каждую битовую матрицу. Регистр маски бита не используется с ре-
жимом записи 1. Все четыре байта в регистрах-защелках записывают-
ся во все четыре битовые матрицы независимо от установки маски
бита. Регистр маски матрицы может быть использован для защиты от-
дельных битовых матриц.
Программа, представленная в листинге 9-6, демонстрирует режим
записи 1. Серия линий чертится в верхней части экрана. Затем эта
серия копируется с использованием режима записи 1. Наконец, гра-
ница образца быстро перечерчивается для демонстрации возможности
мультипликации.
- 9-23 -
Листинг 9-6. Программа MODEL.C
---------------------------------------------------------------
/* mode1.c */
/* Эта программа демонстрирует режим записи 1 EGA */
#include
#include
#include
#include "ega.h"
void copy( int,int,int,int,int,int );
void main()
{
registr i,j;
int k = 0;
set_crt_mode(16) ; /*только усовершенствованный монитор!*/
/* Рисует интересующую серию: */
for(k = 0; k <= 4; ++k)
for(j = 0+k; j <= 500+k; j += 5)
for(i = 0+k; i <= 100+k; ++i)
fastdot(i,i+j,13) ;
for(k = 0; k <= 3; ++k)
for(j = 0+k; j <= 500+k; j += 5)
for(i = 0+k; i <= 100+k; ++i)
fastdot(i,i+j,3) ;
/* Скопировать серию на 120 строк вниз: */
copy(0,0,105,639, 120,0) ;
while(!kbhit())
{
/* Скопировать границу повторно,
** создает иллюзию движения: */
copy(99,100,106,592, 219,100) ;
copy(99,100,106,592, 219,108) ;
}
set_crt_modes(3) ;
}
void copy(r1_1, c1_1, r2_1, c2_1, r1_2, c1_2)
int r1_1, c1_1, /* верхний левый угол источника */
r2_1, c2_1, /* нижний правый угол источника */
r1_2, c1_2 ; /* верхний левый угол назначения */
{
/* Быстро копирует одну область экрана в другую.
** Использует режим записи 1. Надо задать только
** верхний угол назначения.
*/
char far *source = (char far *)(0xA0000000L) ;
char far *destination = (char far *)(0xA0000000L) ;
int rows = r2_1 - r1_1 ;
int cols = (c2_1 >> 3) - (c1_1 >> 3) ;
int bytes_per_line = GET_CRT_COLS() ;
int next_row = bytes_per_line - cols ;
registr x,y ;
source += bytes_per_line * r1_1 + (c1_1 >> 3) ;
destination += bytes_per_line * r1_2 + (c1_2 >> 3) ;
EGA_GRFX(5,1) ; /* установить режим записи 1 */
for(y = 0 ; y < rows ; y++)
{
- 9-24 -
for(x = 0; x < cols; x++)
*(destination++) = *(source++) ;
source += next_row ;
destination += next_row ;
}
EGA_GRFX(5,0) ; /* сбросить режим записи */
}
----------------------------------------------------------------
Поскольку регистр маски бита не пригоден для использования в
режиме записи 1, подпрограмма copy() будет копировать восемь эле-
ментов изображения исходных байтов в байты назначения. Другими
словами, режим записи 1 применяется для манипулирования байтами,
а не элементами изображения. Режим записи 1 можно использовать
для сохранения области экрана на невидимой странице. Это полезно
для реализации спускающихся меню. Область под спускающимся меню
может быть сохранена на невидимой странице и затем восстановлена
после использования меню. Режим записи 1 способен копировать дан-
ные только в другую область памяти EGA. Для чтения цвета из памя-
ти EGA требуется отдельное чтение четырех битовых матриц.
VGA имеет один новый режим записи. Режим записи 3 VGA сходен
с использованием пары регистров установки/сброса и разрешения ус-
тановки/сброса в режиме записи 0 EGA для установки цвета (приме-
няется подпрограммой line() программы 9-4). Разница заключается в
том, что в режиме записи 3 регистр разрешения установки/сброса не
используется, поэтому значение, содержащееся в регистре установ-
ки/сброса не маскируется регистром разрешения установки/сброса.
Чтение битовых матриц
Поскольку каждый байт адресного пространства центрального
процессора, зарезервированного для EGA, представляет 4 байта гра-
фической памяти, память EGA не может быть прочитана непосредс-
твенно центральным процессором. EGA возвратит байт из битовой
матрицы, выбранной в регистре выбора чтения битовой матрицы. Счи-
тываемую матрицу необходимо установить перед чтением смещения
EGA, содержащего интересующие Вас элементы изображения.
Для определения цвета заданного элемента изображения требует-
ся отдельное чтение из каждой битовой матрицы. Каждый бит 4-бито-
вого значения цвета расположен в одной из четырех битовых матриц.
Самый значимый бит значения цвета находится в битовой матрице 3,
а менее значимый бит в битовой матрице 0. Регистр выбора чтения
матрицы имеет индекс 4 в графических чипах 1 и 2 EGA. Так как
каждая битовая матрица EGA должна считываться отдельно, значение
регистра выбора чтения матрицы соответствует только одной битовой
матрице EGA в один момент времени.
Функция в программе 9-7 возвращает цвет элемента изображения
на дисплее. Так же как и fastdot(), она читает цвет точки в не-
сколько раз быстрее, чем эквивалентная подпрограмма BIOS.
Смещение байта, содержащего элемент изображения, определяется
точно также, как и в подпрограмме fastdot(). Значение маски бита
вычисляется определением номера бита изменяемого байта. Но значе-
ние маски бита не посылается в регистр маски бита EGA. Регистр
маски бита EGA не влияет на байты, читаемые EGA. Маска бита ис-
пользуется для изоляции элемента изображения от байта, считывае-
мого из битовой матрицы EGA. Биты затем прибавляются матрица за
- 9-25 -
матрицей к коду цвета элемента изображения. Регистр выбора чтения
матрицы выбирает матрицу для чтения. Битовые матрицы читаются в
обратном порядке (матрица 3, 2, 1, 0), так как это облегчает
трансляцию кода. Обратите внимание, что регистр выбора чтения
матрицы не сбрасывается в конце подпрограммы. При выполнении цик-