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

       

Регистр данных таблицы цветов (Look-up Table Data Register - LTDR)


Регистр используется для получения доступа к регистрам таблицы цветов. Для чтения и записи одного элемента таблицы цветов необходимо три раза прочитать (записать) содержимое регистра данных. При этом каждый раз считывается (записывается) шесть очередных битов. Первые шесть битов отвечают за интенсивность красного, вторые - зеленого и третьи - синего цвета.

Нельзя прерывать цикл чтения регистров таблицы цветов, состоящий из трех операций чтения, выполнением операции записи в другой регистр таблицы и наоборот. Во время доступа к регистру LTDR прерывания должны быть запрещены. Между операциями доступа к регистрам таблицы цвета необходимо выдержать временной интервал не менее 240 наносекунд.

D5-D0    Данные для обмена с регистрами таблицы цветов.

D7-D6    Не используется.

Программа VGA256 (листинг 4.13) записывает новые значения в таблицу цветов непосредственно через регистры цифро-аналогового преобразователя VGA. На экране монитора отображается пять вертикальных полос различного цвета. Каждая полоса состоит из 64 вертикальных линий. Интенсивность цвета этих линий плавно уменьшается слева на право.

Листинг 4.13. Файл VGA256.C

#include                <stdio.h>

#include                <conio.h>

#include                "sysp.h"

#include                "sysgraph.h"

#include                <dos.h>

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

int           main( void );

void        SetVideoMode( unsigned char );

void        Hello(void);

// Функция SetVgaDAC определена в файле DACTABLE.ASM



void __pascal __far           SetVgaDAC(unsigned, unsigned);

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

// Главная функция

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

int main( void )

{

 

RGB      color_table[256];

 

int          error, x_num, y_num;

 

unsigned             i, j, iii;

 

unsigned             seg_table,off_table;

 

unsigned char   far *ptr;

// Записываем в массив 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

  SetVideoMode( 0x13 );

// Определяем сегмент и смешение массива color_table

  ptr = (unsigned char far*) &color_table[0];

  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();

// Плавно гасим изображение на экране, уменьшая значения

// регистров таблицы цветов

  for(i=0;i<320;i++){

                for(iii=0;iii<256;iii++)  {

                                (color_table[iii]).red =

                                                ((color_table[iii]).red>6) ?

                                                color_table[iii].red-1 : 1;

                                (color_table[iii]).green =

                                                ((color_table[iii]).green>6) ?

                                                color_table[iii].green-1 : 1;

                                (color_table[iii]).blue =



                                                ((color_table[iii]).blue>6) ?

                                                color_table[iii].blue-1 : 1;

                }

                SetVgaDAC(seg_table,off_table);

  }

// Ожидаем нажатие на клавишу

  SetVideoMode( 0x3 );

  Hello();

  return 0;

}

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

// Функция SetVideoMode устанавливает режим работы

// видеоадаптера, заданный параметром vmode

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

void SetVideoMode( unsigned char vmode ) {

  union  REGS    inregs, outregs;

  inregs.h.ah = 0x0;

  inregs.h.al = vmode;

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

}

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

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

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

void Hello(void) {

  printf("\nCopyright (C)Frolov G.V.,1995. "

                                 "E-mail: frolov@glas.apc.org\n");

}

Функция SetVgaDAC, предназначенная для заполнения таблицы цветов, представлена в листинге 4.14.

Листинг 4.14. Файл DACTABLE.ASM

TITLE      DACTABLE.ASM

NAME     DACTABLE

PAGE      55,132

P286

IDEAL

NOWARN BRK

SEGMENT VGA_TEXT WORD PUBLIC 'CODE'

ASSUME                cs:VGA_TEXT

;============================================================

; Функция

; void SetVgaDAC(unsigned seg_table, unsigned off_table)

;============================================================

off_table               EQU        [bp+6]

seg_table             EQU        [bp+8]

  PUBLIC                SETVGADAC

  PROC   SETVGADAC FAR

  enter    0, 0

  ; Сохраняем регистры 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

  leave

  ret 4

  ENDP    SETVGADAC

ENDS      VGA_TEXT

END


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