4.5.2. Работа с SVGA-режимами

В режиме VGA 320x200 с 256 цветами для отображения видеопамяти на ос­новное адресное пространство используется 64 000 байт, располагающихся с ад­реса OAOOOh:OOOOh. Дальнейшее увеличение разрешения или числа цветов при­водит к тому, что объем видеопамяти превышает максимальные границы сегмента в реальном режиме (65 535 байт), а затем и размер участка адресного ства, отводимого для видеопамяти (160 Кб, от OAOO0h:0O00h до 0B800h:0FFFFh. С адреса 0C800h:0000h начинается область ROM BIOS). Чтобы вывести изобра -жение, используются два механизма - переключение банков видеопамяти для ре­ального режима и LFB (линейный кадровый буфер) для защищенного.

Во втором случае видеопамять отображается на непрерывный кусок адресного пространства, но начинающегося не с OAOOOOh, а с какого-нибудь другого адреса, так чтобы весь массив видеопамяти, который может занимать несколько мегабайтов,

отобразился в одну непрерывную область. В защищенном режиме максимальный размер сегмента составляет 4 Гб, поэтому никаких сложностей с адресацией этого буфера    возникает. Буфер LFB можно использовать, только если

поддерживает спецификацию VBE 2.0 (см. пример в разделе 6.4).

В реальном режиме вывод на экран осуществляется по-прежнему копирова-ниєм данных в 64-килобайтный сегмент, обычно начинающийся с адреса но эта область памяти соответствует только части Чтобы вывести изображение в другую часть экрана, нужно вызвать функцию перемеще­ния окна (или, что то же самое, переключения банка видеопамяти), изменяющую область видеопамяти, которой соответствует сегмент OAOOOh. Например, в режи­ме 640x480 с 256 цветами требуется 307 200 байт для хранения всего видеоизоб­ражения. Заполнение сегмента 0A000h:0000h - 0A000h:0FFFFh приводит к за­краске приблизительно 1/5 экрана, перемещение окна А на позицию 1 (или переключение на банк 1) и повторное заполнение этой же области - к закраске следующей 1/5 экрана и т. д. Перемещение-окна осуществляется подфункцией 05 видеофункции 4Fh или передачей управления прямо на процедуру, адрес кото­рой можно получить, активизировав подфункцию 01, как будет ниже. Некоторые видеорежимы позволяют использовать сразу два таких

окна, окно А и окно В, так что можно записать 128 Кб данных, не вызывая прерывания.

Стандартные графические режимы SVGA могут быть 4-, 8-, 15-, 16-, 24- и 32-

битными.

4-битные режимы (1б цветов) VGA

012h: 640x480 (64 Кб) VESA VBE 1.0

102h: 800x600 (256 Кб)

104h: 1024x768 (384 Кб)

106h: 1280x1024 (768 Кб) Каждый пиксел описывается одним битом, для вывода цветного изображения

требуется программирование видеоадаптера на уровне портов ввода-вывода (раз­дел 5.10.4).

8-битные режимы (25б цветов) VGA

013h: 320x200 (64 Кб) VBE 1.0

100b: 640x400 (256 Кб) 101h: 640x480 (320 Кб)

103h: 800x600 ( 512 Кб) 105h: 1024x768 (768 Кб) 107h: 1280x1024 (1,3 Мб) VBE 2.0

120h: 1600x1200 (1,9 Мб)

Каждый пиксел описывается ровно одним байтом. Значение байта - номер цвета из палитры, значения цветов которой можно изменять, например вызывая подфункцию 09h видеофункции 4Fh.

15- битные режимы (32 К цветов) VBE 1.2

lODh: 320x200 (128 Кб)

HOh: 640x480 (768 Кб)

1131т: 800x600(1 Мб)

1161т: 1024x768 (1,5 Мб)

119h: 1280x1024 (2,5 Мб) VBE 2.0

121h: 1600x1200 0,8 Мб) Каждый пиксел описывается ровно одним словом (16 бит), в котором биты 0-4 содержат значение синей компоненты цвета, биты 5-9 - зеленой, а биты 10-14 -красной. Бит 15 не используется.

16- битные режимы (64 К цветов) VBE 1.2

10Eh: 320x200 (128 Кб)

lllh: 640x480(768 Кб)

114h: 800x600(1 Мб)

117h: 1024x768 (1,5 Мб)

llAh: 1280x1024(2,5 Мб) VBE 2.0

122h: 1600x1200 (3,8 Мб) Так же как и в 15-битных режимах, каждый пиксел описывается, ровно одним словом. Обычно биты 0-4 (5 бит) содержат значение синей компоненты, биты 5-10 (6 бит) - зеленой, а биты 11-15 (5 бит) - красной. В нестандартных режимах число битов, отводимое для каждого цвета, может отличаться, так что при их ис­пользовании следует вызвать подфункцию 01 видеофункции 4Fh и получить ин­формацию о видеорежиме, включающую битовые маски и битовые смещения для цветов.

24-битные и 32-битные режимы (16 М цветов) VBE 1.2

10Fh: 320x200 (192 Кб)

112k 640x480 (1 Мб)

115h: 800x600 (1,4 Мб) -

118h: 1024x768 (2,3 Мб)

llBh: 1280x1024 (3,7 Мб) В режимах с 24-битным и 32-битным цветом каждому пикселу на экране соот­ветствуют три байта и одно двойное слово (4 байта). Если видеорежим использу­ет модель памяти 6 (Direct Color), то младший байт (байт 0) содержит значение синего цвета, байт 1 содержит значение зеленого, байт 2 - значение красного, а байт 3 - в 32-битных режимах резервный и используется либо для выравнива­ния, либо содержит значение для альфа-канала. Некоторые видеорежимы могут использовать не Direct Color, a YUV (модель памяти 7) - здесь младший байт со­ответствует красного, байт 1 - насыщенности синего, а байт 2 -яркости.

Видеоадаптер может поддерживать и собственные нестандартные видеорежи­мы. Список их номеров можно получить, вызвав подфункцию а получить информацию о режиме по его номеру - вызвав подфункцию Olh видеофункции 4Fh. Более того, для стандартных режимов также следует вызывать подфункцию Olh, чтобы проверить реальную доступность режима (например, режим может быть в списке, но не поддерживаться из-за нехватки памяти). VBE 2.0 видеоадаптерам не поддерживать никаких стандартных режимов вообще,

INT 10h АН- 4Fh, AL = 00: Получить общую SVGA-информацию

Вход:  AX = 4FOOh

ES.DI = адрес буфера (512 байт) Выход: AL = 4Fh, если функция поддерживается АН = 01, если произошла ошибка АН = 00, если данные получены и записаны в буфер

Буфер для общей SVGA-информации:

+00h: 4 байта- будет содержать VESA после вызова прерывания, чтобы получить поля, начиная с здесь надо предварительно записать строку VBE2

слово - номер версии VBE в двоично-десятичном формате - для

1.2, 0200h - для 2.0) +06h: 4 байта- адрес строки-идентификатора производителя +0Ah:4 байта- флаги:

бит 0: АЦП поддерживает 8-битные цветовые компоненты (см. подфун­кцию 08h) бит   видеоадаптер несовместим с VGA

бит 2: АЦП можно программировать только при обратном ходе луча бит 3: поддерживается спецификация аппаратного ускорения графики VBE/AF 1.0

бит 4: требуется вызов EnableDirectAccess перед использованием LFB бит 5: поддерживается аппаратный указатель мыши

бит 6: поддерживается аппаратный clipping

бит 7: поддерживается аппаратный BitBlt

биты 8-31 зарезервированы +0Eh: 4 байта - адрес списка номеров поддерживаемых видеорежимов (массив слов, последнее слово = OFFFFh, после которого обычно следует список нестандартных также заканчивающийся сло-

вом OFFFFh)

+12h: слово - объем видеопамяти в 64-килобайтных блоках слово - внутренняя версия данной реализации VBE

+ 16h: 4 байта - адрес строки с названием производителя 4 байта   - адрес строки с названием видеоадаптера +1 Eh: 4 байта - адрес строки с версией видеоадаптера +22h: слово     - версия VBE/AF (BCD, то есть OlOOh для 1.0) +24h: 4 байта - адрес списка номеров режимов, поддерживающих аппаратное

ускорение (если бит поддержки VBE/AF установлен в 1) +28h: 216 байт - зарезервировано VESA

байт - зарезервировано для внутренних данных VBE. Так, например,

в эту область копируются строки с названиями производителя,

видеоадаптера, версии и т. д.

INT 10h АН =4Fh, AL=> 01: Получить информацию о режиме

Вход:  АХ = 4F01h

СХ = номер SVGA-режима (бит 14 соответствует использованию LFB,

бит 13 - аппаратному ускорению) ES:DI = адрес буфера для информации о режиме (256 байт) Выход: AL = 4Fh, если функция поддерживается АН - Olh, если произошла ошибка АН =» 00h, если данные получены и записаны в буфер

Буфер для информации о SVGA-режиме:

+00h: слово - атрибуты режима:

бит 0: режим присутствует

бит 1: дополнительная информация (смещения 12h - lEh) присутству­ет (для VBE 2.0 эта информация обязательна и бит всегда уста­новлен)

бит 2: поддерживается вывод текста на экран средствами BIOS

бит 3: режим цветной

бит 4: режим графический

бит 5: режим несовместим с VGA

бит 6: переключение банков не поддерживается бит 7: LFB не поддерживается бит 8: не определен

бит 9: (для VBE/AF) приложения должны вызвать

EnableDirectAccess, прежде чем переключать банки

+02h: байт - атрибуты окна А:

бит    окно существует

бит 2: чтение из окна разрешено

бит 3: запись в окно разрешена

+03h: байт - атрибуты окна В

+04h: слово - гранулярность окна - число килобайтов, которому всегда кратен

адрес начала окна в видеопамяти (обычно 64) +06h: слово - размер окна в килобайтах (обычно 64) +08h: слово - сегментный адрес окна А (обычно OAOOOh)

+OAh: слово - сегментный адрес окна В

I    Основы программирования для MS DOS

слово +12h: слово

слово +16h: байт +17h: байт +18h: байт

+19h: байт +lAh: байт

+lBh:

+OCh: 4 байта - адрес процедуры перемещения окна (аналог подфункций 05h, но выполняется быстрее)

- число целых байтов в логической строке

- ширина в пикселах (для графики) или символах (для текста)

- высота в пикселах (для графики) или символах (для текста)

- высота символов в ширина символов в пикселах

- число плоскостей памяти (4 - для 1 - для обычных, число переключений банков, требуемое для доступа ко всем битам    или 8), - для модели памяти 5) число битов на пиксел

- число банков для режимов, в которых строки группируются в бан­ки (2 - для CGA, 4 - для HGC)

байт - модель памяти: 00h - текст -

02h - HGC-графика

03h - EGA-графика (16 цветов)

04h - VGA-графика (256 цветов в одной плоскости)

05h - Режим X (256 цветов в разных плоскостях)

06h - RGB (15-битные и выше)

07h-YUV

08h -       - зарезервированы VESA - FFh - нестандартные модели +lCh: байт - размер банка в килобайтах (8 - для CGA и HGC, 0 - для остальных) число видеостраниц

- зарезервирован

битовая маска красной компоненты первый бит красной компоненты битовая маска зеленой компоненты первый бит зеленой компоненты битовая маска синей компоненты первый бит синей компоненты битовая маска зарезервированной компоненты

- первый бит зарезервированной компоненты 0: поддерживается перепрограммирование цветов (подфункция 09h)

бит 1: приложение может использовать биты в зарезервированной компоненте +28h: 4 байта - физический адрес начала LFB

+2Ch: 4 байта - смещение от начала LFB, указывающее на первый байт после

конца участка памяти, отображающейся на экране

+30h: слово - размер памяти в LFB, не отображающейся на экране, в килобайтах +32h: 206 байт - зарезервировано

+ШЬ: байт ■ +1ЕЬ: байт +1Еп:байт -+20п: байт ■ +21Ь: байт ■ +22Ь: байт ■ +23п: байт -+24Ь: байт ■ +25Ь: байт -+26Ь: байт +27Ь: байт -

INT 10h АН = 4Fh, AL = 02: Установить режим

Вход:  AX = 4F02h

ВХ = номер режима:

биты 0-6: собственно номер режима

бит У: видеопамять не очищается при установке режима, если все

следующие биты - нули бит 8: стандартный VBE SVGA-режим бит 9: нестандартный SVGA-режим биты 10-12: зарезервированы бит 13: режим использует аппаратное ускорение бит 14: режим использует LFB

бит     видеопамять не очищается при установке режима Кроме того, специальный номер режима соответствует доступу ко всей

видеопамяти и может использоваться для сохранения ее содержимого.

Выход: AL = 4Fh, если функция поддерживается

АН    00, если режим установлен

АН = 01 или 02, если произошла ошибка

INT 10h АН = 4Fh, AL = 03: Узнать номер текущего видеорежима ' Вход:    AX = 4F03h "

Выход: AL = 4Fh, если функция поддерживается ВХ = номер режима

INT 10h АН =4FhAL = 05: Перемещение окна (переключение банка видеопамяти)

Вход:  АХ = 4F05h

ВН = 00 - установить окно ВН = 01 - считать окно BL - 00 - окно А BL = 01 - окно В

DX = адрес окна в единицах гранулярности (номер банка), если ВН = О

Выход: AL = 4Fh, если функция поддерживается

DX = адрес окна в единицах гранулярности (номер банка), если ВН = 1 АН = 03, если функция была вызвана в-режиме, использующем LFB

Всегда предпочтительнее переключать банки прямым дальним вызовом проце­дуры, адрес которой возвращается подфункцией 01Ьв блоке информации о видео­режиме. Все параметры передаются в процедуру точно так же, как и в подфункцию 05h, но содержимое регистров АХ и DX по возвращении не определено.

INT 10h АН = 4FhAL = 07: Установка начала изображения Вход:    АХ = 4F07h ВН - 00

BL = 00 - считать начало изображения ■

BL = 80h - установить начало изображения (в VBE 2.0 автоматически выполняется при следующем обратном ходе луча)

6 Assembler для DOS

g|;   Основы программирования для MS DOS

СХ = первый изображаемый пиксел в строке (для BL = 80h) DX = первая изображаемая строка (для BL = 80h) Выход: AL = 4Fh, если функция поддерживается АН = 01, если произошла ошибка АН = 00, если функция выполнилась успешно ВН = 00 (для BL = 00)

СХ = первый изображаемый пиксел в строке (для BL = 00)

DX = первая изображаемая строка (для BL - 00)

С помощью этой функции можно выполнять как плавный сдвиг экрана, пере­мещая начало изображения на одну строку за один раз, так и быстрый показ двух разных изображений, изменяя одно, пока на экране находится другое, — своего рода эффект плавной анимации.

scrolls.asm

Изображает в разрешении 1024х768х64К окрашенный конус, плавно перемещать по экрану стрелками вверх и вниз.

который можно

start:

.model , code

.386

org

mov mov

mov

int tiny

ЮОгс

ax,4F01h cx,116h

di,offset vbe_mode_buffer

■ 10h

Используется

СОМ-файл.

команда shrd.

Получить информацию

1024х768х64К

видеорежиме.

Здесь для простоты опущена проверка наличия режима.

mov mov int

push

pop eld ax,4F02h

bx,116h

10h

word ptr

es

Установить режим.

[vbe_mode_buffer+8]

Поместить в ES адрес (обычно AOOOh).

начала видеопамяти

конуса

на экран.

 

mov

-1

Началвное значение цвета (белый).

mov

si,100

Началвный радиус.

mov

bx,300

Номер столбца.

mov

"1 •

ax,200

Номер строки.

J .

inc

si

Увеличитв радиус круга на 1.

inc

ax

Увеличитв номер строки.

inc

bx

Увеличитв номер столбца.

call

fast_circle

Нарисоватв круг.

sub

cx,0000100000100001b

Изменитв цвет.

cmp

Si,350

Если еще не нарисовано 350 кругов,

о

Графические видеорежимы

jb

main_loop

 

; продолжить.

xor

сх,сх

;

Иначе: выбрать черный цвет,

call

fast_circle

;

нарисовать последний круг.

; Плавное перемещение изображения

по экрану с помощью функции 4F07h.

xor

bx,bx.

 

BX = 0 - установить начало экрана.

xor

dx, dx

 

Номер строки = 0.

 

 

 

Номер столбца в CX уже ноль.

main_loop_2:

 

 

 

mov

ax,4F07h

 

 

int

10h

 

Переместить начало экрана.

mov

ah,7

 

Считать нажатую клавишу с ожиданием,   без эха

int

21h

 

и без проверки на Ctrl-Break.

test

al.al

 

Если это обычная клавиша -

jnz

exit_loop_2

 

завершить программу.

int

21h

 

Иначе:   получить расширенный ASCII-код.

cmp

al,50h

 

Если это стрелка вниз

je

key_down

 

 

cmp

al,48h

 

или вверх - вызвать обработчик.

je

key_up

 

 

exit_loop_2:

 

 

Иначе - завершить программу.

mov

ax,3

 

Текстовый режим.

int

10h

 

 

ret

 

 

Завершить

key_down:

 

 

Обработчик  нажатия   стрелки вниз.

dec

dx

 

Уменьшить номер экрана.

jns

main_loop_2

 

Если знак не изменился - продолжить цикл.

 

 

 

Иначе (если номер был 0, а стал -1) -

 

 

 

увеличить номер строки.

key_up:

 

 

Обработчик  нажатия   стрелки вверх.

inc

dx

 

Увеличить номер строки начала экрана.

jmp

short

 

; Процедура

вывода точки на

экран

в 16-битном видеорежиме.

;   Вход:   DX =

номер строки,

BX = номер столбца,   ES = OAOOOh,   CX = цвет.

; Модифицирует АХ.

 

 

putpixel16b:

 

 

 

push

dx

 

 

push

di

 

 

xor

di.di

 

 

shrd

di,dx,6

 

DI = номер строки х 1024 mod 65 536. •

shr

dx,5

 

DX = номер строки / 1024 х 2.

inc

dx

 

 

cmp

dx,current_

bank

Если номер банка для выводимой точки

jne

bank_switch

 

отличается то текущего  - переключить банки.

switched:

 

 

 

add

di, b.x

 

Добавить к DI номер столбца.

mov

ax,

 

Цвет в AX.

shl

stosw

pop

pop

ret di,1

di dx ;  Ш = Ш х 2, так как- адресация идет в словах. ;   Вывести точку на экран. ;  Восстановить регистры.

bank_switch: ; Переключение банка.

push bx

bx, bx

xor

;  ВХ = 0 -> установить начало экрана.

; Сохранить новый номер текущего банка.

call

ptr

; Переключить банк.

pop

bx

 

jmp

short switched

 

; Алгоритм рисования круга, используя только сложение, вычитание и сдвиги

;   (упрощенный алгоритм промежуточной точки).

;  Вход: SI =

радиус, СХ = цвет, АХ

= номер столбца центра круга.

; ВХ = номер

строки центра круга модифицирует DI, DX.

fast circle:

 

 

push

si

 

push

ax

 

push

bx

 

xor

di.di ;

ВІ - относителвная Х-координата текущей точ

de'c

di

(31 - относителвная У-координата, начальное

mov

ax, 1

значение - радиус).

sub

ax, si ;

АХ - наклон (началвное значение 1-Радиус):.

circlejoop:

 

 

inc

di ;

Следующий X (началвное значение - 0). :

cmp

di.si ;

Цикл продолжается, пока X < У.

ja

exit_main_loop

 

pop

bx           ' ;

ВХ = номер строки центра круга.

pop

dx

БХ = номер столбца центра круга.

push

dx

 

push

bx

 

push

ax ;

Сохранитв АХ (ритріхе116Ь его изменяет). :

add

;

Вывод восвми точек на окружности:

add

dx, si

 

call

;

центр_Х + X, центр_У + У, :

sub

dx.si

 

sub

dx, si

 

call

;

центр_Х + X, центр_У - У,

sub

bx, di

 

sub

bx, di

 

call

;

центр_Х - X, центр_У - У,

add

dx, si

 

add

dx, si

 

call

;

центр_Х - X, центр_У + У,

sub

dx, si

 

add

dx, di

 

Графические видеорежимы

add

bx, di

add

bx,si

call

putpixel16b

sub

dx, di

sub

dx, di

call

putpixel16b

sub

bx, si

sub

bx, si

call

putpixe!16b

add

dx, di

add

dx, di

call

putpixel16b

pop

ax

test

ax

js

slopjiegative

mov

dx.di

sub

dx, si

shl

dx,1

' inc

dx

add

ax, dx

dec

si

jmp

circle_loop

lative:

 

mov

dx, di

shl

dx, 1

inc

dx

add

ax, dx

jmp

clrcle_loop

n_loop:

 

pop

bx

pop

ax

pop

si

ret

 

current_bank dw vbe_mode_buffer:

end start

центр_Х + Y,   центр_У + X,

центр_Х + X,  центр„У - X,

центр_Х - Y,  центр,Y - X,

центр_Х - Y,  центр_У + X.

Если наклон положительный,

наклон = наклон + 2(Х Y) + 1, Y = Y - 1,

Если наклон отрицательный,

наклон = наклон + 2Х + 1, и Y не изменяется.

Номер текущего банка.

Начало буфера данных о видеорежиме.

В этом примере для наглядности отсутствуют необходимые проверки на под­держку VBE (все прерывания должны возвращать 4Fh в AL), на поддержку ви­деорежима (атрибут видеорежима в первом байте буфера, заполняемого подфун­кцией 02) или на объем видеопамяти (должно быть как минимум 2 Мб) и на другие ошибки (все прерывания должны возвращать 0 в АН).

Для вывода точки на экран используется выражение типа

номер_банка = номер.строки х байт_в_строке / байт_в_банке смещение = номер_строки х. байт_в_строке MOD байт_в_банке

Но так как и число байтов в строке, и число байтов в банке являются степеня­ми двойки, умножение, деление и вычисление остатка от деления можно заменить более быстрыми операциями сдвига, как это сделано в процедуре putpixell6b.

Переключение банков всегда отнимает значительное время, так что по возмож­ности программированием для SVGA-режимов лучше всего заниматься в 32-бит­ном режиме с линейным кадровым буфером, например используя DOS-расшири­тели, как показано в разделе 6.4.