Previous | Table of Contents | Next

LISTING 43.1 L43-1.ASM

    ; Program to demonstrate bit-plane animation. Performs
    ; flicker-free animation with image transparency and
    ; image precedence across four distinct planes, with
    ; 13 32x32 images kept in motion at once.
    ;
    ;
    ; Set to higher values to slow down on faster computers.
    ; 0 is fine for a PC. 500 is a reasonable setting for an AT.
    ; Slowing animation further allows a good look at
    ; transparency and the lack of flicker and color effects
    ; when images cross.
    ;
    SLOWDOWN        equ     10000
    ;
    ; Plane selects for the four colors we’re using.
    ;
    RED     equ     01h
    GREEN   equ     02h
    BLUE    equ     04h
    WHITE   equ     08h
    ;
    VGA_SEGMENT     equ     0a000h  ;mode 10h display memory
                                    ; segment
    SC_INDEX        equ     3c4h    ;Sequence Controller Index
                                    ; register
    MAP_MASK        equ     2       ;Map Mask register index in
                                    ; Sequence Controller
    SCREEN_WIDTH    equ     80      ;# of bytes across screen
    SCREEN_HEIGHT   equ     350     ;# of scan lines on screen
    WORD_OUTS_OK    equ     1       ;set to 0 to assemble for
                                    ; computers that can’t
                                    ; handle word outs to
                                    ; indexed VGA regs
                                    ;
    stack segment para stack ‘STACK’
            db      512 dup (?)
    stack ends
    ;
    ; Complete info about one object that we’re animating.
    ;
    ObjectStructure         struc
    Delay   dw      ?       ;used to delay for n passes
                            ; throught the loop to
                            ; control animation speed
    BaseDelay dw    ?       ;reset value for Delay
    Image   dw      ?       ;pointer to drawing info
                            ; for object
    XCoord  dw      ?       ;object X location in pixels
    XInc    dw      ?       ;# of pixels to increment
                            ; location by in the X
                            ; direction on each move
    XLeftLimit dw   ?       ;left limit of X motion
    XRightLimit dw  ?       ;right limit of X motion
    YCoord  dw      ?       ;object Y location in pixels
    YInc    dw      ?       ;# of pixels to increment
                            ; location by in the Y
                            ; direction on each move
    YTopLimit dw    ?       ;top limit of Y motion
    YBottomLimit dw ?       ;bottom limit of Y motion
    PlaneSelect db  ?       ;mask to select plane to
                            ; which object is drawn
              db    ?       ;to make an even # of words
                            ; long, for better 286
                            ; performance (keeps the
                            ; following structure
                            ; word-aligned)
    ObjectStructure ends
    ;
    Data segment    word ‘DATA’
    ;
    ; Palette settings to give plane 0 precedence, followed by
    ; planes 1, 2, and 3. Plane 3 has the lowest precedence (is
    ; obscured by any other plane), while plane 0 has the
    ; highest precedence (displays in front of any other plane).
    ;
    Colors  db      000h    ;background color=black
            db      03ch    ;plane 0 only=red
            db      03ah    ;plane 1 only=green
            db      03ch    ;planes 0&1=red (plane 0 priority)
            db      039h    ;plane 2 only=blue
            db      03ch    ;planes 0&2=red (plane 0 priority)
            db      03ah    ;planes 1&2=green (plane 1 priority)
            db      03ch    ;planes 0&1&2=red (plane 0 priority)
            db      03fh    ;plane 3 only=white
            db      03ch    ;planes 0&3=red (plane 0 priority)
            db      03ah    ;planes 1&3=green (plane 1 priority)
            db      03ch    ;planes 0&1&3=red (plane 0 priority)
            db      039h    ;planes 2&3=blue (plane 2 priority)
            db      03ch    ;planes 0&2&3=red (plane 0 priority)
            db      03ah    ;planes 1&2&3=green (plane 1 priority)
            db      03ch    ;planes 0&1&2&3=red (plane 0 priority)
            db      000h    ;border color=black
    ;
    ; Image of a hollow square.
    ; There’s an 8-pixel-wide blank border around all edges
    ; so that the image erases the old version of itself as
    ; it’s moved and redrawn.
    ;
    Square  label   byte
            dw 48,6    ;height in pixels, width in bytes
            rept    8
            db      0,0,0,0,0,0;top blank border
            endm
            .radix  2
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,00000000,00000000,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            db      0,11111111,11111111,11111111,11111111,0
            .radix  10
            rept    8
            db      0,0,0,0,0,0;bottom blank border
            endm
    ;
    ; Image of a hollow diamond with a smaller diamond in the
    ; middle.
    ; There’s an 8-pixel-wide blank border around all edges
    ; so that the image erases the old version of itself as
    ; it’s moved and redrawn.
    ;
    Diamond label byte
            dw      48,6    ;height in pixels, width in bytes
            rept    8
            db      0,0,0,0,0,0;top blank border
            endm
            .radix  2
            db      0,00000000,00000001,10000000,00000000,0
            db      0,00000000,00000011,11000000,00000000,0
            db      0,00000000,00000111,11100000,00000000,0
            db      0,00000000,00001111,11110000,00000000,0
            db      0,00000000,00011111,11111000,00000000,0
            db      0,00000000,00111110,01111100,00000000,0
            db      0,00000000,01111100,00111110,00000000,0
            db      0,00000000,11111000,00011111,00000000,0
            db      0,00000001,11110000,00001111,10000000,0
            db      0,00000011,11100000,00000111,11000000,0
            db      0,00000111,11000000,00000011,11100000,0
            db      0,00001111,10000001,10000001,11110000,0
            db      0,00011111,00000011,11000000,11111000,0
            db      0,00111110,00000111,11100000,01111100,0
            db      0,01111100,00001111,11110000,00111110,0
            db      0,11111000,00011111,11111000,00011111,0
            db      0,11111000,00011111,11111000,00011111,0
            db      0,01111100,00001111,11110000,00111110,0
            db      0,00111110,00000111,11100000,01111100,0
            db      0,00011111,00000011,11000000,11111000,0
            db      0,00001111,10000001,10000001,11110000,0
            db      0,00000111,11000000,00000011,11100000,0
            db      0,00000011,11100000,00000111,11000000,0
            db      0,00000001,11110000,00001111,10000000,0
            db      0,00000000,11111000,00011111,00000000,0
            db      0,00000000,01111100,00111110,00000000,0
            db      0,00000000,00111110,01111100,00000000,0
            db      0,00000000,00011111,11111000,00000000,0
            db      0,00000000,00001111,11110000,00000000,0
            db      0,00000000,00000111,11100000,00000000,0
            db      0,00000000,00000011,11000000,00000000,0
            db      0,00000000,00000001,10000000,00000000,0
            .radix  10
            rept    8
            db      0,0,0,0,0,0;    bottom blank border
            endm
    ;
    ; List of objects to animate.
    ;
    even;word-align for better 286 performance
    ;
    ObjectListlabelObjectStructure
     ObjectStructure <1,21,Diamond,88,8,80,512,16,0,0,350,RED>
     ObjectStructure <1,15,Square,296,8,112,480,144,0,0,350,RED>
     ObjectStructure <1,23,Diamond,88,8,80,512,256,0,0,350,RED>
     ObjectStructure <1,13,Square,120,0,0,640,144,4,0,280,BLUE>
     ObjectStructure <1,11,Diamond,208,0,0,640,144,4,0,280,BLUE>
     ObjectStructure <1,8,Square,296,0,0,640,144,4,0,288,BLUE>
     ObjectStructure <1,9,Diamond,384,0,0,640,144,4,0,288,BLUE>
     ObjectStructure <1,14,Square,472,0,0,640,144,4,0,280,BLUE>
     ObjectStructure <1,8,Diamond,200,8,0,576,48,6,0,280,GREEN>
     ObjectStructure <1,8,Square,248,8,0,576,96,6,0,280,GREEN>
     ObjectStructure <1,8,Diamond,296,8,0,576,144,6,0,280,GREEN>
     ObjectStructure <1,8,Square,344,8,0,576,192,6,0,280,GREEN>
     ObjectStructure <1,8,Diamond,392,8,0,576,240,6,0,280,GREEN>
    ObjectListEndlabelObjectStructure
    ;
    Dataends
    ;
    ; Macro to output a word value to a port.
    ;
    OUT_WORDmacro
    if WORD_OUTS_OK
            out     dx,ax
    else
            out     dx,al
            inc     dx
            xchg    ah,al
            out     dx,al
            dec     dx
            xchg    ah,al
    endif
            endm
    ;
    ; Macro to output a constant value to an indexed VGA
    ; register.
    ;
    CONSTANT_TO_INDEXED_REGISTERmacro ADDRESS, INDEX, VALUE
            movdx,  ADDRESS
            movax,  (VALUE shl 8) + INDEX
            OUT_WORD
            endm
    ;
    Code    segment
            assume  cs:Code, ds:Data
    Start   proc    near
            cld
            mov     ax, Data
            mov     ds, ax
    ;
    ; Set 640x350 16-color mode.
    ;
            mov     ax,0010h        ;AH=0 means select mode
                                    ;AL=10h means select
                                    ; mode 10h
            int     10h             ;BIOS video interrupt
    ;
    ; Set the palette up to provide bit-plane precedence. If
    ; planes 0 & 1 overlap, the plane 0 color will be shown;
    ; if planes 1 & 2 overlap, the plane 1 color will be
    ; shown; and so on.
    ;
            mov  ax,(10h shl 8) + 2      ;AH = 10h means
                                         ; set palette
                                         ; registers fn
                                         ;AL = 2 means set
                                         ; all palette
                                         ; registers
            push    ds                   ;ES:DX points to
            pop     es                   ; the palette
            mov     dx,offset Colors     ; settings
            int     10h                  ;call the BIOS to
                                         ; set the palette
    ;
    ; Draw the static backdrop in plane 3. All the moving images
    ; will appear to be in front of this backdrop, since plane 3
    ; has the lowest precedence the way the palette is set up.
    ;
            CONSTANT_TO_INDEXED_REGISTER SC_INDEX, MAP_MASK, 08h
                                            ;allow data to go to
                                            ; plane 3 only
    ;
    ; Point ES to display memory for the rest of the program.
    ;
            mov     ax,VGA_SEGMENT
            mov     es,ax
    ;
            sub     di,di
            mov     bp,SCREEN_HEIGHT/16     ;fill in the screen
                                            ; 16 lines at a time
    BackdropBlockLoop:
            call    DrawGridCross           ;draw a cross piece
            call    DrawGridVert            ;draw the rest of a
                                            ; 15-high block
            dec     bp
            jnz     BackdropBlockLoop
            call    DrawGridCross           ;bottom line of grid
    ;
    ; Start animating!
    ;
    AnimationLoop:
            mov     bx,offset ObjectList    ;point to the first
                                            ; object in the list
    ;
    ; For each object, see if it’s time to move and draw that
    ; object.
    ;
    ObjectLoop:
    ;
    ; See if it’s time to move this object.
    ;
            dec  [bx+Delay]            ;count down delay
            jnz  DoNextObject          ;still delaying-don’t move
            mov  ax,[bx+BaseDelay]
            mov  [bx+Delay],ax         ;reset delay for next time
    ;
    ; Select the plane that this object will be drawn in.
    ;
            mov     dx,SC_INDEX
            mov     ah,[bx+PlaneSelect]
            mov     al,MAP_MASK
            OUT_WORD
    ;
    ; Advance the X coordinate, reversing direction if either
    ; of the X margins has been reached.
    ;
            mov     cx,[bx+XCoord]          ;current X location
            cmp     cx,[bx+XLeftLimit]      ;at left limit?
            ja      CheckXRightLimit        ;no
            neg     [bx+XInc]               ;yes-reverse
    CheckXRightLimit:
            cmp     cx,[bx+XRightLimit]     ;at right limit?
            jb      SetNewX                 ;no
            neg     [bx+XInc]               ;yes-reverse
    SetNewX:
            add     cx,[bx+XInc]            ;move the X coord
            mov     [bx+XCoord],cx          ; & save it
    ;
    ; Advance the Y coordinate, reversing direction if either
    ; of the Y margins has been reached.
    ;
            mov     dx,[bx+YCoord]    ;current Y location
            cmp     dx,[bx+YTopLimit]   ;at top limit?
            ja      CheckYBottomLimit   ;no
            neg     [bx+YInc]    ;yes-reverse
    CheckYBottomLimit:
            cmp     dx,[bx+YBottomLimit]    ;at bottom limit?
            jb      SetNewY    ;no
            neg     [bx+YInc]    ;yes-reverse
    SetNewY:
            add     dx,[bx+YInc]    ;move the Y coord
            mov     [bx+YCoord],dx    ; & save it
    ;
    ; Draw at the new location. Because of the plane select
    ; above, only one plane will be affected.
    ;
            mov     si,[bx+Image]   ;point to the
                                    ; object’s image
                                    ; info
            call    DrawObject
    ;
    ; Point to the next object in the list until we run out of
    ; objects.
    ;
    DoNextObject:
            add     bx,size ObjectStructure
            cmp     bx,offset ObjectListEnd
            jb      ObjectLoop
    ;
    ; Delay as specified to slow things down.
    ;
    if SLOWDOWN
            mov     cx,SLOWDOWN
    DelayLoop:
            loop    DelayLoop
    endif
    ;
    ; If a key’s been pressed, we’re done, otherwise animate
    ; again.
    ;
    CheckKey:
            mov     ah,1
            int     16h             ;is a key waiting?
            jz      AnimationLoop   ;no
            sub     ah,ah
            int     16h             ;yes-clear the key & done
    ;
    ; Back to text mode.
    ;
            mov     ax,0003h        ;AL=03h means select
                                    ; mode 03h
            int     10h
    ;
    ; Back to DOS.
    ;
            mov     ah,4ch          ;DOS terminate function
            int     21h             ;done
    ;
    Start endp
    ;
    ; Draws a single grid cross-element at the display memory
    ; location pointed to by ES:DI. 1 horizontal line is drawn
    ; across the screen.
    ;
    ; Input: ES:DI points to the address at which to draw
    ;
    ; Output: ES:DI points to the address following the
    ;       line drawn
    ;
    ; Registers altered: AX, CX, DI
    ;
    DrawGridCross   proc    near
            mov     ax,0ffffh       ;draw a solid line
            mov     cx,SCREEN_WIDTH/2-1
            rep     stosw           ;draw all but the rightmost
                                    ; edge
            mov     ax,0080h
            stosw                   ;draw the right edge of the
                                    ; grid
            ret
    DrawGridCross   endp
    ;
    ; Draws the non-cross part of the grid at the display memory
    ; location pointed to by ES:DI. 15 scan lines are filled.
    ;
    ; Input: ES:DI points to the address at which to draw
    ;
    ; Output: ES:DI points to the address following the
    ;       part of the grid drawn
    ;
    ; Registers altered: AX, CX, DX, DI
    ;
    DrawGridVert    proc    near
            mov     ax,0080h        ;pattern for a vertical line
            mov     dx,15           ;draw 15 scan lines (all of
                                    ; a grid block except the
                                    ; solid cross line)
    BackdropRowLoop:
            mov     cx,SCREEN_WIDTH/2
            rep     stosw           ;draw this scan line’s bit
                                    ; of all the vertical lines
                                    ; on the screen
            dec     dx
            jnz     BackdropRowLoop
            ret
            DrawGridVert    endp
    ;
    ; Draw the specified image at the specified location.
    ; Images are drawn on byte boundaries horizontally, pixel
    ; boundaries vertically.
    ; The Map Mask register must already have been set to enable
    ; access to the desired plane.
    ;
    ; Input:
    ;       CX - X coordinate of upper left corner
    ;       DX - Y coordinate of upper left corner
    ;       DS:SI - pointer to draw info for image
    ;       ES - display memory segment
    ;
    ; Output: none
    ;
    ; Registers altered: AX, CX, DX, SI, DI, BP
    ;
    DrawObject      proc    near
            mov     ax,SCREEN_WIDTH
            mul     dx              ;calculate the start offset in
                                    ; display memory of the row the
                                    ; image will be drawn at
            shr     cx,1
            shr     cx,1
            shr     cx,1            ;divide the X coordinate in pixels
                                    ; by 8 to get the X coordinate in
                                    ; bytes
            add     ax,cx           ;destination offset in display
                                    ; memory for the image
            mov     di,ax           ;point ES:DI to the address to
                                    ; which the image will be copied
                                    ; in display memory
            lodsw
            mov     dx,ax           ;# of lines in the image
            lodsw                   ;# of bytes across the image
            mov     bp,SCREEN_WIDTH
            subbp,ax                ;# of bytes to add to the display
                                    ; memory offset after copying a line
                                    ; of the image to display memory in
                                    ; order to point to the address
                                    ; where the next line of the image
                                    ; will go in display memory
    DrawLoop:
            mov     cx,ax           ;width of the image
            rep     movsb           ;copy the next line of the image
                                    ; into display memory
            add     di,bp           ;point to the address at which the
                                    ; next line will go in display
                                    ; memory
            dec     dx              ;count down the lines of the image
            jnzDrawLoop
            ret
    DrawObjectendp
    ;
    Code    ends
            end     Start

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash