Режим 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
Содержание раздела