Программирование видеоадаптеров

       

Атрибуты символов (монохромный режим)


Назначение полей байта атрибутов в монохромном режиме сходно с их назначениями в цветном режиме (см. выше). Биты D0-D2 управляют типом символа, который может быть обычным, мигающим или подчеркнутым, биты D4-D6 могут выбрать обратный (инвертированный) символ.

Бит D3 играет различную роль в зависимости от того, сколько таблиц знакогенератора одновременно являются активными. Если активной является одна таблица, то бит D3 используется для управления интенсивностью символа.

Если одновременно определены две таблицы знакогенератора, тогда бит D3 также задает таблицу знакогенератора, которая будет использована при отображении данного символа.

Бит D7 выполняет две различные функции в зависимости от состояния регистра режима контроллера атрибутов. Он управляет либо интенсивностью фона, либо миганием символа. По умолчанию бит D7 управляет миганием символа.

Перечислим все возможные значения атрибутов символов в текстовом монохромном режиме:

Атрибут

Внешний вид символа



00000000b (00h)

Черный символ на черном фоне

00000001b (01h)

Подчеркнутый символ

00000111b (07h)

Обычный символ (светлый символ на черном фоне)

00001001b (09h)

Подчеркнутый символ с повышенной  интенсивностью

00001111b (0Fh)

Символ с повышенной интенсивностью

01110000b (70h)

Обратное отображение символа (черный символ на светлом фоне)

10000001b (81h)

Подчеркнутый мигающий символ

10000111b (87h)

Мигающий символ

10001001b (89h)

Подчеркнутый мигающий символ с повышенной интенсивностью

11110000b (0F0h)

Мигающее обратное отображение символа

В случае использования других значений атрибутов результат зависит от конкретной модели видеоадаптера.

Теперь приведем программу TEXTATTR (листинг 3.1), иллюстрирующую непосредственный доступ к видеопамяти в текстовых режимах работы адаптера. При запуске программы TEXTATTR вы должны указать ей два числовых параметра.

Первый параметр определяет режим работы видеоадаптера. Вы можете задать любой текстовый режим. Второй параметр управляет атрибутами символов, отображаемых на экране монитора. Если второй параметр равен 0, то бит D7 байта атрибутов управляет интенсивностью фона символов, а если он равен 1, то бит D7 байта атрибутов управляет миганием символов.


Листинг 3.1. Файл TEXTATTR.C

#include                <stdio.h>

#include                <conio.h>

#include                <dos.h>

// Файл для определения макрокоманды FP_MAKE

#include                "sysp.h"

// Файл для определения структуры VIDEOBUF

#include                "sysgraph.h"

// Описание функций

void        SetVideoMode( unsigned char vmode );

void        SetBlinkIntensity( unsigned char mode );

int           GetColumn(void);

int           GetVideoBuf(int);

void        Hello(void);

int           main( int, char ** );

//======================================================

// Главная функция программы

//======================================================

int main( int argc, char * argv[] )

{

  union REGS         inregs, outregs;

  VIDEOBUF           _far *vbuf, _far *ptr_vbuf;

  unsigned char   background, foreground;

  unsigned char   char_attr;

  int          vmode, bl_in_mode;

  char      szText[4];

  // Проверка командной строки программы

  if( argc != 3 )

  {

                Hello();

                return -1;

  }

  // Разбор строки параметров

  sscanf(argv[1],"%d",&vmode);

  sscanf(argv[2],"%d",&bl_in_mode);

  // Если указан графический режим, завершаем программу

  if(vmode > 3 && vmode != 7)

                return(-2);

  // Если неправильно указан параметр <интенсивность>,

  // завершаем программу

  if((bl_in_mode != 0)&&(bl_in_mode != 1))

                return(-3);

  // Устанавливаем новый режим работы видеоадаптера,

  // указанный параметром <режим>

  SetVideoMode((unsigned char) vmode );

  // Выбираем как будут интерпритироваться атрибуты

  // символов. Если параметр <интенсивность> равен 0

  // атрибуты управляют интенсивностью цвета символов,

  // если параметр равен 1 атрибуты управляют миганием

  //символов

  SetBlinkIntensity((unsigned char) bl_in_mode );

  // Определяем адрес начала активной страницы

  // видеопамяти



  ptr_vbuf = vbuf= (VIDEOBUF _far *)

                FP_MAKE(GetVideoBuf((unsigned char) vmode ),0);

  // Отображаем на экране массив символов, имеющих

  // различные атрибуты

  for( background=0; background<16; background++)

  {

                for( foreground=0; foreground<16; foreground++)

                {

                                char_attr =

                                                                (unsigned char)((background<<4) | foreground);

                                sprintf( szText, "%02X", char_attr );

                                // Отображаем на экране символ. Записываем

                                // в видеопамять код символа и его атрибут

                                ptr_vbuf->chr =

                                                szText[0];             ptr_vbuf->attr = char_attr;

                                ptr_vbuf++;

                                ptr_vbuf->chr =

                                                szText[1]; ptr_vbuf->attr = char_attr;

                                ptr_vbuf++;

                }

                ptr_vbuf = vbuf = vbuf + GetColumn();

  }

  // Ожидаем нажатие на любую клавишу клавиатуры

  getch();

  // Устанавливаем текстотвый режим номер 3

  SetVideoMode(3);

  return 0;

}

//======================================================

// Функция возвращает сегментный адрес активной страницы

// видеопамяти (учитывается значение регистров смещения

// адреса видеопамяти)

//======================================================

int GetVideoBuf(int vmode) {

  unsigned vbase;

  unsigned adr_CRT;

  unsigned high;

  unsigned low;

  unsigned offs;

  // В зависимости от режима видеоадаптера базовый адрес

  // видеопамяти может быть 0xb000 или 0xb800

  vbase = (vmode == 7) ? 0xb000 : 0xb800;

  // Определяем адрес порта контроллера ЭЛТ

  adr_CRT = *(unsigned _far *)(FP_MAKE(0x40,0x63));

  // Считываем содержимое регистров начального адреса

  outp(adr_CRT,0xc);



  high = inp(adr_CRT+1);

  outp(adr_CRT,0xd);

  low = inp(adr_CRT+1);

  offs = ((high << 8) + low) >> 4;

  // Добавляем к базовому адресу видеопамяти смещение,

  // взятое из регистров начального адреса

  vbase += offs;

  return(vbase);

}

//======================================================

// Функция возвращает количество символов в строке

//======================================================

int GetColumn(void) {

  // Считываем содержимое переменной BIOS, расположенной по

  // адресу 0000:044Ah. В ней записано количество символов

  // в строке для текущего режима

  return(*(int _far *)(FP_MAKE(0x40,0x4a)));

}

//======================================================

// Функция устанавливает режим работы видеоадаптера, заданный

// параметром vmode

//======================================================

void SetVideoMode( unsigned char vmode ) {

  union  REGS    inregs, outregs;

  // Устанавливаем режим vmode

  inregs.h.ah = 0x0;

  inregs.h.al = vmode;

  int86( 0x10, &inregs, &outregs );

}

//======================================================

// Функция управляет назначением атрибутов символов.

//  mode = 0 атрибут управляет интенсивностью цвета символов

//  mode = 1 атрибут управляет миганием символов

//======================================================

void SetBlinkIntensity( unsigned char mode ) {

  union  REGS    inregs, outregs;

  inregs.h.ah = 0x10;

  inregs.h.al = 0x3;

  inregs.h.bl = mode;

  int86( 0x10, &inregs, &outregs );

}

//======================================================

// Функция выводит на экран краткую справку о программе

//======================================================

void Hello(void) {

  printf(   "\nCopyright (C)Frolov G.V.,1995. E-mail:"

                                                "frolov@glas.apc.org\n"

                                "\nФормат вызова: TEXTATTR <режим> <интенсивность>"

                                "\n   <режим>: любые текстовые режимы"



                                "\n   <интенсивность>: 0 - интенсивность цвета, "

                                "1 - мигание символа" );

}

Исходный текст включаемого файла SYSP.H, который используется в примере TEXTATTR.C, а также в других примерах книги, представлен в листинге 3.2. Файл SYSP.H содержит определение макрокоманды FP_MAKE, служащей для получения дальнего указателя из сегмента и смещения.

Листинг 3.2. Файл SYSP.H

// Макрокоманда FP_MAKE составляет дальний указатель

// из сегмента и смещения

#define FP_MAKE(seg,off) ((void far *)                                          \

  ((((unsigned long) (unsigned)(seg)) << 16L) |            \

  ((unsigned long) (unsigned) (off))))

Включаемый файл SYSGRAPH.H содержит определения нескольких типов структур, используемых в примерах нашей книги. Исходный текст файла SYSGRAPH.H представлен в листинге 3.3.

Листинг 3.2. Файл SYSGRAPH.H

#pragma pack(1)

// Структура для определения символа и его атрибута

typedef struct _VIDEOBUF_ {

  unsigned char chr;

  unsigned char attr;

} VIDEOBUF;

// Структура для доступа к переменным видеофункций BIOS

typedef struct _BIOS_VAR_ {

  unsigned char  bEquipFlags;

  unsigned char  bReserv1[0x38];

  unsigned char  bVideoMode;

  unsigned       wColumns;

  unsigned       wPageLength;

  unsigned       wVidStart;

  unsigned       w8CursorPos[8];

  unsigned       wCursorShape;

  unsigned char  bActivePage;

  unsigned       wAddrCRT;

  unsigned char  bRegMode;

  unsigned char  bRegPalette;

  unsigned char  bReserv2[0x1D];

  unsigned char  bRows;

  unsigned       wCharHigh;

  unsigned char  bInfo;

  unsigned char  bInfoTwo;

  unsigned char  bReserv3[0x1F];

  void far       dwSavePtr;

} BIOS_VAR;

// Структура для заполнения таблицы цветов (таблицы ЦАП)

typedef struct _RGB_ {

  unsigned char red;

  unsigned char green;

  unsigned char blue;

} RGB;

#pragma pack()


Содержание раздела