EarthWeb   
   datamation.com Brought to you by EarthWeb

HomeSubscribeSearchFAQSitemapContact Us
     

   

  Search Tips
  Advanced Search
   
  

  
Go to ITKnowledge Enterprise

Zen of Graphics Programming, 2nd Edition Zen of Graphics Programming, 2nd Edition
by Michael Abrash
Coriolis, The Coriolis Group
ISBN: 1883577896   Pub Date: 04/01/96

Search this book:
 
Previous Table of Contents Next


By the way, the code in Listing 6.1 is intended only to illustrate read mode 0, and is, in general, a poor way to perform animation, since it’s slow and tends to flicker. Later in this book, we’ll take a look at some far better VGA animation techniques.

As you’d expect, neither the read mode nor the setting of the Read Map register affects CPU writes to VGA memory in any way.

An important point regarding reading VGA memory involves the VGA’s latches. (Remember that each of the four latches stores a byte for one plane; on CPU writes, the latches can provide some or all of the data written to display memory, allowing fast copying and efficient pixel masking.) Whenever the CPU reads a given address in VGA memory, each of the four latches is loaded with the contents of the byte at that address in its respective plane. Even though the CPU only receives data from one plane in read mode 0, all four planes are always read, and the values read are stored in the latches. This is true in read mode 1 as well. In short, whenever the CPU reads VGA memory in any read mode, all four planes are read and all four latches are always loaded.

Read Mode 1

Read mode 0 is the workhorse read mode, but it’s got an annoying limitation: Whenever you want to determine the color of a given pixel in read mode 0, you have to perform four VGA memory reads, one for each plane, and then interpret the four bytes you’ve read as eight 16-color pixels. That’s a lot of programming. The code is also likely to run slowly, all the more so because a standard IBM VGA takes an average of 1.1 microseconds to complete each memory read, and read mode 0 requires four reads in order to read the four planes, not to mention the even greater amount of time taken by the OUTs required to switch between the planes. (1.1 microseconds may not sound like much, but on a 66-MHz 486, it’s 73 clock cycles! Local-bus VGAs can be a good deal faster, but a read from the fastest local-bus adapter I’ve yet seen would still cost in the neighborhood of 10 486/66 cycles.)

Read mode 1, also known as color compare mode, provides special hardware assistance for determining whether a pixel is a given color. With a single read mode 1 read, you can determine whether each of up to eight pixels is a specific color, and you can even specify any or all planes as “don’t care” planes in the pixel color comparison.

Read mode 1 is selected by setting bit 3 of the Graphics Mode register (Graphics Controller register 5) to 1. In its simplest form, read mode 1 compares the cross-plane value of each of the eight pixels at a given address to the color value in bits 3-0 of the Color Compare register (Graphics Controller register 2), and returns a 1 to the CPU in the bit position of each pixel that matches the color in the Color Compare register and a 0 for each pixel that does not match.

That’s certainly interesting, but what’s read mode 1 good for? One obvious application is in implementing flood-fill algorithms, since read mode 1 makes it easy to tell when a given byte contains a pixel of a boundary color. Another application is in detecting on-screen object collisions, as illustrated by the code in Listing 6.2.

LISTING 6.2 L6-2.ASM

; Program to illustrate use of read mode 1 (color compare mode)
; to detect collisions in display memory. Draws a yellow line on a
; blue background, then draws a perpendicular green line until the
; yellow line is reached.
;
; By Michael Abrash
;
stack   segment word stack 'STACK'
         db       512 dup (?)
stack   ends
;
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
COLOR_COMPARE             EQU      2       ;Color Compare register index
                                           in GC
GRAPHICS_MODE             EQU      5       ;Graphics Mode register index
                                           in GC
BIT_MASK                    EQU      8        ;Bit Mask register index in
                                              GC
;
code               segment          word 'CODE'
                   assume           cs:code
Start             proc              near
                   cld
;
; Select graphics mode 10h.
;
         mov      ax,10h
         int      10h
;
; Fill the screen with blue.
;
         mov      al,1                         ;blue is color 1
         call     SelectSetResetColor      ;set to draw in blue
         mov      ax,VGA_SEGMENT
         mov      es,ax
         sub      di,di
         mov      cx,7000h
         rep      stosb             ;the value written actually doesn't
                                     ; matter, since set/reset is
                                     ; providing the data written
                                     ; to display memory
;
; Draw a vertical yellow line.
;
         mov      al,14                       ;yellow is color 14
         call     SelectSetResetColor     ;set to draw in yellow
         mov      dx,GC_INDEX
         mov      al,BIT_MASK
         out      dx,al                       ;point GC Index to Bit Mask
         inc      dx                          ;point to GC Data
         mov      al,10h
         out      dx,al                       ;set Bit Mask to 10h
         mov      di,40                       ;start in the middle of the
                                              top line
         mov      cx,350                      ;do full height of screen
VLineLoop:
         mov      al,es:[di]                  ;load the latches
         stosb                       ;write next pixel of yellow line
                                     ; (set/reset provides the data
                                     ; written to display
                                     ; memory, and AL is actually ignored)
         add      di,SCREEN_WIDTH-1        ;point to the next scan line
         loop     VLineLoop
;
; Select write mode 0 and read mode 1.
;
         mov      dx,GC_INDEX
         mov      al,GRAPHICS_MODE
         out      dx,al            ;point GC Index to Graphics Mode
                                   register
         inc      dx                 ;point to GC Data
         mov      al,00001000b    ;bit 3=1 is read mode 1, bits 1 & 0=00
                                     ; is write mode 0
         out      dx,al            ;set Graphics Mode to read mode 1,
                                     ; write mode 0
;
; Draw a horizontal green line, one pixel at a time, from left
; to right until color compare reports a yellow pixel is encountered.
;
; Draw in green.
;
         mov      al,2                        ;green is color 2
         call     SelectSetResetColor     ;set to draw in green
;
; Set color compare to look for yellow.
;
         mov      dx,GC_INDEX
         mov      al,COLOR_COMPARE
         out      dx,al            ;point GC Index to Color Compare
                                   register
         inc      dx                 ;point to GC Data
         mov      al,14            ;we're looking for yellow, color 14
         out      dx,al            ;set color compare to look for yellow
         dec      dx                 ;point to GC Index
;
; Set up for quick access to Bit Mask register.
;
         mov      al,BIT_MASK
         out      dx,al            ;point GC Index to Bit Mask register
         inc      dx                 ;point to GC Data
;
; Set initial pixel mask and display memory offset.
;
         mov      al,80h                      ;initial pixel mask
         mov      di,100*SCREEN_WIDTH
                                              ;start at left edge of scan
                                              line 100
HLineLoop:
         mov      ah,es:[di]       ;do a read mode 1 (color compare) read.
                                      ; This also loads the latches.
         and      ah,al             ;is the pixel of current interest
                                    yellow?
         jnz      WaitKeyAndDone  ;yes-we've reached the yellow line, so
                                  we're
                                      ; done
         out      dx,al             ;set the Bit Mask register so that we
                                      ; modify only the pixel of interest
         mov     es:[di],al         ;draw the pixel. The value written is
                                       ; irrelevant, since set/reset is
                                       ; providing the data written
                                       ; to display memory
         ror     al,1                  ;shift pixel mask to the nextpixel
         adc     di,0                  ;advance the display memory offset
                                       ; if the pixel mask wrapped
;
; Slow things down a bit for visibility (adjust as needed).
;
         mov     cx,0
DelayLoop:
         loop    DelayLoop

         jmp     HLineLoop
;
; Wait for a key to be pressed to end, then return to text mode and
; return to DOS.
;
WaitKeyAndDone:
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
Start   endp
;
; Enables set/reset for all planes, and sets the set/reset color
; to AL.
;
SelectSetResetColor     proc     near
         mov      dx,GC_INDEX
         push     ax                 ;preserve color
         mov      al,SET_RESET
         out      dx,al            ;point GC Index to Set/Reset register
         inc      dx                 ;point to GC Data
         pop      ax                 ;get back color
         out      dx,al            ;set Set/Reset register to selected
                                   color
         dec      dx                 ;point to GC Index
         mov      al,ENABLE_SET_RESET
         out      dx,al            ;point GC Index to Enable Set/Reset
                                   register
         inc      dx                 ;point to GC Data
         mov      al,0fh
         out      dx,al            ;enable set/reset for all planes
         ret
SelectSetResetColor     endp
code     ends
         end      Start


Previous Table of Contents Next

homesubscribesearchfaqsitemapcontactus
Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.