|Previous||Table of Contents||Next|
LISTING 28.2 L28-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 move s,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 loopVLineLoop ; ; 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 next pixel 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 Startendp ; ; Enables set/reset for all planes, and sets the set/reset color ; to AL. ; SelectSetResetColorprocnear 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 SelectSetResetColorendp code ends end Start
Still and all, there arent all that many uses for basic color compare operations. There is, however, a genuinely odd application of read mode 1 thats worth knowing about; but in order to understand that, we must first look at the dont care aspect of color compare operation.
As described earlier, during read mode 1 reads the color stored in the Color Compare register is compared to each of the 8 pixels at a given address in VGA memory. Butand its a big butany plane for which the corresponding bit in the Color Dont Care register is a 0 is always considered a color compare match, regardless of the values of that planes bits in the pixels and in the Color Compare register.
Lets look at this another way. A given pixel is controlled by four bits, one in each plane. Normally (when the Color Dont Care register is 0FH), the color in the Color Compare register is compared to the four bits of each pixel; bit 0 of the Color Compare register is compared to the plane 0 bit of each pixel, bit 1 of the Color Compare register is compared to the plane 1 bit of each pixel, and so on. That is, when the lower four bits of the Color Dont Care register are all set to 1, then all four bits of a given pixel must match the Color Compare register in order for a read mode 1 read to return a 1 for that pixel to the CPU.
However, if any bit of the Color Dont Care register is 0, then the corresponding bit of each pixel is unconditionally considered to match the corresponding bit of the Color Compare register. You might think of the Color Dont Care register as selecting exactly which planes should matter in a given read mode 1 read. At the extreme, if all bits of the Color Dont Care register are 0, then read mode 1 reads will always return 0FFH, since all planes are considered to match all bits of all pixels.
Now, were all prone to using tools the right waythat is, in the way in which they were intended to be used. By that token, the Color Dont Care register is clearly intended to mask one or more planes out of a color comparison, and as such, has limited use. However, the Color Dont Care register becomes far more interesting in exactly the extreme case described above, where all planes become dont care planes.
Why? Well, as Ive said, when all planes are dont care planes, read mode 1 reads always return 0FFH. Now, when you AND any value with 0FFH, the value remains unchanged, and that can be awfully handy when youre using the bit mask to modify selected pixels in VGA memory. Recall that you must always read VGA memory to load the latches before writing to VGA memory when youre using the bit mask. Traditionally, two separate instructionsa read followed by a writeare used to perform this task. The code in Listing 28.2 uses this approach. Suppose, however, that youve set the VGA to read mode 1, with the Color Dont Care register set to 0 (meaning all reads of VGA memory will return 0FFH). Under these circumstances, you can use a single AND instruction to both read and write VGA memory, since ANDing any value with 0FFH leaves that value unchanged.
|Previous||Table of Contents||Next|