Программирование игр для Windows. Советы профессионала

         

Сверхскоростная очистка экрана


Экран в режиме 13h отображается в области памяти, начиная с адреса А000:0000 и по A000:FBFF. При этом каждый пиксель задается одним байтом. Давайте посмотрим на рисунок 2.3, чтобы лучше понять, как это происходит. В данной конфигурации каждый пиксель может принимать одно из 256 значений, но эти значения не являются, как можно было бы подумать, кодом цвета пикселя. Они представляют собой видимое значение цвета.

Теперь поговорим о том, как это работает. Значение пикселя, а это байт, адрес которого определяет положение пикселя на экране, используется в качестве индекса в гигантской таблице цветов. Таким образом, значение пикселя 26 не означает цвет номер 26. Наоборот, это значит «индекс, указывающий на 26-й элемент таблицы и использующий значение этого поля».

Примечание

Таблица цветов содержит по одному байту для каждого из первичных цветов, Однако реально используются только шесть первых бит каждого байта. Таким образом, каждый из элементов таблицы состоит из трех байтов, определяющих значения трех основных цветов; красного (R - Red), зеленого (G - Green) и голубого (В — Blue), которые в сумме позволяют представить 262114 цветов. Однако размер таблицы ограничен 256-ю элементами, поэтому и на экране может одновременно присутствовать не более 256 цветов.

В видеоиграх, которые нас привлекают, экран перерисовывается от 15 до 30 раз в секунду. Таким образом, перед тем как нарисовать что-то новое на экране, нам необходимо удалить старое изображение. Для того чтобы это делать, надо найти способ быстрого заполнения видеобуфера каким-нибудь значением цвета, например, цветом фона.

Это значение будет заполнять всю видеопамять, а, следовательно, и весь экран в виде цвета, Самый быстрый способ сделать это - воспользоваться ассемблерной инструкцией STOSW. Вы можете спросить: «А зачем использовать STOSW, когда каждый пиксель — это байт, в то время как STOWS оперирует со словами (WORD)?". На этот вопрос можно дать два ответа:

§          Во-первых, коль мы можем записать один байт в видеопамять, то значит, можем записать и два;




§          Во-вторых, нам надо минимизировать количество обращений к видеопамя­ти, поскольку она работает примерно в 10 раз медленнее, чем обычная память. Поэтому, предпочтительнее писать не по одному байту, а сразу по два.

Листинг 2.10 показывает ассемблерную функцию для заполнения экрана определенным цветом, а Листинг 2.11 содержит программу на Си, тестирующую ее.

Листинг 2.10. Процедура, заполняющая экран (FILLA.ASM).



screen_ram EQU 0A000h       ; видеопамять в этом режиме начинается                            

; по адресу A000:0000h

.MODEL MEDIUM, С            ;устанавливаем модель памяти MEDIUM,                              

; соглашения по вызову языка Си

.CODE                       ; начало кодового сегмента

PUBLIC Fill_Screen          ; объявляем процедуру общедоступной,

Fill_Screen PROC FAR С color : WORD ;функция принимает один параметр

mov AX, screen_ram            ;ES:DI должно указывать на видеопамять

mov ES,AX

xor di,di                    ;обнуляем DI

mov CX,320*200/2            

;количество слов, которое надо вывести

mov AL,BYTE PTR color        ;помещаем в регистр AL код цвета

mov AH,AL                    ; этот же код помещаем в регистр АН

rep STOSW                    ;эта команда заполняет видеопамять

; выбранным цветом с максимально

; возможной скоростью

RET                          ;выход из процедуры

Fill_Screen ENDP             ;конец процедуры

END                          ;конец кодового сегмента

Листинг 2.11, Программа на Си для тестирования программы 2.10 (FILLC.C).

#inciude <stdio.h>

#define VGA256 0х13

#define TEXT_MODE 0х03

extern Set_Mode(int mode);

extern Fill_Screen(int color);

void main(void)

{

int i;

// устанавливаем режим 320х200 точек, 256 цветов (режим 13h)

Set_Mode(VGA256);                     

// заполняем экран цветом с кодом 1 (в,палитре, устанавливаемой

// по умолчанию, это соответствует синему цвету)

for (t=0; t<1000; t++) Fill_Screen(1) ;



// ждем нажатия любой клавиши

while(!kbhit()) {}

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

Set_Mode(TEXT_MODE);

} // конец функции main

Эти программы чистят экран с максимальной скоростью.

Примечание

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

На прилагаемой к этой книге дискете вы найдете программу под названием GAUGE.EXE, Вы можете использовать ее для замера производительности вашей видеосистемы.

Наш курс ассемблера проходит отлично. Я уже сам узнал кучу нового и надеюсь, что вы тоже. Теперь нам осталось узнать еще про одну возможность программирования на ассемблере: об использовании встроенного (in-line) ассемблера,


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