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

         

Оптимизированные версии OpaqueBlt() и TransparentBlt()


Листинг 17.4 содержит оптимизированные ассемблерные версии подпрограмм OpaqueBlt() и TransparentBlt(), которые имеются и на дискете (BLIT.ASM). Эти подпрограммы можно использовать вместо соответствующих функций на Си, что увеличит быстродействие программы примерно на 30 процентов.

Демонстрационная программа PARAL использует ассемблерные версии этих подпрограмм. Они были написаны с тем расчетом, чтобы могли работать с процессором 286. Поскольку они заполняют буфер системной памяти, их можно оптимизировать и дальше, применив 32-битовые команды перемещения банных.

Листинг 17.4. Оптимизированная подпрограмма (BLIT.ASM).

ideal

model compact,с

p286

dataseg

VIEW_WIDTH equ 320

VIEW_HEIGHT equ 100

TRANSPARENT equ 0

global MemBuf:dword

.codeseg

public OpaqueBIt public TransparentBIt



;

;Эта процедура копирует битовую карту в MemBuf. Кроме этого, она

; может скроллировать левую и правую части битового образа

; в зависимости от значения ScrollSplit ;

proc OpaqueBlt

ARG Bitmap:dword,StartY:word,Height:word,ScrollSplit:word

USES si,di

les   di,[MemBuf]      ; получить указатель на буфер памяти

mov   ax,[StartY]      ;получить начальную Y-координату

mov   bx,ax            ;скопировать

sal   ax,6             ; умножить на 64

sal   bx,8             ; умножить на 256

add   ax,bx            ; результат равен умножению на 320

add   di,ax            ; вычислить смещение внутри MemBuf

mov   bx,[Height]      ; получить высоту битовой карты

mov   dx,[ScrollSplit] ; получить длину правой половины

push ds                ; сохранить сегмент данных

lds   si,[Bitmap]     ; получить полный указатель на битовую карту

mov   ax,VIEW_WIDTH    ; получить ширину экрана

sub   ax,dx            ; вычислить длину левой половины

cld        ; обрабатывать данные от младших адресов к старшим

@@lоор01: add   di,dx            ; вычислить начальную позицию

mov   сх,ах            ; получить длину левой половины

shr   cx,1 ; разделить на 2 (поскольку выводим по 2 байта)   :




rep   movsw            ; нарисовать правую половину карты  

jnc   short @@skip01   ; пропустить, если выполнено

movsb                  ; дорисовать последний пиксель

@@skip01:

sub   di,VIEW_WIDTH    ; получить ширину выводимого окна

mov   cx,dx            ; получить длину правой половины

shr  сх,1             ; разделить на 2

rep   movsw            ; нарисовать правую половину карты

jnc   short @@skip02   ; пропустить, если выполнено

movsb                  ; перейти к последнему пикселю

@@skip02:

add   di,ax         ; получить ширину следующей строки вывода

dec   bx               ; уменьшить счетчик столбцов

jnz   short @@loop01   ; повторить

pop   ds               ; восстановить сегмент данных

ret                    ; завершить

endp OpaqueBlt

;

; Эта процедура копирует битовую карту в MemBuf. Функция не рисует

; пиксель, если его цвет равен "прозрачному"

;

proc TransparentBIt

ARG Bitmap:dword,StartY:word,Height:word,ScrollSplit:word USES si,di

les   di,[MemBuf]      ; получить указатель на память

mov   ax,[StartY]      ; получить начальную Y-координату

mov   ex, ax            ; получить копию

sal   ax,б             ; умножить на 64

sal   ex,8             ; умножить 256

add   ax, ex          ; результат эквивалентен умножению на 320

add   di,ax            ; прибавить смещение к MemBuf

mov   dx,[ScrollSplit] ; получить ширину левой половины

                        ;  изображения

mov   bx,VIEW_WIDTH    ; общая ширина изображений

sub   bx,dx            ; вычислить ширину правой половины

push  ds               ; сохрани,ть сегмент , данных

lds   si,[Bitmap] ; получить полный указатель на битовый образ

@@lоор01;

add   di,dx            ; вычислить начальную позицию экрана

mov   сх,Ьх            ; получить ширину правой половины ;

;Нарисовать правую половину ;

@@lоор02;

mov   аl,[si]            ; получить пиксель карты

inc   si                 ; следующий пиксель

cmp   al,TRANSPARENT     ; "прозрачный"?

je    short @@skip01     ; ...пропустить, если да



mov   [es:di],al         ; иначе, нарисовать его

@@skip01:

inc   di                 ; указать на следующий байт MemBuf

dec   ex                 ; уменьшить счетчик

jnz   short @@loop02                

sub   di,VIEW_WIDTH       ; получить ширину выводимого окна

mov   cx,dx               ; получить ширину правой половины

; Нарисовать левую половину

@@lоор03:

mov   ai,[si]            ; получить пиксель карты

inc   si                 ; следующий пиксель

cmp   al,TRANSPARENT     ; "прозрачный"?

je    short @@skip02       ;...пропустить, если да

mov   [es:di],al           ;иначе, нарисовать его

@@skip02;

inc   di                   ;перейти к следующему байту видеобуфера

dec   ex                   ;уменьшить счетчик

jnz   short @@loop03       ; повторить цикл, пока не сделаем все

add   di,bx                ;добавить значение ширины правой

части изображения

dec   [Height]             ;уменьшить счетчик колонок

jnz   short @@loop01       ;повторить еще раз

pop   ds                   ;восстановить сегмент данных

ret                       ; закончить

endp TransparentBlt

end


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