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

168 lines
9.6 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: Bones and Sinew</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=23//-->
<!--PAGES=427-430//-->
<!--UNASSIGNED1//-->
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="23-01.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="23-03.html">Next</A></TD>
</TR>
</TABLE>
</CENTER>
<P><BR></P>
<H3><A NAME="Heading5"></A><FONT COLOR="#000077">At the Core</FONT></H3>
<P>A little background is necessary before we&#146;re ready to examine Listing 23.1. The VGA is built around four functional blocks, named the CRT Controller (CRTC), the Sequence Controller (SC), the Attribute Controller (AC), and the Graphics Controller (GC). The single-chip VGA could have been designed to treat the registers for all the blocks as one large set, addressed at one pair of I/O ports, but in the EGA, each of these blocks was a separate chip, and the legacy of EGA compatibility is why each of these blocks has a separate set of registers and is addressed at different I/O ports in the VGA.
</P>
<P>Each of these blocks has a sizable complement of registers. It is not particularly important that you understand why a given block has a given register; all the registers together make up the programming interface, and it is the entire interface that is of interest to the VGA programmer. However, the means by which most VGA registers are addressed makes it necessary for you to remember which registers are in which blocks.</P>
<P>Most VGA registers are addressed as <I>internally indexed</I> registers. The internal address of the register is written to a given block&#146;s Index register, and then the data for that register is written to the block&#146;s Data register. For example, GC register 8, the Bit Mask register, is set to 0FFH by writing 8 to port 3CEH, the GC Index register, and then writing 0FFH to port 3CFH, the GC Data register. Internal indexing makes it possible to address the 9 GC registers through only two ports, and allows the entire VGA programming interface to be squeezed into fewer than a dozen ports. The downside is that two I/O operations are required to access most VGA registers.</P>
<P>The ports used to control the VGA are shown in Table 23.1. The CRTC, SC, and GC Data registers are located at the addresses of their respective Index registers plus one. However, the AC Index and Data registers are located at the same address, 3C0H. The function of this port toggles on every <B>OUT</B> to 3C0H, and resets to Index mode (in which the Index register is programmed by the next <B>OUT</B> to 3C0H) on every read from the Input Status 1 register (3DAH when the VGA is in a color mode,</P>
<TABLE WIDTH="75%"><TR>
<TD COLSPAN="2"><HR>
<TR>
<TH WIDTH="45%" ALIGN="LEFT" VALIGN="TOP">Register
<TH WIDTH="30%" VALIGN="TOP" ALIGN="LEFT">Address
<TR>
<TD COLSPAN="2"><HR>
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">AC Index/Data register
<TD VALIGN="TOP" ALIGN="LEFT">3C0H (write with toggle)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">AC Index register
<TD VALIGN="TOP" ALIGN="LEFT">3C0H (read)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">AC Data register
<TD VALIGN="TOP" ALIGN="LEFT">3C1H (read)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">Miscellaneous Output register
<TD VALIGN="TOP" ALIGN="LEFT">3C2H (write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">
<TD VALIGN="TOP" ALIGN="LEFT">3CCH (read)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">Input Status 0 register
<TD VALIGN="TOP" ALIGN="LEFT">3C2H (read)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">SC Index register
<TD VALIGN="TOP" ALIGN="LEFT">3C4H (read/write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">SC Data register
<TD VALIGN="TOP" ALIGN="LEFT">3C5H (read/write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">GC Index register
<TD VALIGN="TOP" ALIGN="LEFT">3CEH (read/write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">GC Data register
<TD VALIGN="TOP" ALIGN="LEFT">3CFH (read/write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">CRTC Index register
<TD VALIGN="TOP" ALIGN="LEFT">3B4H/3D4H (read/write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">CRTC Data register
<TD VALIGN="TOP" ALIGN="LEFT">3B5H/3D5H (read/write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">Input Status 1 register/
<TD VALIGN="TOP" ALIGN="LEFT">
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">AC Index/Data reset
<TD VALIGN="TOP" ALIGN="LEFT">3 BAH/3DAH (read)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">Feature Control
<TD VALIGN="TOP" ALIGN="LEFT">3BAH/3DAH (write)
<TR>
<TD VALIGN="TOP" ALIGN="LEFT">
<TD VALIGN="TOP" ALIGN="LEFT">3CAH (read)
<TR>
<TH CAPTION ALIGN="LEFT" COLSPAN="2">Table 1.1 The Ports through which the VGA is controlled.
<TR>
<TD COLSPAN="2"><HR>
</TABLE>
<P>3BAH in monochrome modes). Note that all CRTC registers are addressed at either 3DXH or 3BXH, the former in color modes and the latter in monochrome modes. This provides compatibility with the register addressing of the now-vanished Color/Graphics Adapter and Monochrome Display Adapter.
</P>
<P>The method used in the VGA BIOS to set registers is to point DX to the desired Index register, load AL with the index, perform a byte <B>OUT</B>, increment DX to point to the Data register (except in the case of the AC, where DX remains the same), load AL with the desired data, and perform a byte <B>OUT</B>. A handy shortcut is to point DX to the desired Index register, load AL with the index, load AH with the data, and perform a word <B>OUT</B>. Since the high byte of the <B>OUT</B> value goes to port DX&#43;1, this is equivalent to the first method but is faster. However, this technique does not work for programming the AC Index and Data registers; both AC registers are addressed at 3C0H, so two separate byte <B>OUT</B>s must be used to program the AC. (Actually, word <B>OUT</B>s to the AC do work in the EGA, but not in the VGA, so they shouldn&#146;t be used.) As mentioned above, you must be sure which mode&#151;Index or Data&#151;the AC is in before you do an <B>OUT</B> to 3C0H; you can read the Input Status 1 register at any time to force the AC to Index mode.</P>
<P>How safe is the word-<B>OUT</B> method of addressing VGA registers? I have, in the past, run into adapter/computer combinations that had trouble with word <B>OUT</B>s; however, all such problems I am aware of have been fixed. Moreover, a great deal of graphics software now uses word <B>OUT</B>s, so any computer or VGA that doesn&#146;t properly support word <B>OUT</B>s could scarcely be considered a clone at all.</P>
<TABLE WIDTH="100%"><TD WIDTH="5%" VALIGN="TOP"><IMG SRC="images/23-01i.jpg"><TD WIDTH="95%" VALIGN="TOP"><SMALL><I>A speed tip: The setting of each chip&#146;s Index register remains the same until it is reprogrammed. This means that in cases where you are setting the same internal register repeatedly, you can set the Index register to point to that internal register once, then write to the Data register multiple times. For example, the Bit Mask register (GC register 8) is often set repeatedly inside a loop when drawing lines. The standard code for this is:</I></SMALL>
</TABLE>
<!-- CODE SNIP //-->
<PRE>
MOV DX,03CEH ;point to GC Index register
MOV AL,8 ;internal index of Bit Mask register
OUT DX,AX ;AH contains Bit Mask register setting
</PRE>
<!-- END CODE SNIP //-->
<TABLE WIDTH="100%">
<TD WIDTH="5%" VALIGN="TOP">
<TD WIDTH="95%" VALIGN="TOP"><SMALL><I>Alternatively, the GC Index register could initially be set to point to the Bit Mask register with</I></SMALL>
</TABLE>
<!-- CODE SNIP //-->
<PRE>
MOV DX,03CEH ;point to GC Index register
MOV AL,8 ;internal index of Bit Mask register
OUT DX,AL ;set GC Index register
INC DX ;point to GC Data register
</PRE>
<!-- END CODE SNIP //-->
<TABLE WIDTH="100%">
<TD WIDTH="5%" VALIGN="TOP">
<TD WIDTH="95%" VALIGN="TOP"><SMALL><I>and then the Bit Mask register could be set repeatedly with the byte-size <B>OUT</B> instruction</I></SMALL>
</TABLE>
<!-- CODE SNIP //-->
<PRE>
OUT DX,AL ;AL contains Bit Mask register setting
</PRE>
<!-- END CODE SNIP //-->
<TABLE WIDTH="100%">
<TD WIDTH="5%" VALIGN="TOP">
<TD WIDTH="95%" VALIGN="TOP"><SMALL><I>which is generally faster (and never slower) than a word-sized <B>OUT</B>, and which does not require AH to be set, freeing up a register. Of course, this method only works if the GC Index register remains unchanged throughout the loop.</I></SMALL>
</TABLE>
<P><BR></P>
<CENTER>
<TABLE BORDER>
<TR>
<TD><A HREF="23-01.html">Previous</A></TD>
<TD><A HREF="index.html">Table of Contents</A></TD>
<TD><A HREF="23-03.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 -->