abrash-black-book/28-04.html
2013-12-30 12:21:49 +11:00

237 lines
11 KiB
HTML

<HTML>
<HEAD>
<META name=vsisbn content="1576101746">
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
<META name=vsauthor content="Michael Abrash">
<META name=vspublisher content="The Coriolis Group">
<META name=vspubdate content="07/01/97">
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Reading VGA Memory</TITLE>
<!-- HEADER -->
<!-- Empty Reference Subhead -->
<!--ISBN=1576101746//-->
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
<!--AUTHOR=Michael Abrash//-->
<!--PUBLISHER=The Coriolis Group, Inc.//-->
<!--CHAPTER=28//-->
<!--PAGES=531-535//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="28-03.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="28-05.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<P><B>LISTING 28.2 L28-2.ASM</B></P>
<!-- CODE //-->
<PRE>
; 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 &amp 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
</PRE>
<!-- END CODE //-->
<H3><A NAME="Heading5"></A><FONT COLOR="#000077">When all Planes &#147;Don&#146;t Care&#148;</FONT></H3>
<P>Still and all, there aren&#146;t all that many uses for basic color compare operations. There is, however, a genuinely odd application of read mode 1 that&#146;s worth knowing about; but in order to understand that, we must first look at the &#147;don&#146;t care&#148; aspect of color compare operation.
</P>
<P>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. But&#151;and it&#146;s a big but&#151;any plane for which the corresponding bit in the Color Don&#146;t Care register is a 0 is always considered a color compare match, regardless of the values of that plane&#146;s bits in the pixels and in the Color Compare register.</P>
<P>Let&#146;s look at this another way. A given pixel is controlled by four bits, one in each plane. Normally (when the Color Don&#146;t 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 Don&#146;t 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.</P>
<P>However, if any bit of the Color Don&#146;t 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 Don&#146;t 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 Don&#146;t 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.</P>
<P>Now, we&#146;re all prone to using tools the &#147;right&#148; way&#151;that is, in the way in which they were intended to be used. By that token, the Color Don&#146;t 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 Don&#146;t Care register becomes far more interesting in exactly the &#147;extreme&#148; case described above, where all planes become &#147;don&#146;t care&#148; planes.</P>
<P>Why? Well, as I&#146;ve said, when all planes are &#147;don&#146;t care&#148; 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 you&#146;re 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 you&#146;re using the bit mask. Traditionally, two separate instructions&#151;a read followed by a write&#151;are used to perform this task. The code in Listing 28.2 uses this approach. Suppose, however, that you&#146;ve set the VGA to read mode 1, with the Color Don&#146;t Care register set to 0 (meaning all reads of VGA memory will return 0FFH). Under these circumstances, you can use a single <B>AND</B> instruction to both read and write VGA memory, since ANDing any value with 0FFH leaves that value unchanged.</P><P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="28-03.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="28-05.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<hr width="90%" size="1" noshade>
<div align="center">
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book &copy; 2001 Michael Abrash</font>
</div>
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
<!-- reference_subfoot = footer -->
<!-- reference_footer = subfoot -->
<!-- BEGIN SUB FOOTER -->
</BODY>
</HTML>
<!-- END FOOTER -->