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

       

Режим 320х400 пикселов, 256 цветов


Мы начнем рассмотрение нестандартных режимов с режима, имеющего разрешение 320х400 пикселов. Программирование этого режима является самым простым и безопасным, так как при его установке нам не придется изменять содержимое регистров контроллера ЭЛТ.

Как мы указывали при описании режимов видеоадаптеров, в режиме 13h используется двойное сканирование. То есть в этом режиме - 320х200 пикселов на самом деле отображается не 200, а 400 линий сканирования. Перепрограммировав несколько регистров адаптера можно перевести его в режим 320х400 пикселов.

Рассмотрим последовательность действий, необходимую для перевода видеоадаптера в нестандартный режим с разрешением 320х400 пикселов:

       Устанавливаем при помощи функций BIOS стандартный режим номер 13h (320х200 пикселов, 256 цветов). При этом программируются все регистры видеоадаптера и нам останется только изменить содержимое нескольких регистров.

       Изменяем структуру видеопамяти, чтобы иметь возможность адресовать 256 Кбайт памяти. Для этого в регистре определения структуры памяти синхронизатора запрещаем режимы в которых доступ по разным адресам (кратным двум и/или кратным четырем) осуществляется к различным цветовым слоям памяти. А в регистре режима работы графического контроллера сбрасываем в ноль бит управления четным/нечетным режимом. Это запрещает доступ по четным адресам к четным цветовым слоям, а по нечетным адресам - к нечетным цветовым слоям видеопамяти. Затем в регистре смешанного назначения графического контроллера сбрасываем бит управляющий сцеплением четных и нечетных слоев памяти. После этих действий видеопамять по своей структуре напоминает режим 10h, за исключением того, что каждый пиксел управляется одним байтом, расположенным в одном из слоев видеопамяти.

       Очищаем видеопамять (для одной или двух страниц по необходимости), так как при установке режима 13h BIOS очищает только первые 64 Кбайт из 256 Кбайт. Остальная часть видеопамяти может содержать данные, которые  появятся на экране монитора после перепрограммирования контроллера ЭЛТ.


       Выключаем режим двойного сканирования. Для этого сбрасываем бит управления двойным сканированием и устанавливаем высоту символов равную единице.

       Переводим контроллер ЭЛТ в режим побайтовой адресации видеопамяти. Для этого выключаем режим адресации по двойным словам в регистре положения подчеркивания символа и включаем режим адресации по байтам в регистре управления режимом работы. Теперь по каждому адресу расположено четыре байта в различных цветовых слоях видеопамяти.

Приведем программу E256MRES, реализующую изложенный алгоритм. Данная программа переводит видеоадаптер в режим отображающий 256 цветов при разрешающей способности 320х400 пикселов (листинг 4.15).

Листинг 4.15. Файл E256MRES.C

#include    <conio.h>

#include    <stdlib.h>

#include    <stdio.h>

#include    <dos.h>

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



void SetVideoMode(unsigned char);

// Следующие функции определены в файле EVGAM.ASM

void __pascal __far Set320x400Mode( void );

void __pascal __far FullScr(unsigned char);

void __pascal __far

WritePixel(unsigned, unsigned, unsigned char);

unsigned char __pascal __far

ReadPixel(unsigned, unsigned, unsigned char);

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

void main( void ){

  unsigned             i;

  char                      ch = 13;

  // Устанавливаем режим 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++) {

                FullScr( (unsigned char) i );

                ch = getch();



  }

  // Возвращаемся в текстовый режим

  SetVideoMode(3);

  printf("\n   (C) Frolov G.V., 1992-1995 \n\n");

}

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

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

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

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

void SetVideoMode( unsigned char vmode ) {

  union  REGS    inregs, outregs;

  inregs.h.ah = 0x0;

  inregs.h.al = vmode;

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

}

Основные функции, предназначенные для выбора нестандартного режима, записи и чтения пикселов, а также заполнения экрана монитора, написаны на языке ассемблера. Исходный текст этих функций содержится в листинге 4.16.

Листинг 4.16. Файл EVGAM.ASM

TITLE      EVGAM.ASM

NAME     EVGAM

PAGE      55,132

P286

IDEAL

NOWARN BRK

INCLUDE "evga.inc"

SEGMENT EVGA_TEXT WORD PUBLIC 'CODE'

ASSUME                cs:EVGA_TEXT

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

; void Set320x400Mode( void )

; Установка режима 320х400 пикселов, 256 цветов.

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

PUBLIC  SET320X400MODE

PROC     SET320X400MODE FAR

  enter    0, 0

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

  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,not 1fh

  ; Запрещаем двойное сканирование

  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

  leave

  ret

ENDP      SET320X400MODE

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



; void WritePixel(unsigned x, unsigned y,

; unsigned char color)

;

; Функция отображает на экране пиксел в заданных координатах,

; определенного цвета.

; x - x-координата пиксела (0-319),

; y - y-координата пиксела (0-399),

; color - цвет пиксела (0-255).

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

color      EQU        [bp+6]

y                              EQU        [bp+8]

x                              EQU        [bp+10]

PUBLIC  WRITEPIXEL

PROC     WRITEPIXEL FAR

  enter    0, 0

  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

  leave

  ret 6

ENDP      WRITEPIXEL

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

; unsigned char ReadPixel(unsigned x, unsigned y, unsigned char color)

; Функция возвращает значение байта видеопамяти, определяющего пиксел

; с заданными координатами.

; x - x-координата пиксела (0-319),

; y - y-координата пиксела (0-399).

; Return  цвет пиксела (0-255).

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

color      EQU        [bp+6]

y                              EQU        [bp+8]

x                              EQU        [bp+10]

PUBLIC  READPIXEL

PROC     READPIXEL FAR

  enter    0, 0

  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]

  xor        ah,ah

  pop       si

  leave

  ret 6



ENDP      READPIXEL

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

; void FullScr( unsigned char color )

; Закрашивает экран заданным цветом.

; color - цвет экрана (0-255).

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

color      EQU        [bp+6]

PUBLIC  FULLSCR

PROC     FULLSCR FAR

  enter    0, 0

  ;разрешаем запись данных во все четыре цветовых слоя

  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

  leave

  ret 2

ENDP FULLSCR

ENDS      EVGA_TEXT

END

Включаемый файл EVGA.INC, в котором определены различные константы для нестандартных режимов видеоадаптера, представлен в листинге 4.17.

Листинг 4.17. Файл EVGA.INC

; Сегмент видеопамяти для режима 13h

VGA_SEGMENT   EQU        0a000h

; Адрес индексного порта синхронизатора

SC_INDEX             EQU        3c4h

  ; Регистр разрешения записи цветового слоя

  CPWER                EQU        2

  ; Регистр определения структуры памяти

  MMR     EQU        4

; Адрес индексного порта графического контроллера

GC_INDEX             EQU        3ceh

  ; Регистр выбора читаемого слоя

  RPSR    EQU        4

  ; Регистр режима работы

  MDR      EQU        5

  ; Регистр смешанного назначения

  MIR       EQU        6

; Адрес индексного порта контроллера ЭЛТ (цветной режим)

CRTC_INDEX        EQU        3d4h

  ; Регистр высоты символов текста

  MSLR   EQU        9

  ; Регистр начального адреса

  SAR_h  EQU        0ch

  ; Регистр положения подчеркивания символа

  ULR       EQU        14h

  ; Регистр управления режимом

  MCR      EQU        17h

; Регистр определения различных режимов работы

MOR       EQU        3c2h

; Режим 320х400 пикселов

  ; Количество пикселов по вертикали

  SCREEN_HEIGHT               EQU        400

  ; Количество пикселов по горизонтали

  SCREEN_WIDTH                EQU        320

; РЕЖИМ 360х480 пикселов

  ; Количество пикселов по вертикали (режим 320х400)

  SCREEN_HEIGHT_H          EQU        480

  ; Количество пикселов по горизонтали (режим 360х480)

  SCREEN_WIDTH_H           EQU        360


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