Programming the VGA Registers
by Boone (boone@ucsd.edu), March '94
The IBM PC has long been slammed by owners of other computers which come
with superior graphics capabilities built right into hardware. The PC is a
strange beast to program in general, and when it comes to graphics the
programmer doesn't get much help from the video hardware. However, there are
quite a few neat tricks you can do using the VGA registers, as I'm sure you're
aware. The trick is knowing just which registers to use and how to use them to
achieve the desired results. In particular, precise timing is necessary to
avoid screen flicker and/or "snow". The registers on your video card are
necessary for just about any communication with the VGA besides basic
reading/writing of pixels. Some of the registers are standard, which are the
ones we will be discussing here. Most SVGA chipsets have their own special
functions associated with different registers for things such as bank
switching, which is part of what makes trying to write SVGA programs so
difficult. The registers are also used to set the various attributes of each
video mode: horizontal and vertical resolution, color depth, refresh rate,
chain-4 mode, and so on. Luckily, BIOS handles all this for us and since we
only need to set the video mode once at program start-up and once at exit, you
should need to mess with these particular functions too much, unless you are
using a special mode, such as mode X. (See the mode X section for more info on
all this.) If you want to experiment with the video mode registers, ftp
yourself a file called TWEAK*.* (my version is TWEAK10.ZIP). For now we'll
just assume the video mode has already been set to whatever mode you wish.
One of the most common techniques used by game programmers is fade in/out.
A clean fade is simple but very effective. Suprisingly, even big-budget games
like Ultima VII often have a lot of screen noise during their fades. With a
little effort you can easily write your own noise-free fade routines. There's
nothing like giving a professional first impression on your intro screen, since
the fade-in is likely to be the very first thing they see of your program.
BIOS is much to slow for this timing-critical opperation, so we'll have to
get down and dirty with our VGA card. Fading is a fairly simple process. As
you should know, the VGA palette consists of 256 colors with 3 attributes for
each color: red, green and blue. Every cycle of the fade, we have to go
through all 768 attributes and if it is larger than 0 subtract one. We'll use
regsiters 3C8h and 3C9h for palette opperations. The operation for sending a
palette to the card is straight-forward: send a 0 to port 3C8h and then your
768 byte buffer to port 3C9h. This is good enough for setting the palette at
the start of your program, but of course it has to go in a loop for the fade,
since you'll have to do this 256 times, subtracting one from each non-zero
member of the buffer. The pseudo-code looks something like this:
constant PALSIZE = 256*3;
unsigned character buffer[PALSIZE];
boolean done;
counter i,j;
for j = 255 to 0
{
for i = 0 to PALSIZE-1
if buffer[i] > 0
buffer[i] = buffer[i] - 1;
output 0 to port 3C8h;
for i = 0 to PALSIZE-1
output buffer[i] to port 3C9h;
}
Easy enough, right? If you convert this to the language of your choice it
should run fine. (Make sure you have the buffer pre-loaded with the correct
palette, however, or you will get very strange results...) But you'll notice
the "snow" mentioned earlier. Depending on your video card, this could mean
that you see no noise at all to fuzz covering your entire screen. Even if it
look fine on your system, however, we want to make sure it will be smooth on
*all* setups it could potentially be run on. For that we're going to have to
ask the video card when it's safe to send the palette buffer to the card, and
for that we'll need the retrace register.
Putting aside palette concerns for a moment, I'll briefly cover the retrace
on your video card. (See the next section of this article for a more in-depth
discussion of this.) Bascially the vertical retrace is a short time in which
the screen is not being updated (from video memory to your monitor) and you can
safely do writes to your video memory or palette without worrying about getting
snow, flicker, tearing, or other unwanted side-effects. This is a pretty quick
period (retrace occurs 60 to 70 times a second) so you can't do too much at
once.
Returning to our fade: we want to update the palette during the vertical
retrace. The value we want is bit 3 of register 3DAh. While that bit is zero
we're safe to write. The best practice in this case is to wait for the bit to
change to one (screen is being traced) and then the instant it changes to 0,
blast all our new video info to the card. It won't be necessary in this case
since all we are doing is fading the palette and then waiting for the next
retrace, but if you're doing animation or playing music at the same time
you'll want to include this extra bit of code as a safety net. Otherwise you
might detect the 0 in the refresh bit at the very last instant of the retrace
and end up writing while the screen is being traced. The pseudo-code now goes
like this:
for j = 255 to 0
{
for i = 0 to PALSIZE-1
if buffer[i] > 0
buffer[i] = buffer[i] - 1;
while bit 3 of port 3DAh is 0
no opperation;
while bit 3 of port 3DAh is 1
no opperation;
output 0 to port 3C8h;
for i = 0 to PALSIZE-1
output buffer[i] to port 3C9h;
}
That's it! All that's left is for you to implement it in your favorite
language. However, I can hear the cries right now: "Code! Give us some real
assembly code we can use!" I'm reluctant to provided it as this is the exact
sort of thing that is easy to cut and paste into your program without knowing
how it works. However, I'll give you the unoptimized main loop in 80x86
assembly as this may be clearer to you that my explanation or pseudo-code. Two
things to remember about this code: it is optimized enough to be smooth on any
video card (or any that I've seen, anyway) assuming that the fade is the _only_
thing going on. There's some other things you may want to change if you plan
to say, play music during this process. Secondly, you'll need to have the
current palette loaded into the buffer beforehand. You could read it from the
VGA card using either registers or BIOS, but this is both slow and (in my
oppinion) sloppy coding. You should *never* ask the video card about anything
(excluding retrace) that you could keep track of yourself. In the case of the
palette, you probably already loaded it from disk anyway, or if you are using
the default palette just read the values once and store
them in your executable or in a resource file.
palbuf DB 768 DUP (?)
fadecnt DW 040h
; At this point, you should:
; 1) have the video mode set
; 2) have palbuf loaded with the current palette
; 3) have something on the screen to fade!
fadeloop:
xor al,al ; used for comparisons and port 3D8h
mov cx,768 ; loop counter
mov si,offset palbuf ; save palette buffer in si
decloop:
mov dl,[si] ; put next pal reg in dx
cmp al,dl ; is it 0?
je next ; nope...
dec dl ; yes, so subtract one
mov [si],dl ; put it back into palette buffer
next:
dec cx ; decrement counter
inc si ; increment our buffer
cmp cx,0
jne decloop ; not done yet, so loop around
mov cx,768 ; reset for palette output
sub si,768 ; reset palbuf pointer
mov dx,03c8h
out dx,al ; inform VGA of palette change
inc dx ; DX = 3C8h + 1 = 3C9h
mov ch,02h ; do outter loop 2 times
mov dx,03dah ; prepare refresh register
mov bx,03c9h ; prepare palette reg (for quick loading)
cli ; disable interrupts!
outloop:
mov cl,80h ; do inner loop 128 times
in al,dx ; wait for current retrace to end
test al,08h
jnz $-5
in al,dx ; wait for current screen trace to end
test al,08h
jz $-5
mov dx,bx ; load up the palette change register
innerloop:
mov al,[si] ; load next byte of palbuf
out dx,al ; send it to the VGA card
dec cl ; decrement counter
inc si ; increment palbuf pointer
cmp cl,0
jne innerloop ; loop while not done
dec ch ; decrement outer loop counter
cmp ch,0
jne outloop ; loop while not done
sti ; restore interrupts
mov ax,fadecnt ; entire palette has been sent
dec ax ; so check fade loop
mov fadecnt,ax
cmp ax,0 ; ready to quit?
jne fadeloop ; nope, keep fading!
I should add a few comments about this code segment. First of all, it
assumes you want to fade every color all the way down. You may only want to
fade certain sections of the palette (if your screen was only using a certain
number of colors) or maybe your palette is low-intensity so you don't need to
go the full 256 loops to get every color down to 0. It also goes by ones, so
if you want a faster fade you can have it subtract two from each attribute.
If you want to fade to a certain color other than black (for instance, fade to
red such as the "getting hit" effect in Doom), you'll need to check if each
attribute is above or below your target color and increment or decrement
accordingly. Also, you may have noticed something in the code absent from the
pseudo-code: it only sends 128 colors to the card each retrace! This is
because if you use all 256 the next retrace may start before you get all colors
sent to the video card, thanks to the unoptimized code. Some recommend as
little as 64 colors per retrace, however I've found 128 to be okay and
certainly much faster. The above code works for any VGA-equiped machine,
regardless of processor, but you'll probably want to compress all the IN and
OUT loops into REP INSB/OUTSB, REP INSW/OUTSW, or REP INSD/OUTSD instructions
depending upon the minimum processor requirement for your game/demo.
I won't describe fading in since it's the same sort of thing, and I'm sure
you can figure it out once you know how to use the registers themselves. It's
a little more complicated since you need a second buffer of target values for
your attributes, but otherwise quite similar.
Next up is vertical retrace. This is simply one of many read registers on
your VGA, but it happens to be one of the most useful for animation and palette
fades (as shown above). Here's a quick rundown of what exactly the vertical
retrace is, and why it's useful.
There's an electron gun in the back of your monitor that keeps the pixels
"refreshed" with their correct values every 1/60th of a second or so. It fires
electrons at each pixel, row by row. The horizontal retrace is the time it
takes it to return from the right side of the screen after it has traced a row.
This is a very short time and I wouldn't worry about that too much right now,
as it is only useful for very specialized (and quite tricky) hardware effects.
More useful, however, is the vertical retrace which occurs when the electron
gun reaches the bottom of the screen (one entire screen traced) and it returns
diagonally to the upper-right hand corner of the screen. During this time you
are free to update anything you like having to do with video with no noise or
interference (since nothing on the screen is being updated). This is a fairly
short amount of time, though, so whatever you want to do you better do it
_quickly_. For animation, you'll usually want to keep a second buffer in main
memory (remember that video RAM is quite slow compared to main RAM) which you
can use to write your animations to. When the vertical retrace occurs, you'll
want to blast the entire thing to the VGA as quickly as possible, using a
memory copy instruction. You can find more on this in articles which cover
animation.
Lastly I'll briefly describe the VGA mode-set registers. There are quite a
number of them and for the most part they're pretty boring. By sending
different values to these registers you can achieve the various video modes
that your card is capable of. These registers set values such as horizontal
and vertical resolution, retrace timing, addressing modes, color depth, timing,
and other fun stuff. The truth is that it's easier and just as effective to
let the BIOS (gasp!) handle setting the screen mode for you, particularly since
most games use standard modes such as 320x200 anyway. At the very least you
can let BIOS set the mode to begin with and then just modify the registers to
"tweak" the mode the way you want it. Any of these non-BIOS modes are
generally refered to as mode X. I don't want to go deep into detail on the
setting and usage of mode X because there is already so much info availible on
the topic. Check out the Mode X Faq (regularly posted in comp.sys.ibm.pc.demos
and rec.games.programmer), Micheal Abrash's collumn in Dr. Dobb's and his
X-sharp library, or the section on mode X in the PC-GPE.
One mode register I'll cover quickly is the chain-4 enable/disable. A lot
of programmers seem to have trouble visualizing what this thing does exactly.
Bit 3 of port 3C4h (index 4) controls chain-4 mode. Normally it is on. This
allows fast linear addressing of the bytes in video memory, which is the way
you are probably used to addressing them. For example, to change the second
pixel on the screen to a certain color, you simply write the value to address
A000:0001. With chain-4 disabled (the main feature of mode X besides better
resolution) A000:0000 refers to the first pixel in the upper-left corner of
your screen, A000:0001 refers to the fourth pixel, A000:0002 to the eight pixel
and so on. The odd pixels are accessed by changing the write plane. Since
there are four planes, you effectively get an extra two bits of addressing
space, boosting the total bit width for your pixel addressing from 16 to 18.
Standard chain-4 four only allows access to 64K of memory (2^16) while
disabling this feature gives you the full 256K (2^18) of memory to work with.
The disadvantage, of course, is that pixel writes are slower due to the port
writes required to access odd pixels. How can this be an advantage? For one
thing, you can write four pixels at a time as long as they are all the same
color - handy for single-color polygons, as in flight simulators. Secondly,
you get four times as much memory. This allows you to have higher resolutions
without bank switching, or scroll the screen using hardware scrolling, or do
page flipping for smooth animation. And since you can change the resolution,
you can give yourself a sqaure aspect ration (320x240) which is better for
bitmap rotations and the like. But remember that it can be slower for
bitmapped graphics because you have to do at least four writes to the card (to
change planes) in order to copy bitmaps from main RAM to video memory. Don't
use mode X just because you think it's "cool"; make sure you have a good reason
for wanting to use it in your program, or otherwise you're wasting a lot of
effort for no reason.
Now, I'm sure you want me to continue until I divulge all the secrets of the
VGA register to you - but, I only have some much time and space. Besides, I
still haven't uncovered all of their mysteries and capabilities myself.
However, below is a list of the registers which you may want to play with for
various effects. The following list was posted on rec.games.programmer by
Andrew Bromage (bromage@mundil.cs.mu.OZ.AU), so thanks to him for posting in to
begin with.
That's it for this article and I hope it helped you understand your VGA card
a little better. If not, re-read it, and try writing your own programs which
use the registers. The only way to really understand it (as with most things)
is to get some hands-on experience.
If you've got any questions, comments, flames, or corrections related to
this document or game programming/design in general, feel free to post an
article in rec.games.programmer (in case you haven't noticed by now, I hang out
there regularly) or send mail to boone@ucsd.edu.
Here's the list. Have fun...
Documentation Over the I/O Registers for Standard VGA Cards
Documentated by Shaggy of The Yellow One
Email: D91-SJD@TEKN.HJ.SE
Feel free to spread this to whoever wants it.....
------------------------------------------------------------
Port-Index: - Port: Write/03c2h Read/03cch
usage: d7 Vertical sync polarity
d6 Horizontal sunc polarity
d5 Odd /even page
d4 Disable video
d3 Clock select 1
d2 Clock select 0
d1 Enable/Disable display RAM
d0 I/O address select
Description: Sync polarity: Bits are set as below for VGA displays
that use sync polarity to determine screen resolution.
Many newer multiple frequency displays are insensitive
to sync polarity
d7 d6 Resolution
0 0 Invalid
0 1 400 lines
1 0 350 lines
1 1 480 lines
I/O address select: When set to zero, selects the
monochrome I/O address space (3bx). When set to one,
it selects the color I/O address space (3dx)
------------------------------------------------------------
Port-Index: - Port: 03c2h ; read only
usage: d7 Vertical Retrace Interrupt pendling
d6 Feature connector bit 1
d5 Feature connector bit 0
d4 Switch sense
d0-d3 Unused
Description: d7 uses IRQ2
------------------------------------------------------------
Port-Index: - Port: 03bah,03dah ; read only
usage: d3 Vertical retrace
d0 Horizontal retrace
------------------------------------------------------------
Port-Index: - Port: 03c3h,46e8h
usage: d7-d1 Reserved
d0 VGA enable/disable (03c3h only)
Description: Disables access to display memmory and the other
VGA's ports
------------------------------------------------------------
Port-Index: 00h Port: 03d4h, 03b4h
usage: Horizontal total
Description: Total number of characters in horizontal scan minus
five ( including blanked and border characters)
------------------------------------------------------------
Port-Index: 01h Port: 03d4h, 03b4h
usage: Horizontal display enable
Description: Total number of characters displayed in horizontal
scan minus one.
------------------------------------------------------------
Port-Index: 02h Port: 03d4h, 03b4h
usage: Start horizontal blanking
Description: Character at which blanking starts
------------------------------------------------------------
Port-Index: 03h Port: 03d4h, 03b4h
usage: End horizontal blanking
d7 Test
d6 Skew control
d5 Skew control
d0-d4 End blanking
Description: End blanking: is five LSB bits of six-bit value,
which define the character at which blanking stops.
The MSB bit of this value is in register index 5.
------------------------------------------------------------
Port-Index: 04h Port: 03d4h, 03b4h
usage: Start horizontal retrace
Description: Character at which horizontal retrace starts
------------------------------------------------------------
Port-Index: 05h Port: 03d4h, 03b4h
usage: End horizontal retrace
d7 End horizontal blanking bit 5
d6 Horizontal retrace delay
d5 Horizontal retrace delay
d0-d4 End horizontal retrace
Description: End horizontal retrace: defines the character at
which horizontal retrace ends
------------------------------------------------------------
Port-Index: 06h Port: 03d4h, 03b4h
usage: Vertical total
Description: Total number of horizontal scan lines minus two
(including blanked and border characters). MSB bits
of this value are in register index 7
------------------------------------------------------------
Port-Index: 07h Port: 03d4h, 03b4h
usage: Overflow register
d7 Vertical retrace start (bit 9)
d6 Vertical display enable end (bit 9)
d5 Vertical total (bit 9)
d4 Line compare (bit 8)
d3 Start vertical blank (bit 8)
d2 Vertical retrace start (bit 8)
d1 Vertical display enable end (bit 8)
d0 Vertical total (bit 8)
------------------------------------------------------------
Port-Index: 08h Port: 03d4h, 03b4h
usage: Preset row scan
d7 Unused
d6 Byte panning control
d5 Byte panning control
d0-d4 Preset row scan
Description: Byte panning control: is used to control byte
panning. This register together with attribute
controller register 13h allows for up to 31 pixels of
panning in double word modes
Preset row scan: Which character scan line is the
first to be displayed
------------------------------------------------------------
Port-Index: 09h Port: 03d4h, 03b4h
usage: Maximum scan line/Character height
d7 double scan
d6 bit d9 of line compare register
d5 bit d9 of start vertical blank register
d0-d4 Maximum scan line
Description: d0-d5=Character height-1, only in textmodes
------------------------------------------------------------
Port-Index: 0ah Port: 03d4h, 03b4h
usage: Cursor start
d7,d6 Reserved (0)
d5 Cursor off
d4-d0 Cursor start
Description:
------------------------------------------------------------
Port-Index: 0bh Port: 03d4h, 03b4h
usage: Cursor end
d7 reserved
d6,d5 Cursor skew
d4-d0 Cursor end
Description:
------------------------------------------------------------
Port-Index: 0ch Port: 03d4h, 03b4h
usage: Start address high
------------------------------------------------------------
Port-Index: 0dh Port: 03d4h, 03b4h
usage: Start address low
Description: Determine the offset in display memory to be
displayed on the upper-left corner on the screen
------------------------------------------------------------
Port-Index: 0eh Port: 03d4h, 03b4h
usage: Cursor location (high byte)
------------------------------------------------------------
Port-Index: 0fh Port: 03d4h, 03b4h
usage: Cursor location (low byte)
Description: Where the cursor is displayed on screen
------------------------------------------------------------
Port-Index: 10h Port: 03d4h, 03b4h
usage: Vertical retrace start
Description: 8 bits out of 10
------------------------------------------------------------
Port-Index: 11h Port: 03d4h, 03b4h
usage: Vertical retrace end
d7 Write protect CRTC register 0 to 7
d6 refresh cycle select
d5 enable vertical interrupt (when 0)
d4 Clear vertical interrupt (when 0)
d0-d3 Vertical retrace end
------------------------------------------------------------
Port-Index: 12h Port: 03d4h, 03b4h
usage: Vertical display enable end
Description: eight LSB bits out of ten-bit value which define
scan line minus one at which the display ends.
The other two are in CRTC register index 7
------------------------------------------------------------
Port-Index: 13h Port: 03d4h, 03b4h
usage: Offset / Logical screen width
Description: Logical screen width between successive scan lines
------------------------------------------------------------
Port-Index: 14h Port: 03d4h, 03b4h
usage: Underline location register
d7 Reserved
d6 Double word mode
d5 count by 4
d0-d4 Underline location
Description: Underline location: Monochrome textmode only
------------------------------------------------------------
Port-Index: 15h Port: 03d4h, 03b4h
usage: Start vertical blanking
Description: eight LSB bits of ten-bit value minus one which
define at which scan line the vertical blanking
starts. The other two bits are in CRTC registers
index 7 and 9
------------------------------------------------------------
Port-Index: 16h Port: 03d4h, 03b4h
usage: End vertical blanking
Description: eight LSB bits of a value which determine the scan
line after which vertical blanking ends.
------------------------------------------------------------
Port-Index: 17h Port: 03d4h, 03b4h
usage: Mode control register
d7 Enable vertical and hoizontal retrace
d6 Byte mode (1), word mode (0)
d5 Address wrap
d4 Reserved
d3 count by 2
d2 multiple vertical by 2 (use half in
CRTC (8,10,12,14,18)
d1 Select row scan counter (not used)
d0 compatibilty mode support (enable interleave)
------------------------------------------------------------
Port-Index: 18h Port: 03d4h, 03b4h
usage: Line compare register
Description: Split screen, 8 bit value out of a ten-bit value
------------------------------------------------------------
Port-Index: 00h Port: 03c4h
usage: Reset register
d7-d2 Reserved
d1 Synchronous reset
d0 Asynchronous reset
Description: Synchr. when set to zero, will halt and reset
the sequencer at the end of its current cycle
Asyncht. when set to zero, will immediatly halt
and reset the sequencer. Data can be loss.
------------------------------------------------------------
Port-Index: 01h Port: 03c4h
usage: Clock mode register
d7,d6 Reserved
d5 display off
d4 Allow 32-bit Fetch (not used in standard modes)
d3 Divide dot clock by 2 (used in some 320*200 modes)
d2 Allow 16-bit fetch (used in mon graphics modes)
d1 Reserved
d0 Enable (0) 9 dot characters (mono text and 400-line)
Description: Display off: Will blank screen and give the cpu
uninterrupted access the display memory.
------------------------------------------------------------
Port-Index: 02h Port: 03c4h
usage: Color plane write enable register
d7,d6 Reserved
d3 Plane 3 Write enable
d2 Plane 2 Write enable
d1 Plane 1 Write enable
d0 Plane 0 Write enable
Description:
------------------------------------------------------------
Port-Index: 03h Port: 03c4h
usage: Character generator select register
d7,d6 Reserved
d5 Character generator table select A (MSB)
d4 Character generator table select B (MSB)
d3,d2 Character generator table select A
d1,d0 Character generator table select B
Description: This register is only of interest if your software
will be using multiple character sets. Either one
or two character sets can be active. Table A selects
the charcater with attribute d3 set to zero and
Table B is the one with d3 set to one.
------------------------------------------------------------
Port-Index: 04h Port: 03c4h
usage: Memory mode register
d4-d7 Reserved
d3 Chain 4 (address bits 0&1 to select plan, mode 13h)
d2 Odd/even (address bit 0 to select plane 0&2 or
1&3 text modes)
d1 Extended memory (disable 64k modes)
d0 Reserved
Description:
------------------------------------------------------------
Port-Index: 00h Port: 03ceh
usage: Set / Reset register
d7-d4 Reserved (0)
d3 Fill data for plane 3
d2 Fill data for plane 2
d1 Fill data for plane 1
d0 Fill data for plane 0
------------------------------------------------------------
Port-Index: 01h Port: 03ceh
usage: Set / Reset enable register
d7-d4 Reserved (0)
d3 enable set/reset for plane 3 (1 = enable)
d2 enable set/reset for plane 2 (1 = enable)
d1 enable set/reset for plane 1 (1 = enable)
d0 enable set/reset for plane 0 (1 = enable)
Description: Set/Reset enable defines which memory planes will
receive fill data from set/reset register. Any plane
that is disable for set/reset will be written with
normal processor output data
------------------------------------------------------------
Port-Index: 02h Port: 03ceh
usage: Color compare register
d7-d4 Reserved
d3 Color compare value for plane 3
d2 Color compare value for plane 2
d1 Color compare value for plane 1
d0 Color compare value for plane 0
Description: one indicate that color is the same
------------------------------------------------------------
Port-Index: 03h Port: 03ceh
usage: Data rotate / Function select register
d7-d5 Resrved (0)
d4,d3 Function select
d2-d0 Rotate count
d4 d3 Function
0 0 Write data unmodified
0 1 Write data ANDed with processor latches
1 0 Write data ORed with processor latches
1 1 Write data XORed with processor latches
Description: Rotation is made before writing data
------------------------------------------------------------
Port-Index: 04h Port: 03ceh
usage: Read plane select register
d7-d2 Reserved (0)
d1,d0 Defines color plane for reading (0-3)
Description: Doesnt matter in color compare mode
------------------------------------------------------------
Port-Index: 05h Port: 03ceh
usage: Mode register
d7 Reserved (0)
d6 256-colour mode
d5 Shift register mode
d4 Odd / Even mode
d3 Color compare mode enable (1 = enable)
d2 Reserved (0)
d1,d0 Write mode
d1 d0 Write mode
0 0 Direct write (data rotate, set/reset may apply)
0 1 Use processor latches as write data
1 0 Color plane n (0-3) is filled with the value of
bit n in the write data
1 1 Use (rotated) write data ANDed with Bit mask as
bit mask. Use set/reset as if set/reset was
enable for all planes
Description:
------------------------------------------------------------
Port-Index: 06h Port: 03ceh
usage: Miscellaneous register
d7-d4 Reserved
d3-d2 Memory map
00 = A000h for 128k
01 = A000h for 64k
10 = B000h for 32k
11 = B800h for 32k
d1 Odd/even enable (used in text modes)
d0 Graphics mode enable
Description: Memory map defines the location and size of the
host window
------------------------------------------------------------
Port-Index: 07h Port: 03ceh
usage: Color don't care register
d7-d4 Reserved (0)
d3 Plane 3 don't care
d2 Plane 2 don't care
d1 Plane 1 don't care
d0 Plane 0 don't care
Description: Color don't care is used in conjunction with color
compare mode. This register masks particular planes
from being tested during color compare cycles.
------------------------------------------------------------
Port-Index: 08h Port: 03ceh
usage: Bitmask register
Description: The bitmask register is used to mask certain bit
positons from being modified.
------------------------------------------------------------
Port-Index: - Port: 03c0h both index and data
usage: d7,d6 Reserved
d5 Palette address source
0 = palette can be modified, screen is blanked
1 = screen is enable, palette cannot be modified
d4-d0 Palette register address
Description: Palette register address selects which register of
the attributes controller will be addres,sed by the
next I/O write cycle
------------------------------------------------------------
Port-Index: 00h-0fh Port: 03c0h
usage: Color palette register
d6,d7 Reserved
d5-d0 Color value
Description: not used in 256 color modes
------------------------------------------------------------
Port-Index: 10h Port: 03c0h
usage: Mode control register
d7 p4,p5 source select
d6 pixel width
d5 Horizontal panning compatibility
d4 Reserved
d3 Background intensify / enable blinking
d2 Line graphics enable (text modes only)
d1 display type
d0 graphics / text mode
Description: p4,p5 source select: selects the source for video
outputs p4 and p5 to the DACs. If set to zero, p4
and p5 are driven from the palette registers (normal
operation). If set to one, p4 and p5 video outputs
come from bits 0 and 1 of the color select register.
pixel width: is set to one in mode 13h (256-color mode)
horizontal panning compatibility: enhances the
operation of the line compare register of the CRT
controller, which allows one section of the screen
to be scrolled while another section remains stationary.
When this bit is set to one, the stationary
section of the screen will also be immune to horizontal
panning.
------------------------------------------------------------
Port-Index: 11h Port: 03c0h
usage: Screen border color
Description: In text modes, the screen border color register
selects the color of the border that sorrounds the
text display area on the screen. This is also referred
to by IBM as overscan. Unfortunately, this feature
does not work properly on EGA displays in 350-line
modes.
------------------------------------------------------------
Port-Index: 12h Port: 03c0h
usage: Color plane enable register
d7,d6 Reserved
d5,d4 Video status mux
d3 Enable color plane 3
d2 Enable color plane 2
d1 Enable color plane 1
d0 Enable color plane 0
Description: The video status mux bits can be used in conjunction
with the diagnostic bits of input status register 1
to read palette registers. For the EGA, this is the
only means available for reading the palette registers.
Enable color planes can be used to enable or disable
color planes at the input to the color lockup table.
A zero in any of these bit positions will mask the
data from that color plane. The effect on the display
will be the same as if that color plane were cleared
to all zeros.
------------------------------------------------------------
Port-Index: 13h Port: 03c0h
usage: Horizontal panning register
d7-d4 reserved
d3-d0 Horizontal pan
Description: Horizontal pan allows the display to be shifted
horizontally one pixel at a time.
d3-d0 Number of pixels shifted to the left
0+,1+,2+ 13h Other modes
3+,7,7+
0 1 0 0
1 2 1 -
2 3 2 1
3 4 3 -
4 5 4 2
5 6 5 -
6 7 6 3
7 8 7 -
8 9 - -
------------------------------------------------------------
Port-Index: 14h Port: 03c0h
usage: Color select register
d7-d4 Reserved
d3 color 7
d2 color 6
d1 color 5
d0 color 4
Description: Color 7 and color 6: are normally used as the high
order bits of the eight-bit video color data from the
attribute controller to the DACs. The only exceptions
are 256-color modes
Color 5 and color 4: can be used in place of the p5
and p6 outputs from the palette registers (see mode
control register - index 10h). In 16-color modes, the
color select register can be used to rapidly cycle
between sets of colors in the video DAC.
------------------------------------------------------------
Port-Index: - Port: 03c6h
usage: Pixel mask register
Description: ???
------------------------------------------------------------
Port-Index: - Port: 03c7h
usage: DAC state register (read-only)
Description: if d0 and d1 is set to zero it indicates that
the lookup table is in a write mode
------------------------------------------------------------
Port-Index: - Port: 03c7h
usage: Lookup table read index register (Write only)
Description: Used when you want to read the palette (set color
number)
------------------------------------------------------------
Port-Index: - Port: 03c8h
usage: Lookup table write index register
Description: Used when you want to change palette (set color
number)
------------------------------------------------------------
Port-Index: - Port: 03c9h
usage: Lookup table data register
Description: Read color value (Red-Green-Blue) or write same data.
------------------------------------------------------------