; ; *** Listing 11-33 *** ; ; Illustrates animation based on exclusive-oring. ; Animates 10 images at once. ; Not a general animation implementation, but rather an ; example of the strengths and weaknesses of exclusive-or ; based animation. ; ; Make with LZTIME.BAT, since this program is too long to be ; handled by the precision Zen timer. ; jmp Skip ; DELAY equ 0 ;set to higher values to ; slow down for closer ; observation REPETITIONS equ 500 ;# of times to move and ; redraw the images DISPLAY_SEGMENT equ 0b800h ;display memory segment ; in 320x200 4-color ; graphics mode SCREEN_WIDTH equ 80 ;# of bytes per scan line BANK_OFFSET equ 2000h ;offset from the bank ; containing the even- ; numbered lines on the ; screen to the bank ; containing the odd- ; numbered lines ; ; Used to count down # of times images are moved. ; RepCount dw REPETITIONS ; ; Complete info about one image that we're animating. ; Image struc XCoord dw ? ;image X location in pixels XInc dw ? ;# of pixels to increment ; location by in the X ; direction on each move YCoord dw ? ;image Y location in pixels YInc dw ? ;# of pixels to increment ; location by in the Y ; direction on each move Image ends ; ; List of images to animate. ; Images label Image Image <64,4,8,4> Image <144,0,56,2> Image <224,-4,104,0> Image <64,4,152,-2> Image <144,0,8,-4> Image <224,-4,56,-2> Image <64,4,104,0> Image <144,0,152,2> Image <224,-4,8,4> Image <64,4,56,2> ImagesEnd label Image ; ; Pixel pattern for the one image this program draws, ; a 32x32 3-color square. ; TheImage label byte rept 32 dw 0ffffh, 05555h, 0aaaah, 0ffffh endm IMAGE_HEIGHT equ 32 ;# of rows in the image IMAGE_WIDTH equ 8 ;# of bytes across the image ; ; Exclusive-ors the image of a 3-color square at the ; specified screen location. Assumes images start on ; even-numbered scan lines and are an even number of ; scan lines high. Always draws images byte-aligned in ; display memory. ; ; Input: ; CX = X coordinate of upper left corner at which to ; draw image (will be adjusted to nearest ; less-than or equal-to multiple of 4 in order ; to byte-align) ; DX = Y coordinate of upper left corner at which to ; draw image ; ES = display memory segment ; ; Output: none ; ; Registers altered: AX, CX, DX, SI, DI, BP ; XorImage: push bx ;preserve the main loop's pointer shr dx,1 ;divide the row # by 2 to compensate ; for the 2-bank nature of 320x200 ; 4-color mode mov ax,SCREEN_WIDTH mul dx ;start offset of top row of image in ; display memory shr cx,1 ;divide the X coordinate by 4 shr cx,1 ; because there are 4 pixels per ; byte add ax,cx ;point to the offset at which the ; upper left byte of the image will ; go mov di,ax mov si,offset TheImage ;point to the start of the one image ; we always draw mov bx,BANK_OFFSET-IMAGE_WIDTH ;offset from the end of an even line ; of the image in display memory to ; the start of the next odd line of ; the image mov dx,IMAGE_HEIGHT/2 ;# of even/odd numbered row pairs to ; draw in the image mov bp,IMAGE_WIDTH/2 ;# of words to draw per row of the ; image. Note that IMAGE_WIDTH must ; be an even number since we XOR ; the image a word at a time XorRowLoop: mov cx,bp ;# of words to draw per row of the ; image XorColumnLoopEvenRows: lodsw ;next word of the image pattern xor es:[di],ax ;XOR the next word of the ; image into the screen inc di ;point to the next word in display inc di ; memory loop XorColumnLoopEvenRows add di,bx ;point to the start of the next ; (odd) row of the image, which is ; in the second bank of display ; memory mov cx,bp ;# of words to draw per row of the ; image XorColumnLoopOddRows: lodsw ;next word of the image pattern xor es:[di],ax ;XOR the next word of the ; image into the screen inc di ;point to the next word in display inc di ; memory loop XorColumnLoopOddRows sub di,BANK_OFFSET-SCREEN_WIDTH+IMAGE_WIDTH ;point to the start of the next ; (even) row of the image, which is ; in the first bank of display ; memory dec dx ;count down the row pairs jnz XorRowLoop pop bx ;restore the main loop's pointer ret ; ; Main animation program. ; Skip: ; ; Set the mode to 320x200 4-color graphics mode. ; mov ax,0004h ;AH=0 is mode select fn ;AL=4 selects mode 4, ; 320x200 4-color mode int 10h ;invoke the BIOS video ; interrupt to set the mode ; ; Point ES to display memory for the rest of the program. ; mov ax,DISPLAY_SEGMENT mov es,ax ; ; We'll always want to count up. ; cld ; ; Start timing. ; call ZTimerOn ; ; Draw all the images initially. ; mov bx,offset Images ;list of images InitialDrawLoop: mov cx,[bx+XCoord] ;X coordinate mov dx,[bx+YCoord] ;Y coordinate call XorImage ;draw this image add bx,size Image ;point to next image cmp bx,offset ImagesEnd jb InitialDrawLoop ;draw next image, if ; there is one ; ; Erase, move, and redraw each image in turn REPETITIONS ; times. ; MainMoveAndDrawLoop: mov bx,offset Images ;list of images ImageMoveLoop: mov cx,[bx+XCoord] ;X coordinate mov dx,[bx+YCoord] ;Y coordinate call XorImage ;erase this image (it's ; already drawn at this ; location, so this XOR ; erases it) mov cx,[bx+XCoord] ;X coordinate cmp cx,4 ;at left edge? ja CheckRightMargin ;no neg [bx+XInc] ;yes, so bounce CheckRightMargin: cmp cx,284 ;at right edge? jb MoveX ;no neg [bx+XInc] ;yes, so bounce MoveX: add cx,[bx+XInc] ;move horizontally mov [bx+XCoord],cx ;save the new location mov dx,[bx+YCoord] ;Y coordinate cmp dx,4 ;at top edge? ja CheckBottomMargin ;no neg [bx+YInc] ;yes, so bounce CheckBottomMargin: cmp dx,164 ;at bottom edge? jb MoveY ;no neg [bx+YInc] ;yes, so bounce MoveY: add dx,[bx+YInc] ;move horizontally mov [bx+YCoord],dx ;save the new location call XorImage ;draw the image at its ; new location add bx,size Image ;point to the next image cmp bx,offset ImagesEnd jb ImageMoveLoop ;move next image, if there ; is one if DELAY mov cx,DELAY ;slow down as specified loop $ endif dec [RepCount] ;animate again? jnz MainMoveAndDrawLoop ;yes ; call ZTimerOff ;done timing ; ; Return to text mode. ; mov ax,0003h ;AH=0 is mode select fn ;AL=3 selects mode 3, ; 80x25 text mode int 10h ;invoke the BIOS video ; interrupt to set the mode