Previous | Table of Contents | Next

Listing 28.3 illustrates an efficient use of write mode 3 in conjunction with read mode 1 and a Color Don’t Care register setting of 0. The mask in AL is passed directly to the VGA’s bit mask (that’s how write mode 3 works—see Chapter 4 for details). Because the VGA always returns 0FFH, the single AND instruction loads the latches, and writes the value in AL, unmodified, to the VGA, where it is used to generate the bit mask. This is more compact and register-efficient than using separate instructions to read and write, although it is not necessarily faster by cycle count, because on a 486 or a Pentium MOV is a 1-cycle instruction, but AND with memory is a 3-cycle instruction. However, given display memory wait states, it is often the case that the two approaches run at the same speed, and the register that the above approach frees up can frequently be used to save one or more cycles in any case.

By the way, Listing 28.3 illustrates how write mode 3 can make for excellent pixel- and line-drawing code.

LISTING 28.3 L28-3.ASM

    ; Program that draws a diagonal line to illustrate the use of a
    ; Color Don't Care register setting of 0FFH to support fast
    ; read-modify-write operations to VGA memory in write mode 3 by
    ; drawing a diagonal line.
    ;
    ; Note: Works on VGAs only.
    ;
    ; By Michael Abrash
    ;
    stack segment  word stack 'STACK'
         db  512 dup (?)
    stackends
    ;
    VGA_SEGMENT      EQU  0a000h
    SCREEN_WIDTH     EQU  80           ;in bytes
    GC_INDEX         EQU  3ceh         ;Graphics Controller Index register
    SET_RESET        EQU  0            ;Set/Reset register index in GC
    ENABLE_SET_RESET EQU  1            ;Enable Set/Reset register index in GC
    GRAPHICS_MODE    EQU  5            ;Graphics Mode register index in GC
    COLOR_DONT_CARE  EQU  7            ;Color Don't Care register index in GC
    ;
    code  segment  word 'CODE'
         assume    cs:code
    Startprocnear
    ;
    ; Select graphics mode 12h.
    ;
         mov  ax,12h
         int  10h
    ;
    ; Select write mode 3 and read mode 1.
    ;
         mov  dx,GC_INDEX
         mov  al,GRAPHICS_MODE
         out  dx,al
         inc  dx
         in   al,dx               ;VGA registers are readable, bless them!
         or   al,00001011b        ;bit 3=1 selects read mode 1, and
                                  ; bits 1 & 0=11 selects write mode 3
        jmp   $+2                 ;delay between IN and OUT to same port
        out   dx,al
        dec   dx
    ;
    ; Set up set/reset to always draw in white.
    ;
        mov  al,SET_RESET
        out  dx,al
        inc  dx
        mov  al,0fh
        out  dx,al
        dec  dx
        mov  al,ENABLE_SET_RESET
        out  dx,al
        inc  dx
        mov  al,0fh
        out  dx,al
        dec  dx
    ;
    ; Set Color Don't Care to 0, so reads of VGA memory always return 0FFH.
    ;
        mov  al,COLOR_DONT_CARE
        out  dx,al
        inc  dx
        sub  al,al
        out  dx,al
    ;
    ; Set up the initial memory pointer and pixel mask.
    ;
        mov  ax,VGA_SEGMENT
        mov  ds,ax
        sub  bx,bx
        mov  al,80h
    ;
    ; Draw 400 points on a diagonal line sloping down and to the right.
    ;
        mov  cx,400
    DrawDiagonalLoop:
        and  [bx],al            ;reads display memory, loading the latches,
                                ; then writes AL to the VGA. AL becomes the
                                ; bit mask, and set/reset provides the
                                ; actual data written
        add  bx,SCREEN_WIDTH
                                ; point to the next scan line
        ror  al,1               ;move the pixel mask one pixel to the right
        adc  bx,0               ;advance to the next byte if the pixel mask wrapped
    loopDrawDiagonalLoop
    ;
    ; Wait for a key to be pressed to end, then return to text mode and
    ; return to DOS.
    ;
    WaitKeyLoop:
        mov  ah,1
        int  16h
        jz   WaitKeyLoop
        sub  ah,ah
        int  16h                ;clear the key
        mov  ax,3
        int  10h                ;return to text mode
        mov  ah,4ch
        int  21h                ;done
    Startendp
    code ends
        end  Start

I hope I’ve given you a good feel for what color compare mode is and what it might be used for. Color compare mode isn’t particularly easy to understand, but it’s not that complicated in actual operation, and it’s certainly useful at times; take some time to study the sample code and perform a few experiments of your own, and you may well find useful applications for color compare mode in your graphics code.

A final note: The Read Map register has no effect in read mode 1, and the Color Compare and Color Don’t Care registers have no effect either in read mode 0 or when writing to VGA memory. And with that, by gosh, we’re actually done with the basics of accessing VGA memory!

Not to worry—that still leaves us a slew of interesting VGA topics, including smooth panning and scrolling, the split screen, color selection, page flipping, and Mode X. And that’s not to mention actual uses to which the VGA’s hardware can be put, including lines, circles, polygons, and my personal favorite, animation. We’ve covered a lot of challenging and rewarding ground—and we’ve only just begun.

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash