0% found this document useful (0 votes)
6 views17 pages

Graphics Programming Black Book-Gpbb49

This chapter discusses the implementation of 256-color animation in VGA's Mode X, focusing on the technique of masked copying to seamlessly integrate nonrectangular images into the background. Masked copying allows for the drawing of specific pixels based on a corresponding mask, enabling transparency effects without the rectangular borders typical of block copying. The chapter also includes a code listing for a masked copy routine, emphasizing its straightforward but unoptimized nature for performance considerations.

Uploaded by

Nuno Gomes
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views17 pages

Graphics Programming Black Book-Gpbb49

This chapter discusses the implementation of 256-color animation in VGA's Mode X, focusing on the technique of masked copying to seamlessly integrate nonrectangular images into the background. Masked copying allows for the drawing of specific pixels based on a corresponding mask, enabling transparency effects without the rectangular borders typical of block copying. The chapter also includes a code listing for a masked copy routine, emphasizing its straightforward but unoptimized nature for performance considerations.

Uploaded by

Nuno Gomes
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Previous Home Next

chapter 49

mode x 256-color animation


e the VGA Really Get up and Dance
rmative anecdotes to kick off this chapter; lotta
ground to cover, g re impatient, I can smell it. I won’t talk about the
of loudly saying “$100 bill” during an animated dis-
cussion while wa ums on Market Street in San Francisco one night,
context is everything. I can’t spare a word about
how my daughter thinks my 11-year-old floppy-disk-based CP/M machine is more
6 with its 100-MB hard disk because the CP/M machine’s word
runs twice as fast as the 386’s Windows-based word processor,
rogress is not the neat exponential curve we’d like to think it is,
and that features and performance are often conflicting notions. And, lord knows, I
can’t take the time todiscuss the habits of small white dogs, notwithstanding that
such dogs seem to be relevant to just about every aspect of computing, as Jeff
Duntemann’s writings make manifest. No lighthearted fluff for us; we have real work
to do, for today we animate with 256 colors in Mode X.

Masked Copying
Over the past two chapters, we’ve put together most of the tools needed to imple-
ment animation in the VGA’s undocumented 320x240 256-color Mode X. We now
have mode set code, solid and 4x4 pattern fills, system memory-to-display memory
block copies, and display memory-to-display memory block copies. The final piece

915
of the puzzle is the ability to copy a nonrectangular image to display memory.I call
this masked copying.
Masked copying is sort of like drawing through a stencil, in that only certain pixels
within the destination rectangle are drawn. The objective isto fit the image seamlessly
into thebackground, without the rectangular fringe that results when nonrectangular
images are drawn by block copying their bounding rectangle. This is accomplished
by using a second rectangular bitmap, separate fromthe image but corresponding
to it on a pixel-by-pixel basis, to control which destination pixels are set from the
source and which are left unchanged. With a masked copy, only those pixels prop-
erly belonging to an image are drawn, and the image fits perfectly into the
background, with no rectangular border. In fact, masked copying even makesit pos-
sible to havetransparent areaswithin images.
Note that anotherway to achieve this effect is to implement copying code that sup-
ports a transparent color; that is, a color that doesn’t get copiedbut ratherleaves the
destination unchanged. Transparent copying makes for more compactimages, be-
cause no separate mask is needed, and is generally faster in a software-only
implementation. However, Mode X supports masked copying but not transparent
copying in hardware, so we’ll use masked copying in this chapter.
The system memory to display memory masked copy routine in Listing 49.1 imple-
ments masked copying in a straightforward fashion. In the main drawing loop, the
corresponding mask byte is consulted as each image pixel is encountered, and the
image pixel is copied only if the mask byteis nonzero. As with most of the system-to-
display code I’ve presented, Listing 49.1 is not heavily optimized, because it’s
inherently slow; there’s a better way to go when performance matters, and that’s to
use the VGA’s hardware.

LISTING 49.1 L49- [Link]


Mode X (320x240. 256 c o l o r s )s y s t e mm e m o r y - t o - d i s p l a y memory maskedcopy
r o u t i n e .N o tp a r t i c u l a r l yf a s t :i m a g e sf o rw h i c hp e r f o r m a n c e i s critical
s h o u l db es t o r e di no f f - s c r e e n memory a n dc o p i e dt os c r e e nv i al a t c h e s . Works
on a l l VGAs. Copiesup t ob u tn o ti n c l u d i n gc o l u m n a t SourceEndXandrow at
SourceEndY. No c l i p p i n g i s p e r f o r m e d . Mask a n ds o u r c ei m a g ea r eb o t hb y t e -
p e r - p i x e l .a n dm u s tb eo f same w i d t h sa n dr e s i d ea t same c o o r d i n a t e s i n t h e i r
r e s p e c t i v eb i t m a p s .A s s e m b l yc o d et e s t e dw i t h TASM C n e a r - c a l l a b l e a s :

v o i d CopySystemToScreenMaskedX(int S o u r c e S t a r t X .
i n tS o u r c e S t a r t Y .i n tS o u r c e E n d X .i n tS o u r c e E n d Y .
i n tD e s t S t a r t X .i n tD e s t S t a r t Y .c h a r * SourcePtr.
u n s i g n e di n tD e s t P a g e B a s e .i n tS o u r c e B i t m a p W i d t h .
i n t D e s t B i t m a p W i d t h .c h a r * MaskPtr):
SC-INDEX 03c4h equ : S e q u e n c eC o n t r o l l e rI n d e xr e g i s t e rp o r t
MAP-MASK :index
02h
equ i n SC o f Map Mask r e g i s t e r
SCREEN-SEG equ OaOOOh :segmentd i sopf l a y memory i n mode X

parms struc
dw 2 dup ( ? ) :pushed BP and r e t ua rdnd r e s s
SourceStartX dw ? :X c osocouroulpdoerpifonfcntefearrt e
: ( s o u r c ei si ns y s t e m memory)

916 Chapter 49
SourceStartY dw ? ;Y c o o r d i n a t eo fu p p e rl e f tc o r n e ro fs o u r c e
SourceEndX dw ? ;X c o o r d i n a t e o f l o w e r r i g h t c o r n e r o f s o u r c e
; ( t h ec o l u m na t EndX i s n o t c o p i e d )
SourceEndY dw ? ; Y c o o r d i n a t eo fl o w e rr i g h tc o r n e ro fs o u r c e
: ( t h er o wa t EndY i s n o t c o p i e d )
DestStartX dw ? ;X c o o r d i n a t eo fu p p e rl e f tc o r n e ro fd e s t
; ( d e s t i n a t i o ni si nd i s p l a y memory)
DestStartY dw ? ;Y c o o r d i n a t eo fu p p e rl e f tc o r n e ro fd e s t
SourcePtr dw ? ; p o i n t e r i n DS t o s t a r t o f b i t m a p w h i c h s o u r c e r e s i d e s
DestPageBase dw ? :base o f f s e t i n d i s p l a y memory o f page i n
; w h i c hd e s tr e s i d e s
SourceBitmapWidth dw ? ;# o fp i x e l sa c r o s ss o u r c eb i t m a p( a l s om u s t
: b ew i d t ha c r o s st h em a s k )
DestBi
tmapWidth dw ? ; # o fp i x e l sa c r o s sd e s tb i t m a p( m u s tb em u l t i p l eo f4 )
MaskPtr dw ? ; p o i n t e r i n DS t o s t a r t o f b i t m a p i n w h i c h mask
: r e s i d e s( b y t e - p e r - p i x e lf o r m a t ,j u s tl i k et h es o u r c e
i m a g e ;0 - b y t e s mean d o n ' tc o p yc o r r e s p o n d i n gs o u r c e
p i x e l , 1 - b y t e s mean docopy)
parms
ends

-2 equ
RectWidth :1 o c a ls t o r a g ef o rw i d t ho fr e c t a n g l e
- 4 R eecqtuH e i g h t ;1 o c a ls t o r a g ef o rh e i g h to fr e c t a n g l e
LeftMask equ -6 :1 o c a ls t o r a g ef o rl e f tr e c te d g ep l a n e mask
STACK-FRAME-SIZE equ 6
.model smal 1
.code
p u b l i c -CopySystemToScreenMaskedX
-CopySystemToScreenMaskedX pnr eo ac r
f r a m e s t a c kc a l;lppush erre' ss e r v e b p
f r a smt ea cl okmov c a l t o ; p ob iPn*ts P
sub [Link]-FRAME-SIZE ; a l l o c a st ep a cf loeor c vaal r s
v a r ri ae bg licesa:st pelpush
l reer s' se r v es i
push di

mov [Link]-SEG ; p o i n t EdS i st op l a y memory


mov es ,ax
mov [Link]+SourceBitmapWidthl
mu1 [ b p + S o u r c e S t a r;ttsYoo]pu r cse ecl iatnne
add ax.[bp+SourceStartXl
mov bx, ax
add a x . C b p + S o u r c e P ;t or lf f sfoierfstsot u r rceepcitx e l
mov s i ,ax ; i n OS
add b x . C b p + M a s k P: torfl f siorefstt mask p i x ienl OS

mov ax.[bp+DestBitmapWidthl
shr ax, 1 a d d r ei nswsied:stchtoon v e r t
shr ax.1
mov [bp+DestBitmapWidth].ax;rememberaddresswidth
mu1 [bp+DestStartYl : t o pd e s tr e c ts c a nl i n e
mov di.[bp+DestStartX]
mov
shr
shr
[Link]
d i .1
d i .1
;X/4 -
offsetoffirstdestrectpixelin
; s c a nl i n e
add d i ,ax ; o f f s e to ff i r s td e s tr e c tp i x e li n page
add [Link]+OestPageBasel :offsetoffirstdestrectpixel

and
mo v
cl .Ollb
a1 . l l h
: i n d i s p l a y memory
;CL
: u p p e rn i b b l e
-
firstdestpixel'splane
comes i n t o p l a y when p l a n ew r a p s
; f r o m 3 b a c kt o 0
sh l a1 . c l :setthebitforthefirstdestpixel'splane
mov [bp+[Link] : i n e a c hn i b b l et o 1

Mode X 256-Color Animation 917


mov a x . [ b p + S o u r c e E: cnadlXc Iu l a t e p11iaxcoerfloss s
sub ax.[bp+SourceStartXl : rect
jle CopyDone : s k i p ni wef gi d0atthoi vr e
mov Cbp+[Link]
sub word p t r [bp+[Link]
: d i s t a n c ef r o me n do fo n es o u r c es c a nl i n et os t a r to fn e x t
mov ax.[bp+SourceEndYI
sub [Link]+SourceStartYl : h e i g h to fr e c t a n g l e
jle CopyDone : s k i p i f 0 o rn e g a t i v eh e i g h t
mov Cbp+[Link]
mov [Link]-INDEX ; p o i n t t o SC I n d e xr e g i s t e r
mov a1 .MAP-MASK
out dx,al : p o i n t SC I n d e x r e g t o t h e Map Mask
inc dx : p o i n t DX t o SC D a t ar e g
CopyRowsLoop:
mov a1 .[bp+LeftMaskl
mov cx.[bp+RectWidthl
push di :remember t h e s t a r t o f f s e t i n t h e d e s t
CopyScaniineLoop:
CmP b y t ep t rC b x l . 0 : i st h i sp i x e lm a s k - e n a b l e d ?
jz MaskOff ;no. s o d o n ' td r a w it
: y e s .d r a wt h ep i x e l
out [Link] : s e tt h ep l a n ef o rt h i sp i x e l
mov ah.[sil : g e tt h ep i x e lf r o mt h es o u r c e
mov es:[[Link] : c o p yt h ep i x e lt ot h es c r e e n
MaskOff:
inc bx : a d v a n c et h e mask p o i n t e r
inc si : a d v a n c et h es o u r c ep o i n t e r
rol a1 ,1 : s e t mask f o r n e x t p i x e l ' s p l a n e
adc d i .O : a d v a n c ed e s t i n a t i o na d d r e s so n l y when
: w r a p p i n gf r o mp l a n e 3 toplane 0
1oop CopyScanLineLoop
POP di : r e t r i e v et h ed e s ts t a r to f f s e t
add di.[bp+DestBitmapWidthl :pointtothestartofthe
: n e x ts c a nl i n eo ft h ed e s t
add si.[bp+SourceBitmapWidthl :pointtothestartofthe
: n e x ts c a nl i n eo ft h es o u r c e
add bx.[bp+SourceBitmapWidthl :pointtothestartofthe
: n e x ts c a nl i n eo ft h e mask
dec word p t r[ b p + R e c t H e i g h t l : c o u n t down s c a nl i n e s
jnz CopyRowsLoop
CopyDone:
POP di ; r e s t o r ec a l l e r ' sr e g i s t e rv a r i a b l e s
POP si
mov [Link] : d i s c a r ds t o r a g ef o rl o c a lv a r i a b l e s
POP bP : r e s t o r ec a l l e r ' ss t a c kf r a m e
ret
-CopySystemToScreenMaskedX endp
end

Faster Masked Copying


In theprevious chapter we saw howthe VGA's latches can be used tocopy four pixels
at a time from one areaof display memory to another in Mode X. We've further seen
that inMode X the Map Maskregister canbe used to selectwhich planes are copied.
That's all we need to know to be able to performfast maskedcopies; we can storean
image in off-screen display memory,and set the Map Mask to the appropriatemask
value asup to fourpixels at a time are copied.

918 Chapter 49
There’s a slight hitch, though. The latches can only be used when the source and
destination left edge coordinates, modulo four, are the same, as explained in the
previous chapter. The solution is to copy allfour possible alignments of each image
to display memory, each properly positioned for one of the four possible destina-
tion-left-edge-modulo-four [Link] aligned images must be accompaniedby the
four possible alignments of the image mask,stored in system memory. Given all four
image and mask alignments, masked copying is a simple matter of selecting the align-
ment that’s appropriate for the destination’s left edge, then setting the Map Mask
with the 4bit mask corresponding to each four-pixel set as we copy four pixels at a
time via the latches.
Listing 49.2 performs fast masked [Link] code expects to receivea pointer to
a MaskedImage structure, which in turn points to fourAlignedMaskedImage struc-
tures that describe the fourpossible imageand mask alignments. The aligned images
are already stored in display memory, and the aligned masks are already stored in
system memory; further, the masks are predigested into Map Mask register-compat-
ible form. Given all that ready-to-use data, Listing 49.2 selects and works with the
appropriate image-mask pair for thedestination’s left edge alignment.

LISTING [Link]
: Mode X ( 3 2 0 x 2 4 0 .2 5 6c o l o r s )d i s p l a y memory t o d i s p l a y memorymaskedcopy
: r o u t i n e . Workson a l l VGAs. Uses approach o fr e a d i n g 4 p i x e l s a t a t i m ef r o m
: s o u r c ei n t ol a t c h e s ,t h e nw r i t i n gl a t c h e st od e s t i n a t i o n ,u s i n g Map Mask
: r e g i s t e rt op e r f o r mm a s k i n g .C o p i e su pt ob u tn o ti n c l u d i n gc o l u m na t
: SourceEndXandrow a t SourceEndY. No c l i p p i n gi sp e r f o r m e d .R e s u l t sa r en o t
: g u a r a n t e e d i f s o u r c ea n dd e s t i n a t i o no v e r l a p . C n e a r - c a l l a b l ea s :

: v o i d CopyScreenToScreenMaskedX(int S o u r c e S t a r t X .
i n tS o u r c e S t a r t Y .i n t SourceEndX. i n t SourceEndY.
i n tD e s t S t a r t X ,i n tO e s t S t a r t Y .M a s k e d I m a g e * Source,
u n s i g n e di n tD e s t P a g e B a s e .i n tD e s t B i t m a p W i d t h ) :

SC-INDEX 03c4h : S e q u e n c eC o n t r o l l e rI n d e xr e g i s t e rp o r t
MAP-MASK 02h : i n d e x i n SC o f Map Mask r e g i s t e r
GC-INDEX 03ceh ; G r a p h i c sC o n t r o l l e rI n d e xr e g i s t e rp o r t
BIT-MASK 08h ; i n d e x i n GC o f Bit Mask r e g i s t e r
SCREENKSEG OaOODh :segment o f d i s p l a y memory i n mode X

parms struc
2 dup ( ? ) ;pushed B P and r e t u r na d d r e s s
SourceStartX ? : X c o o r d i n a t eo fu p p e rl e f tc o r n e ro fs o u r c e
SourceStartY ? :Y c o o r d i n a t e o f u p p e r l e f t c o r n e r o f s o u r c e
SourceEndX ? :X c o o r d i n a t e o f l o w e r r i g h t c o r n e r o f s o u r c e
: ( t h ec o l u m na tS o u r c e E n d X i sn o tc o p i e d )
SourceEndY ? ; Y c o o r d i n a t eo fl o w e rr i g h tc o r n e ro fs o u r c e
: ( t h e rowatSourceEndY i sn o tc o p i e d )
DestStartX ? ; X c o o r d i n a t eo fu p p e rl e f tc o r n e ro fd e s t
DestStartY ? :Y c o o r d i n a t eo fu p p e rl e f tc o r n e r o f dest
Source ? : p o i n t e r t o MaskedImage s t r u c t f o r s o u r c e
: w h i c hs o u r c er e s i d e s
DestPageBase 1 : b a s eo f f s e ti nd i s p l a y memory o f page i n
: w h i c hd e s tr e s i d e s
DestBitmapWidth ? ;#o f p i x e l s a c r o s s d e s t b i t m a p ( m u s t b e m u l t i p l e o f 4)
parms
ends

Mode X 256-Color Animation 9 19


SourceNextScanOffset - e2 q u ; l o c a ls t o r a g ef o rd i s t a n c ef r o me n do f
; o n es o u r c es c a nl i n et os t a r to fn e x t
DestNextScanOffset -4equ ; l o c a ls t o r a g ef o rd i s t a n c ef r o me n do f
; o n ed e s ts c a nl i n et os t a r to fn e x t
RectAddrWidth equ -6 ; l o c a ls t o r a g ef o ra d d r e s sw i d t ho fr e c t a n g l e
RectHeight equ -8 ; l o c a ls t o r a g ef o rh e i g h to fr e c t a n g l e
SourceBitmapWidthequ - 10 ; l o c a ls t o r a g ef o rw i d t ho fs o u r c eb i t m a p
; ( i na d d r e s s e s )
STACK-FRAME-SIZE 10equ
MaskedImage struc
A1 i g n m e n t s dw 4 d u p ( ? ) ; p o i n t e r st oA l i g n e d M a s k e d I m a g e sf o rt h e
: 4 p o s s i b l ed e s t i n a t i o ni m a g ea l i g n m e n t s
MaskedImage
ends
AlignedMaskedImage struc
Imagewidth dw ? : i m a g ew i d t h i n a d d r e s s e s( a l s o mask w i d t h i n b y t e s )
ImagePtr dw ? ; o f f s e to fi m a g eb i t m a pi nd i s p l a y memory
MaskPtr dw ? : p o i n t e r t o mask b i t m a p i n DS
AlignedMaskedImage ends
.model small
.code
p u b l i c -CopyScreenToScreenMaskedX
-CopyScreenToScreenMaskedX pnr eo ac r
f r a m e s t a c kc a ;l push pl er re' s e r v eb p
f r a smt ea cl okcmov a l t o ; p obi pn .t s p
sub [Link]-FRAME-SIZE ; a l l o c a st ep a cf loeorc a l VarS
v a r ri ea gb ilcsea;tsplpush
elrerers' se r v es i
push di

cld
mov [Link]-INDEX ; stbhei et mask s teol eba cil tlts
mov [Link]+BIT-MASK ; f r otm
hl ae t c h easnndo nf reo m
out [Link] : t h e CPU. so t h a t we wtchraietne
; l a t c hc o n t e n t sd i r e c t l yt o memory
mov [Link]-SEG : p o i n t ES d i st op l a y memory
mov [Link]
mov ax.[bp+DestBitmapWidthl
a d d r e s isne sw i dshr
t h t:oc o n av ex .r 1t
shr ax.1
mu1 [ b p + D e s t S t a ;drrstteolY
ciscpnal ten
mov di.[bp+DestStartXl
mov
shr
shr
si ,di
d i .1
d i .1
;X/4
; scan l i n e
- o ff idforrsepsefesitictxtnte l

add d i ,ax ; ofpdirfparefoissgsnxcfteetetl


add d i . [ b p + D e s t P a g e B a s e:]o f f s eot ffi r sdt e srt e cpt i x eilnd i s p l a y
; memory. now l o o ku pt h ei m a g et h a t ' s
: a l i g n e dt om a t c hl e f t - e d g ea l i g n m e n t
; o fd e s t i n a t i o n
and s i .3 ; D e s t S t a r t Xm o d u l o 4
mo v cx,si : s e ta s i d ea l i g n m e n tf o rl a t e r
shl s i .1 ; p r e p a r ef o rw o r dl o o k - u p
mov bx. [bp+Sourcel ; p o i n tt os o u r c eM a s k e d I m a g es t r u c t u r e
mov bx.[bx+Alignments+sil ; p o i n tt oA l i g n e d M a s k e d I m a g e
: strucforcurrentleft e d g ea l i g n m e n t
mov ax,[bx+ImageWidthl ;image width i n addresses
mov [bp+[Link] ;remember image w i d tiahnd d r e s s e s
mu1 [ b p + S o u r c e S t a r;ttsYoo]pu r cse ecl iatnne
mov
shr
shr
si, [bp+SourceStartXl
s i .1
s i .1
:X/4
; scan l i n e
- a dfdsi oroseufrptsreiiscnxceet l

add s i ,ax ;fsoiiorfmosfuprsfitaerinexcgcteet l

920 Chapter 49
mov [Link]
add si.[bx+MaskPtrl : p o i n t t o mask o f f s e t o f f i r s t mask p i x e l i n OS
mov bx.[bx+ImagePtrl ; o f f s e to ff i r s ts o u r c er e c tp i x e l
add [Link] : i n d i s p l a y memory

mov ax,[bp+SourceStartXl : c a l c u l a t e # o f a d d r e s s e sa c r o s s
add ax,cx ; r e c t .s h i f t i n g i f n e c e s s a r yt o
add cx,[bp+SourceEndX] ; a c c o u n tf o ra l i g n m e n t
CmP [Link]
jle CopyDone ; s k i p i f 0 o rn e g a t i v ew i d t h
add cx.3
and a x . n o tO l l b
sub [Link]
shr cx. 1
shr cx.1 ;# o f a d d r e s s e sa c r o s sr e c t a n g l et oc o p y
mov
-
ax.[bp+SourceEndYl
sub [Link]+SourceStartYl :AX h e i g h to fr e c t a n g l e
jle CopyDone ; s k i p i f 0 o rn e g a t i v eh e i g h t
mov [bp+[Link]
mov ax.[bp+DestBitmapWidthl
a d d r e sisne sw i sd ht hr t; oc o nav xe.r1t
shr ax.1
sub a x . :cdxi s t a n fcreoem ononddf essct al isnt toenaoerftx t
mov Cbp+[Link]
mov ax.[bp+SourceBitmapWidthl ; wai di ntdhr e s s e s
sub a x .: cd xi s t a nf cr eoenmd o f s o u r sc ce al isnnt toeanoreftx t
mov [bp+[Link]
mov Cbp+[Link] ;remember width i n addresses

mov [Link]-INDEX
mov a1 ,MAP"MASK
out ; [Link] SC Ir ne dgteiosx t e r Map Mask
t oinc
;point dx r eSC
g i sDt ea rt a
CopyRowsLoop:
mov cx.[bp+RectAddrWidthl ; w i d t ha c r o s s
CopyScanLineLoop:
lodsb : g e tt h e mask f o r t h i s f o u r - D i x e l s e t
: - a n da d v a n c et h e mask p o i n t e r
the o: suett [Link] mask
mov a1 . e s : [;bl olxtahal tedc hwfeoi tsuh r - p fisxrseoeotm lu r c e
mov e s : [ d ;fi c][Link]-eyttposi ex te l
p o i n t esro u r c e t h e : aidncv a n c e b x
inc di pdoeisnttienra t itohne; a d v a n c e
s ef ot su r - p i x eol f f ; cdec ount cx
jnz CopyScanLineLoop

mov ax,[bp+SourceNextScanOffset]
o f s t a r t t h eadd t o ; p osi in,ta x
add [Link] s o u r c e n, e x t : t h e mask,
add di.[bp+DestNextScanOffsetl : a nddelsi nt e s
dec word p[ tbrp + R e c t H e i g h: ct lo u n t down s c al inn e s
j nz CopyRowsLoop
CopyDone:
mov [Link]-INDEX+l ; r e s t otbhr ieet mask idt eos f a u l t ,
mov a1 . O f f h ; w hsi ec lhbfera ti cohtl stlm
es CPU
out [Link] l a (ttcthfh:hnreeoeoam
snned GC
; I n d e xs t i l lp o i n t st oB i t Mask)
v a r ri ae bg licesatsle:l rePOPer 'sst o r e d i
POP si
v a r imovl ao bc lael sf s;odtroi sr [Link]

Mode X 256-Color Animation 921


f r a m es t a cc ka lPOP
:l reer s' st o r e b p
ret
-CopyScreenToScreenMaskedX endp
end

It would be handy to have a function that, given a base image and mask, generates
the fourimage and mask alignments and fills in the MaskedImage structure. Listing
49.3,together with the includefile in Listing 49.4and thesystem memory-to-display
memory block-copy routine in Listing 48.4 (in theprevious chapter) does just that.
It would be faster if Listing 49.3were in assembly language, but there's no reason to
think that generating aligned images needs to be particularly fast; in such cases, I
prefer to use C, for reasons of coding speed,fewer bugs, and maintainability.

LISTING 49.3 L49-3.C


/* Generates a l l f o u r p o s s i b l e mode X i m a g e / m a s ka l i g n m e n t s ,s t o r e si m a g e
a l i g n m e n t si nd i s p l a y memory. a l l o c a t e s memory f o r andgenerates mask
a l i g n m e n t s ,a n d f i l l s o u t an A l i g n e d M a s k e d I m a g es t r u c t u r e .I m a g ea n d mask must
b o t hb ei nb y t e - p e r - p i x e lf o r m ,a n dm u s tb o t hb eo fw i d t hI m a g e w i d t h . Mask
maps i s o m o r p h i c a l l y( o n et oo n e )o n t oi m a g e ,w i t he a c h0 - b y t ei n mask masking
o f fc o r r e s p o n d i n gi m a g ep i x e l( c a u s i n g i t n o t t o b ed r a w n ) .a n de a c hn o n - 0 - b y t e
a l l o w i n gc o r r e s p o n d i n gi m a g ep i x e lt ob ed r a w n .R e t u r n s 0 i f f a i l u r e , or # o f
d i s p l a y memory a d d r e s s e s( 4 - p i x e ls e t s )u s e d i f success. For s i m p l i c i t y ,
a l l o c a t e d memory i s n o t d e a l l o c a t e d i n c a s e o f f a i l u r e . C o m p i l e d w i t h
B o r l a n d C++ i n C c o m p i l a t i o n mode. */

# i n c l u d e< s t d i o . h >
#i n c l ude < s t d l ib. h>
#include"maskim.h"

e x t e r nv o i d CopySystemToScreenX(int, i n t . i n t . i n t . i n t . i n t . c h a r *,
u n s i g n e di n t ,i n t .i n t ) ;
u n s i g n e d i n t CreateAlignedMaskedImage(Masked1mage * ImageToSet.
u n s i g n e di n tD i s p M e m S t a r t .c h a r * Image, i n t Imagewidth.
i n t I m a g e H e i g h t .c h a r * Mask)
(
i n tA l i g n ,S c a n L i n e .B i t N u m .S i z e ,T e m p I m a g e W i d t h ;

-
u n s i g n e dc h a r MaskTemp;
u n s i g n e di n tD i s p M e m O f f s e t DispMemStart;
A1 ignedMaskedImage *WorkingAMImage;
char*NewMaskPtr.*OldMaskPtr:

f o r( A l i g n -
I* G e n e r a t ee a c ho ft h ef o u ra l i g n m e n t si nt u r n .
0: A l i g n < 4;Align++) I
*I

i f ((WorkingAMImage -
/ * A l l o c a t es p a c ef o rt h eA l i g n e d M a s k e d I m a g es t r u c tf o rt h i sa l i g n m e n t .
ImageToSet->AlignmentsCAlignl
malloc(sizeof(AlignedMasked1mage))) -- NULL)
-
*/

r e t u r n 0;
WorkingAMImage->Imagewidth -
-
( I m a g e w i d t h + A l i g n + 3 ) / 4; / * w i d t h i n 4 - p i x e l s e t s
W o r k i n g A M I m a g e - > I m a g e P t r DispMemOffset: I* i m a g ed e s t */
/ * Download t h i sa l i g n m e n to ft h ei m a g e . */
*/

CopySystemToScreenX(0, 0. I m a g e w i d t h I. m a g e H e i g h t A , lign, 0.
Image,[Link]. WorkingAMImage->Imagewidth * 4);
/ * C a l c u l a t e t h e number o f b y t e s n e e d e d t o s t o r e t h e mask i n
n i b b l e (Map M a s k - r e a d y )f o r m ,t h e na l l o c a t et h a ts p a c e . */
-
Size WorkingAMImage->Imagewidth * ImageHeight:
i f ((WorkingAMImage->MaskPtr
r e t u r n 0;
-
malloc(Size)) - NULL)

922 Chapter 49
/* G e n e r a t et h i sn i b b l eo r i e n t e d (Map M a s k - r e a d y )a l i g n m e n to f

--
t h e mask,onescan
OldMaskPtr Mask:
l i n e a t a t i m e . */

---
NewMaskPtr WorkingAMImage->MaskPtr:
f o r( S c a n L i n e 0: ScanLine < ImageHeight:ScanLine++) {
BitNum Align:
MaskTemp 0:
TempImageWidth - Imagewidth:
do {
/ * S e tt h e mask b i t f o r n e x t p i x e l a c c o r d i n g t o i t s a l i g n m e n t . */
MaskTemp I- (*OldMaskPtr++ !- 0 ) << BitNum:
i f (++BitNum > 3 ) {

1
*NewMaskPtr++
MaskTemp - - -
BitNum
MaskTemp:
0:

1 w h i l e( - - T e m p I m a g e W i d t h ) :

1
/* S e ta n yp a r t i a lf i n a l maskon
i f ( B i t N u m !- 0 ) *NewMaskPtr++ - t h i ss c a nl i n e .
MaskTemp:
*/

DispMemOffset +- S i z e : /* mark o f f t h e space we j u s t u s e d */


1
r e t u r nD i s p M e m O f f s e t - DispMemStart;
1

LISTING 49.4 MASK1M.H


/* MASK1M.H: s t r u c t u r e su s e df o rs t o r i n ga n dm a n i p u l a t i n gm a s k e d
images */

/* D e s c r i b e so n ea l i g n m e n to f a m a s k - i m a g ep a i r . */
t y p e d e fs t r u c t {
i n tI m a g e w i d t h : / * i m a g ew i d t hi na d d r e s s e si nd i s p l a y memory ( a l s o
mask w i d t h i n b y t e s ) */
u n s i g n e di n tI m a g e P t r : / * o f f s e t o f imagebitmap i n d i s p l a y mem */
char*MaskPtr; / * p o i n t e rt o maskbitmap */
1 AlignedMaskedImage;
/ * D e s c r i b e sa l lf o u ra l i g n m e n t so f a m a s k - i m a g ep a i r . */
t y p e d e fs t r u c t {
AlignedMaskedImage*Alignments[41: /* p t r st oA l i g n e d M a s k e d I m a g e
s t r u c t sf o rf o u rp o s s i b l ed e s t i n a t i o n
i m a g ea l i g n m e n t s */
1 MaskedImage:

Notes on Masked Copying


Listings 49.1 and 49.2, like all Mode X code I’ve presented, perform no clipping,
because clipping code would complicate the listings too much. While clipping can
be implemented directly in thelow-level Mode X routines (at thebeginning of List-
ing 49.1, for instance), another,potentially simpler approach would be to perform
clipping at a higher level, modifjmg the coordinates and dimensions passed to low-
level routines such as Listings 49.1 and 49.2 as necessary to accomplish the desired
clipping. It is for precisely this reason that the low-level Mode X routines support
programmable start coordinates in the source images, rather than assuming (0,O);
likewise for thedistinction between the width of the image and thewidth of the area
of the image to draw.

Mode X 256-Color Animation 923


Also, it would be more efficient tomake up structures that describe the source and
destination bitmaps, with dimensions and coordinates built in, andsimply passpoint-
ers to these structures tolow thelevel, rather thanpassing manyseparate parameters,
as is now the case. I’ve used separate parameters forsimplicity and flexibility.

Be aware that as nijii as Mode X hardware-assisted masked copying is, whether


or not it’s actually faster than software-only masked or transparent copying de-
pends upon theprocessor and thevideo adapter The advantage of Mode Xmasked
copying is the 32-bit parallelism; the disadvantages are the need to read display
memory and the needto perform an OUT for every four pixels. (OUT is a slow
486/Pentium instruction, and mostVGAs respond to OUTSmuch moreslowly than
to display memory writes.)

Animation
Gosh. There’s just no way I can discuss high-level animation fundamentals in any
detail here; I could spend an entire (andentirely separate) bookon animation tech-
niques alone. You might want to have a look at Chapters 43 through 46 before
attacking the code inthis chapter; thatwill have to do us for the presentvolume. (I
will return to 3-Danimation in the next chapter.)
Basically, I’mgoing to performpage flipped animation,in which one page (that is, a
bitmap large enough to hold a full screen) of display memory is displayed while
another page is drawn to. When the drawing is finished, thenewly modified page is
displayed, and the other-now invisible-page is drawn to. The process repeats ad
infinitum. For further information, some good places to start areComputer Guphics,
by Foley and van Dam (Addison-Wesley);Principles oflnteructive Computer Graphics,by
Newman and Sproull (McGraw Hill) ; and “Real-TimeAnimation” by Rahner James
(January 1990, Dr. Dobb’s Journal ) .
Some of the code inthis chapter was adapted forMode X from the codein Chapter
44-yet another reason to read that chapter before finishing this one.

Mode X Animation in Action


Listing 49.5 tiestogether everything I’ve discussed about Mode X so far in a compact
but surprisingly powerful animation package. Listing 49.5 first uses solid and pat-
terned fills and system-memory-to-screen-memorymasked copying to draw a static
background containing a mountain, a sun, a plain, water, and a housewith puffs of
smoke coming out of the chimney, and sets up the four alignmentsof a masked kite
image. The background is transferred to bothdisplay pages, and drawing of 20 kite
images in the nondisplayedpage using fast masked copying begins. After all images
have been drawn, the page is flipped to showthe newly updated screen, and the kites
are moved and drawn in the other page, which is no longer displayed. Kites are
erased at their old positions in the nondisplayed page by block copying from the

924 Chapter 49
background page. (See the discussion in the previous chapter for the display memory
organization used by Listing 49.5.)So far as the displayed image is concerned, there
is never any hint of flicker or disturbance of the [Link] continues at a rate
of up to 60 times a second until Esc is pressed to exit the program. See Figure 49.1
for ascreen shot of the resulting image-add the animation inyour imagination.

LISTING 49.5 L49-5.C


/* Sample mode X VGA a n i m a t i o np r o g r a m .P o r t i o n so ft h i sc o d ef i r s ta p p e a r e d
i n PC T e c h n i q u e s .C o m p i l e dw i t hB o r l a n d C++ 2.0 i n C c o m p i l a t i o n mode. */
# i n c l u d e< s t d i o . h >
#i n c l u d e < c o n i0. h>
#include <dos. h>
# i n c l u d e< m a t h . h >
#include"maskim.h"

#define SCREEN-SEG
OxAOOO
#define SCREEN-WIDTH 320
#define SCREEN-HEIGHT 240
#define PAGEO-START-OFFSET 0
#define PAGE1-START-OFFSET (((long)SCREEN-HEIGHT*SCREEN-WIOTH)/4)
#define BG-STARTLOFFSET (((long)SCREEN_HEIGHT*SCREEN_WIDTH*2)/4)
#define DOWNLOAD-STARTLOFFSET (((long)SCREENKHEIGHT*SCREEN-WIDTH*3)/4)

-
-
-
s t a t i cu n s i g n e di n tP a g e S t a r t O f f s e t s C Z l
s t a t i cc h a rG r e e n A n d B r o w n P a t t e r n C ]
s t a t i cc h a rP i n e T r e e P a t t e r n C l
{[Link]-START-OFFSET):
( 2 . 6 . 2 . 6 .6 . 2 . 6 . 2 .2 . 6 . 2 . 6 .6 . 2 . 6 . 2 ) ;
([Link], 2 . 6 . 2 . 6 .2 . 2 . 6 . 2 . 2.2.2,2):
- I 6 . 6 . 7 . 6 .7 . 7 . 7 . 7 .7 . 6 . 6 , 6 . 7.7,7,7.}:
-
s t a t i cc h a rB r i c k P a t t e r n C l
s t a t i cc h a rR o o f P a t t e r n C l ( 8 . 8 . 8 . 7 , 7 . 7 . 7 . 7 . 8 . 8 . 8 . 7 ,8 . 8 . 8 . 7 ) ;

# d e f i n e SMOKE-WIDTH 7
# d e f i n e SMOKE-HEIGHT 7

Mode X 256-Color Animation 925


s t a t i cc h a rS m o k e P i x e l s C l
0. [Link]. 0. 0.
- (

0. 7. [Link]. 0.
8. 7. 7. [Link],
8. 7. 7. 7. 7.15.15.
0. 8, 7. 7, 7. 7.15.
0. 0. 8. 7. 7. 7. 0.
0. 0. 0. 8. 8. 0. 01:
s t a t i cc h a r SmokeMaskCl
0. 0. 1. 1. 1. 0. 0.
- (

0. 1. 1. 1. 1. 1. 0.
1, 1, 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1.
1, 1. 1. 1. 1. 1. 1.
[Link].1.1.0.
0. 0. 1. 1. 1. 0. 01:
# d e f i n e KITELWIDTH 10
# d e f i n e KITELHEIGHT 16
s t a t i cc h a rK i t e P i x e l s C l
0. 0. 0. 0.45, 0. 0. 0.
- 0. 0.
(

0. 0. [Link], 0. 0. 0. 0.
0. [Link].47.47. 0. 0. 0.
[Link],[Link]. 0. 0.
49.49,[Link].49.49.49. 0.
0,[Link].50.50.50. 0. 0.
[Link].51.51,51.51, 0. 0.
0. [Link].52.52. 0. 0. 0.
0. 0,[Link].53. 0. 0. 0.
0, 0, [Link]. 0. 0, 0. 0.
0. 0. [Link]. 0. 0. 0. 0.
0. 0. 0. 0.58, 0. 0. 0. 0. 0.
0. 0. 0. 0.59, 0. 0. 0. 0.66.
0. 0. 0. 0.60, 0. 0.64, 0.65.
0. 0. 0. 0. 0.61, 0. 0.64. 0.
0. 0. 0. 0. 0. 0.62.63, 0.641;
s t a t i cc h a rK i t e M a s k C l
[Link],[Link].0.0.
- (

0. 0. 0. 1. 1. 1. 0. 0, 0. 0.
0. 0. 1. 1. 1. 1. 1. 0. 0. 0.
0. 1. 1. 1. 1. 1. 1. 1. 0. 0.
1. 1. 1. 1. 1. 1. 1. 1. 1. 0.
[Link].[Link].0.0.
0. 1. 1. 1. 1. 1. 1. 1. 0. 0.
0. 0. 1. 1, 1. 1. 1. 0. 0. 0,
0. 0. 1. 1. 1. 1. 1. 0. 0. 0.
[Link].[Link],0.0.
0. 0. 0. 1. 1. 1. 0. 0. 0. 0.
[Link].[Link],0.0.
0. 0. 0. 0. 1. 0. 0. 0. 0. 1.
0. 0. 0. 0. 1. 0. 0. 1. 0. 1.
0. 0. 0. 0. 0. 1. 0. 0. 1. 0.
0. 0. 0. 0. 0. 0. 1. 1. 0. 11:
s t a t i c MaskedImageKiteImage:

# d e f i n e NUM-OBJECTS 20
t y p e d e fs t r u c t (
i n t X,[Link];
MaskedImage*Image:
1 Animatedobject:

926 Chapter 49
A n i m a t e d o b j e c tA n i m a t e d O b j e c t s C l-I
[ 0. [Link]-WIDTH.KITE_HEIGHT. 1. 1. 0. O , & K i t e I m a g e l ,
{ 1 0 . 10,[Link]-HEIGHT. 0 . 1, 1 0l.O . & K i t e I m a g e I .
{ 20. [Link].-1. 1, 20.2O.&KiteImagej.
[ 30. [Link]~[Link]~HEIGHT."1. 3 0 3. 0 . & K i t e I m a g e j ,
( 40. [Link]-HEIGHT. 1;l. 40.40.&KiteImage).
[ 50, [Link],KITEKHEIGHT. O,-l 50.
, 50.&KiteImage).
I 6 0 , [Link]-WIDTH.KITE_HEIGHT. 1. 0. 60.60.&KiteImage).
[ 70. [Link]-HEIGHT,-l, 0 . 70.7D.&KiteImage).
[ EO. [Link]-HEIGHT. 1, 2. EO. EO,&KiteImage).
{ 90. [Link]-HEIGHT. 0. 2.90,90.&KiteImage}.
[[Link]~[Link]~HEIGHT.-1. 2.100.10D.&KiteImageI.
~[Link].-1.-2,llO,llO.&KiteIma~e~.
[ 1 2 0 . 1 2 0 . K I T E ~ W I D T H , K I T E ~ H E I G H T , 1.-2.120.120.&KiteImage).
[130.130,KITEKWIDTH,KITEKHE1GHT, 0.-2.130.130.&KiteImage).
([Link]~[Link]. 2,0.140.140.&KiteImage).
{150.150,KITE~WIDTH.KITEKHE1GHT,-2. 0.150,150.&KiteImage).
(160,160,KITEKWIDTH.K1TEKHE1GHT, 2.2,16D.l60.&KiteImage),
{[Link]~[Link]~HEIGHT.-2, 2.170.170.&KiteImage).
{1E0.1E0,KITEKWIOTH,KITEKHEIGHT.-2.-2,lEO,lEO,&KiteImage~,
[190.190,KITE~WIDTH,KITEKHEIGHT, 2.-2.190.190.&KiteImagej.
I;
voidmain(void);
v o i dD r a w B a c k g r o u n d ( u n s i g n e di n t ) ;
v o i d MoveObject(Animated0bject * ) ;
e x t e r nv o i dS e t 3 2 0 ~ 2 4 0 M o d e ( v o i d ) ;
e x t e r nv o i dF i l l R e c t a n g l e X ( i n t ,i n t .i n t .i n t .u n s i g n e di n t .i n t ) :
e x t e r nv o i dF i l l P a t t e r n X ( i n t .i n t .i n t .i n t .u n s i g n e di n t .c h a r * ) ;
e x t e r nv o i d CopySystemToScreenMaskedX(int. i n t . i n t . i n t , i n t . i n t .
c h a r *, u n s i g n e di n t .i n t .i n t ,c h a r *);
e x t e r nv o i d CopyScreenToScreenX(int. i n t . i n t . i n t . i n t . i n t ,
u n s i g n e di n t .u n s i g n e di n t .i n t .i n t ) ;
e x t e r nu n s i g n e di n t CreateAlignedMaskedImage(Masked1mage * ,
u n s i g n e di n t .c h a r *, i n t .i n t .c h a r *):
e x t e r nv o i d CopyScreenToScreenMaskedX(int. i n t . i n t . i n t . i n t . i n t .
MaskedImage *, u n s i g n e d i n t . i n t ) ;
e x t e r nv o i dS h o w P a g e ( u n s i g n e di n t ) ;

voidmain0
I
i nD
t i s p l a y e d P a g eN . o n D i s p l a y e d P a g eD , one, i;
u n i o n REGS r e g s e t ;
Set320x240ModeO;
/ * D o w n l o a dt h ek i t ei m a g ef o rf a s tc o p y i n gl a t e r . */
i f (CreateAlignedMaskedImage(&KiteImage. DOWNLOADKSTART-OFFSET,
K i t e P i x e l s . KITELWIDTH. KITELHEIGHT, KiteMask) --
-
0) {
[Link] 0 x 0 0 0 3 ;i n t E 6 ( 0 x 1 0 .& r e g s e t .& r e g s e t ) :
p r i n t f ( " C o u 1 d n ' tg e tm e m o r y \ n " ) :e x i t ( ) ;
j
/* Draw t h eb a c k g r o u n dt ot h eb a c k g r o u n dp a g e . */
DrawBackground(BG-STARTL0FFSET);
/ * Copy t h eb a c k g r o u n dt ob o t hd i s p l a y a b l ep a g e s . */
CopyScreenToScreenX(0, 0 . SCREEN-WIDTH, SCREENKHEIGHT. 00. .
BG-START-OFFSET, PAGEO-START-OFFSET, SCREEN-WIDTH. SCREENKWIDTH);
CopyScreenToScreenX(0, 0. SCREENKWIDTH. SCREEN-HEIGHT. 0.0.
BGKSTART-OFFSET. PAGE1-START-OFFSET, SCREEN-WIDTH. SCREEN-WIDTH);
/ * Move t h eo b j e c t sa n du p d a t et h e i ri m a g e si nt h en o n d i s p l a y e d
f l i p t h e page, u n t i l Esc i s p r e s s e d . * /
-
p a g e t, h e n
Done = D i s p l a y e d P a g e 0;
do I
NonDisplayedPage -D i s p l a y e d P a g e A 1;

Mode X 256-Color Animation 927


I* E r a s ee a c ho b j e c ti nn o n d i s p l a y e dp a g eb yc o p y i n gb l o c kf r o m
b a c k g r o u n dp a g ea tl a s tl o c a t i o ni nt h a tp a g e . *I
f o r( i - 0 : i<NUM-OBJECTS; i++) (
CopyScreenToScreenX~AnimatedObjects~[Link],
AnimatedObjects[[Link].
AnimatedObjects[[Link] +
AnimatedObjects[[Link].
AnimatedObjects[[Link] +
AnimatedObjects[[Link].
AnimatedObjects[[Link].
A n i m a t e d O b j e c t s [ i l . Y O t h e r P a g e . BG-START-OFFSET.
PageStartOffsetsCNonDisplayedPagel. SCREEN-WIDTH. SCREEN-WIDTH):
1
I* Move a n dd r a we a c ho b j e c t i nt h en o n d i s p l a y e dp a g e . *I
f o r( i - 0 ; i<NUMLOBJECTS; i++) (
MoveObject(&AnimatedObjects[il):
I* Draw o b j e c ti n t on o n d i s p l a y e dp a g ea t new l o c a t i o n * I
CopyScreenToScreenMaskedX(0, 0, AnimatedObjects[[Link],
AnimatedObjects[[Link]. AnimatedObjects[il.X,
A n i m a t e d O b j e c t s [ i l . Y . AnimatedObjectsCil.1mage.
PageStartOffsets[NonDisplayedPagel, SCREEN-WIDTH):
I
/* F l i p t o t h ep a g ei n t ow h i c h
-
we j u s t drew. * I
ShowPaqe(PaaeStartOffsetsrDisD1ayedPage
" - . NonOisplayedPage]);
I* See i f i t ' s t i m e t o end. * I
if (kbhit0) (

1
if (getch0 -
OxlB)Done 1; -
I* Esc t o end * I

1 w h i l e( ! D o n e ) :
I* R e s t o r e t e x t mode anddone.
- 0 x 0 0 0 3 ;i n t 8 6 ( 0 x 1 0 .
*I
[Link] & r e g s e t .& r e g s e t ) ;
1
voidDrawBackground(unsigned i n tP a g e s t a r t )
I
i n ti . j , T e m p ;
I* F i l lt h es c r e e nw i t hc y a n . *I
F i l l R e c t a n g l e X ( 0 , 0. SCREEN-WIDTH. SCREEN-HEIGHT. P a g e s t a r t . 11);
I* Draw a g r e e na n db r o w nr e c t a n g l et oc r e a t e a f l a t p l a i n . *I
F i l l P a t t e r n X ( 0 1. 6 0 , SCREEN-WIDTH, SCREEN-HEIGHT. PageStart,
GreenAndBrownPattern):
I* D r a wb l u ew a t e ra tt h eb o t t o mo ft h es c r e e n . *I
F i l l R e c t a n g l e X ( 0 . SCREENLHEIGHT-30. SCREEN-WIDTH. SCREEN-HEIGHT.
P a g e s t a r t , 1) :
I* Draw a b r o w n m o u n t a i n r i s i n g o u t o f t h e p l a i n . *I
f o r( i - 0 :i < 1 2 0 : i++)
FillRectangleX(SCREEN~WIDTHl2-30-i. 51+i, SCREEN-WIDTH/2-30+i+l,
5 1 + i + lP, a g e s t a r t6. ) ;
I* Draw a y e l l o ws u nb yo v e r l a p p i n gr e c t so fv a r i o u ss h a p e s . *I

Temp -
f o r( i - 0 i; < - 2 0 : i++) (
(int)(sqrt(20.0*20.0 - ( f l o a t ) i * ( f l o a t ) i ) + 0.5):
F i l l R e c t a n g l e X ( S C R E E N _ W I D T H - 2 5 - i . 30-Temp,
SCREEN-WIDTH-25+i+l.
30+Temp+l. P a g e s t a r t 1. 4 ) ;
1
I* D r a wg r e e nt r e e s down t h e s i d e o ft h em o u n t a i n . *I
f o r( i - 1 0 :i < 9 0 ; i +- 1 5 )
f o r( j - 0 ;j < 2 0 ; j++)
FillPatternX(SCREENLWIDTH12+i-j13-15, i + j + 5 1 , S C R E E N ~ W I D T H / 2 + i + j I 3 - 1 5 + 1 ,
i + j + 5 1 + 1P. a g e s t a r tP. i n e T r e e P a t t e r n ) :
I* Draw a house on t h e p l a i n . *I
F i l l P a t t e r n X ( 2 6 5 1. 5 0 2. 9 5 1. 7 0 P
. a g e s t a r tB
. rickPattern);

928 Chapter 49
F i l l P a t t e r n X ( 2 6 51, 3 02. 7 01, 5 0P. a g e S t a r tB. r i c k P a t t e r n ) ;
f o r( i = O :i < 1 2 ; i++)
F i l l P a t t e r n X ( 2 8 0 - i * 2 1. 3 8 + i . 2 8 O + i * 2 + 11. 3 8 + i + lP. a g e s t a r tR. o o f P a t t e r n ) :
/ * F i n a l l y ,d r a wp u f f so f smoke r i s i n gf r o mt h ec h i m n e y . *I
f o r( i - 0 :i < 4 ; i++)
CopySystemToScreenMaskedX(0, 0 . SMOKELWIDTH. SMOKE-HEIGHT. 264,
1 1 0 - i * 2 0S, m o k e P i x e l sP. a g e S t a r t . SMOKE-WIDTH.SCREEN_WIDTH, SmokeMask):
1
/* Move t h e s p e c i f i e d o b j e c t , b o u n c i n g a t t h e e d g e s o f t h es c r e e na n d
r e m e m b e r i n gw h e r et h eo b j e c t was b e f o r e t h e move f o r e r a s i n g n e x t t i m e . *I
v o i d MoveObject(Animated0bject * ObjectToMove)

-
i n t X, Y:
ObjectToMove->X + ObjectToMove->XDir;
-
X
Y ObjectToMove->Y + ObjectToMove->YDir:
i f ( ( X < 0 ) 1 1 (X > (SCREEN-WIDTH - O b j e c t T o M o v e - > W i d t h ) ) ) [

X -
ObjectToMove->XDir - -0bjectToMove->XDir:
ObjectToMove->X + ObjectToMove->XDir:
1
if ((Y < 0 ) 1 1 ( Y > (SCREEN-HEIGHT - O b j e c t T o M o v e - > H e i g h t ) ) ) {
ObjectToMove->YDir -
-0bjectToMove->YDir:
Y -
ObjectToMove->Y + ObjectToMove->YDir;
1
/ * Remember p r e v i o u sl o c a t i o nf o re r a s i n gp u r p o s e s .
-
*I
ObjectToMove->XDtherPage ObjectToMove->X:
ObjectToMove->YOtherPage ObjectToMove->Y; -
ObjectToMove->X -
X : / * s e t new l o c a t i o n * /
ObjectToMove->Y Y: -
1

Here’s something worth noting: The animation is extremely smooth on a 20 MHz


386. It is somewhat more jerky on an 8 MHz 286, because only 30 frames a second
can be processed. If animation looksjerky on your PC, try reducing the number of kites.
The kites drawperfectly into the background,with no interference or fringe, thanks
to masked copying. In fact, the kites also cross withno interference (the last-drawn
kite is always infront), although that’s not readily apparent because they alllook the
same anyway and aremoving fast. Listing 49.5 isn’t inherently limited to kites; create
your own images and initialize the object list to displaya mix ofthose images and see
the full power of ModeX animation.
The external functions called by Listing 49.5 can be found in Listings 49.1, 49.2,
49.3, and 49.6, and in the listings for the previous two chapters.

LISTING [Link]
: Shows t h e p a g e a t t h e s p e c i f i e d o f f s e t i n t h e b i t m a p . Page i s d i s p l a y e d when
: t h i sr o u t i n er e t u r n s .
: C n e a r - c a l l a b l ea s :v o i dS h o w P a g e ( u n s i g n e di n tS t a r t o f f s e t ) :
INPUTLSTATUSLl 0e3q:duI naSpht ua t u s 1 register
CRTC-INDEX equ 03d4h :CRT C or enI gnt rdoel lxe r
START-ADDRESS-HIGH equ Och ; b i t sm atdadrptbhr eyi gst ehs
START_ADDRESSLLOWequ Odh : basiydttltdm
aoerrw
aetps s

ShowPageParms struc
dw 2 dup ( ? ) :pushed BP and r e t ua rdnd r e s s
Startoffset dw ? d i s ptpol abygioet: fm
oi fnaf ps e t
ShowPageParms
ends

Mode X 256-ColorAnimation 929


Previous Home Next

.model
small
.code
p u b l3i ch o w P a g e
-Showpage n e aprr o c
push bp : p r e s e r v ec a l l e r ’ ss t a c kf r a m e
mov [Link] ; p o i n tt ol o c a ls t a c kf r a m e
: W a i tf o rd i s p l a ye n a b l et ob ea c t i v e( s t a t u si sa c t i v el o w ) .t ob e
: s u r eb o t hh a l v e so ft h es t a r ta d d r e s s will t a k e i n t h e same frame.
[Link]-ADDRESS-LOW
mov : p r e l o a df o rf a s t e s t
mov [Link] yp tt era r t O f f s e t C b p ] : f l i p p i n g o n c ed i s p l a y
cl.START_ADDRESS-HIGH
mov : e n a b l e i sd e t e c t e d
mov c h . b ySpttera r t O f f s e t + l [ b p ]
mov [Link]-STATUSpl
WaitDE:
in a1 .dx
test
- active)
a1 ,Olh
jnz WaitDE ; d i s p l a ye n a b l ei sa c t i v el o w (0
: Setthestartoffsetindisplay memory o f t h e page t o d i s p l a y .
[Link]
mov
mov [Link]
;start [Link] out
mov ax,cx
;start [Link] out
: Now w a i t f o r v e r t i c a l s y n c , s o t h eo t h e rp a g e will b e i n v i s i b l e when
: we s t a r t d r a w i n g t o i t .
mov [Link]-STATUS-1
Wai tVS:
in ,dx a1
test a1 .08h
jz WaitVS : v e r t i c a ls y n ci sa c t i v eh i g h (1 - active)
POP bp : r e s t o r ec a l l e r ’ ss t a c kf r a m e
ret
endp -Showpage
end

Works Fast, Looks Great


We now end ourexploration of Mode X, although we’ll use it again shortly for 3-D
animation. Mode X admittedly has its complexities; that’s why I’ve provided a broad
and flexible primitive set. Still, so what if it is complex? Take a look at Listing 49.5 in
action. That sort of colorful, high-performance animation is worth jumping through
a few hoops for;drawing 20, or even 10, fair-sized objects at a rateof 60 Hz, with no
flicker, interference, orfringe, is no mean accomplishment, even on a 386.
There’s much more we could do with animation in general and with Mode X in
particular, butit’s time to move on to new challenges. Inclosing, I’d like to point out
that all of the VGA’s hardware features, including thebuilt-in AND, OR, and XOR
functions, are available in Mode X, just as they are in the standard VGA modes. If
you understand the VGA’s hardware in mode 12H, try applying that knowledge to
Mode X; you might be surprised at what you find you can do.

930 Chapter 49

You might also like