Previous | Table of Contents | Next

LISTING 28.1 L28-1.ASM

    ; Program to illustrate the use of the Read Map register in read mode 0.
    ; Animates by copying a 16-color image from VGA memory to system memory,
    ; one plane at a time, then copying the image back to a new location
    ; in VGA memory.
    ;
    ; By Michael Abrash
    ;
    stacksegmentword stack 'STACK'
    db512 dup (?)
    stackends
    ;
    datasegment    word 'DATA'
    IMAGE_WIDTHEQU 4                 ;in bytes
    IMAGE_HEIGHT   EQU   32          ;in pixels
    LEFT_BOUND     EQU   10          ;in bytes
    RIGHT_BOUND    EQU   66          ;in bytes
    VGA_SEGMENT    EQU   0a000h
    SCREEN_WIDTH   EQU   80          ;in bytes
    SC_INDEX       EQU   3c4h        ;Sequence Controller Index register
    GC_INDEX       EQU   3ceh        ;Graphics Controller Index register
    MAP_MASK       EQU   2           ;Map Mask register index in SC
    READ_MAP       EQU   4           ;Read Map register index in GC
    ;
                                     ; Base pattern for 16-color image.
    ;
    PatternPlane0    label byte
         db    32 dup (0ffh,0ffh,0,0)
    PatternPlane1    labelbyte
         db    32 dup (0ffh,0,0ffh,0)
    PatternPlane2    labelbyte
         db    32 dup (0f0h,0f0h,0f0h,0f0h)
    PatternPlane3    labelbyte
         db    32 dup (0cch,0cch,0cch,0cch)
    ;
    ; Temporary storage for 16-color image during animation.
    ;
    ImagePlane0 db   32*4 dup (?)
    ImagePlane1 db   32*4 dup (?)
    ImagePlane2 db   32*4 dup (?)
    ImagePlane3 db   32*4 dup (?)
    ;
    ; Current image location & direction.
    ;
    ImageX          dw  40           ;in bytes
    ImageY          dw  100          ;in pixels
    ImageXDirection dw  1            ;in bytes
    dataends
    ;
    code segment    word 'CODE'
         assume     cs:code,ds:data
    Start proc  near
         cld
         mov  ax,data
         mov  ds,ax
    ;
    ; Select graphics mode 10h.
    ;
         mov  ax,10h
         int  10h
    ;
    ; Draw the initial image.
    ;
         mov  si,offset PatternPlane0
         call DrawImage
    ;
    ; Loop to animate by copying the image from VGA memory to system memory,
    ; erasing the image, and copying the image from system memory to a new
    ; location in VGA memory. Ends when a key is hit.
    ;
    AnimateLoop:
    ;
    ; Copy the image from VGA memory to system memory.
    ;
         mov  di,offset ImagePlane0
         call GetImage
    ;
    ; Clear the image from VGA memory.
    ;
         call EraseImage
    ;
    ; Advance the image X coordinate, reversing direction if either edge
    ; of the screen has been reached.
    ;
         mov  ax,[ImageX]
         cmp  ax,LEFT_BOUND
         jz   ReverseDirection
         cmp  ax,RIGHT_BOUND
         jnz  SetNewX
    ReverseDirection:
         neg  [ImageXDirection]
    SetNewX:
         add  ax,[ImageXDirection]
         mov  [ImageX],ax
    ;
    ; Draw the image by copying it from system memory to VGA memory.
    ;
         mov  si,offset ImagePlane0
         call DrawImage
    ;
    ; Slow things down a bit for visibility (adjust as needed).
    ;
         mov  cx,0
    DelayLoop:
         loop DelayLoop
    ;
    ; See if a key has been hit, ending the program.
    ;
         mov  ah,1
         int  16h
         jz   AnimateLoop
    ;
    ; Clear the key, return to text mode, and return to DOS.
    ;
         sub  ah,ah
         int  16h
         mov  ax,3
         int  10h
         mov  ah,4ch
         int  21h
    Startendp
    ;
    ; Draws the image at offset DS:SI to the current image location in
    ; VGA memory.
    ;
    DrawImageprocnear
         mov  ax,VGA_SEGMENT
         mov  es,ax
         call GetImageOffset   ;ES:DI is the destination address for the
                          ; image in VGA memory
         mov  dx,SC_INDEX
         mov  al,1        ;do plane 0 first
    DrawImagePlaneLoop:
         push di          ;image is drawn at the same offset in
                          ; each plane
         push ax          ;preserve plane select
         mov  al,MAP_MASK ;Map Mask index
         out  dx,al       ;point SC Index to the Map Mask register
         pop  ax          ;get back plane select
         inc  dx          ;point to SC index register
         out  dx,al       ;set up the Map Mask to allow writes to
                          ; the plane of interest
         dec  dx          ;point back to SC Data register
         mov  bx,IMAGE_HEIGHT  ;# of scan lines in image
    DrawImageLoop:
         mov  cx,IMAGE_WIDTH   ;# of bytes across image
         rep  movsb
         add  di,SCREEN_WIDTH-IMAGE_WIDTH
                               ;point to next scan line of image
         dec  bx               ;any more scan lines?
         jnz  DrawImageLoop
         pop  di               ;get back image start offset in VGA memory
         shl  al,1             ;Map Mask setting for next plane
         cmp  al,10h           ;have we done all four planes?
         jnz  DrawImagePlaneLoop
         ret
    DrawImageendp
    ;
    ; Copies the image from its current location in VGA memory into the
    ; buffer at DS:DI.
    ;
    GetImage  proc near
         mov  si,di             ;move destination offset into SI
         call GetImageOffset    ;DI is offset of image in VGA memory
         xchg si,di             ;SI is offset of image, DI is destination offset
         push ds
         pop  es                ;ES:DI is destination
         mov  ax,VGA_SEGMENT
         mov  ds,ax             ;DS:SI is source
    ;
         mov  dx,GC_INDEX
         sub  al,al;do plane 0 first
    GetImagePlaneLoop:
         push si                ;image comes from same offset in each plane
         push ax                ;preserve plane select
         mov  al,READ_MAP       ;Read Map index
         out  dx,al             ;point GC Index to Read Map register
         pop  ax                ;get back plane select
         inc  dx                ;point to GC Index register
         out  dx,al             ;set up the Read Map to select reads from
                                ; the plane of interest
         dec  dx                ;point back to GC data register
         mov  bx,IMAGE_HEIGHT   ;# of scan lines in image
    GetImageLoop:
         mov  cx,IMAGE_WIDTH    ;# of bytes across image
         rep  movsb
         add  si,SCREEN_WIDTH-IMAGE_WIDTH
                                ;point to next scan line of image
         dec  bx                ;any more scan lines?
         jnz  GetImageLoop
         pop  si                ;get back image start offset
         inc  al                ;Read Map setting for next plane
         cmp  al,4              ;have we done all four planes?
         jnz  GetImagePlaneLoop
         push es
         pop  ds                ;restore original DS
         ret
    GetImageendp
    ;
    ; Erases the image at its current location.
    ;
    EraseImage proc near
         mov  dx,SC_INDEX
         mov  al,MAP_MASK
         out  dx,al             ;point SC Index to the Map Mask register
         inc  dx                ;point to SC Data register
         mov  al,0fh
         out  dx,al             ;set up the Map Mask to allow writes to go to
                                ; all 4 planes
         mov  ax,VGA_SEGMENT
         mov  es,ax
         call GetImageOffset    ;ES:DI points to the start address
                                ; of the image
         sub  al,al             ;erase with zeros
         mov  bx,IMAGE_HEIGHT   ;# of scan lines in image
    EraseImageLoop:
         mov  cx,IMAGE_WIDTH    ;# of bytes across image
         rep  stosb
         add  di,SCREEN_WIDTH-IMAGE_WIDTH
                                ;point to next scan line of image
         dec  bx                ;any more scan lines?
         jnz  EraseImageLoop
         ret
    EraseImage endp
    ;
    ; Returns the current offset of the image in the VGA segment in DI.
    ;
    GetImageOffset proc near
         mov  ax,SCREEN_WIDTH
         mul  [ImageY]
         add  ax,[ImageX]
         mov  di,ax
         ret
    GetImageOffset endp
    code  ends
         end  Start

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash