				VGA Hardware Tricks
				Part 2 of 6

Introduction:

Welcome to VGA Hardware Tricks, a six-part series written by
Trixter/Hornet.  In this series, I'll be exploring ways you can push VGA
harder to achieve new effects.  The emphasis of this series is twofold:

	- The techniques discussed will work on any *standard* VGA card.
	(No SVGA or VESA video cards are necessary, but these techniques
	will work on those cards as well.)

	- The techniques discussed require very little calculation, so
	they will work on slower computers.  (Some techniques, however,
	requires a lot of CPU *attention*, which means that while the
	effects are happening, they can't be disturbed by other
	calculations, etc.  Good Assembler programmers might be able to
	get around this, however.)

This series is for intermediate to advanced coders, so there are a
couple of prerequisites you should meet:  Example code will be given in
assembler and Pascal, so familiarity with those languages will be
helpful when looking at the example code; also, a familiarity with Mode
X (unchained VGA) is required, as procedures like changing video
resolutions will be discussed.

This series covers six topics:

	- Crossfading 16-color pictures
	- Crossfading 256-color pictures	(this article)
	- More than 256 colors: 12-bit color
	- More than 256 colors: 18-bit color
	- Copper effects in text mode
	- Displaying graphics in text mode

Description:

As covered in the first installment of this series, Crossfading is a
clever effect that, to my knowledge, was displayed first in an EMF demo
in 1991.  Fading in/out a palette had been used extensively until then,
but crossfading was much more impressive.  For anyone who's never seen
crossfading, it works just like crossfades do in movies or television:
A picture on the screen gradually fades into another picture until only
the second picture is displayed.

However, as we discovered last time, there's no easy way to cross-fade
pictures with more bits that, when combined, exceed 8 (the same amount
of bits in a single 256-color pixel).  What if you want to crossfade pictures
with all 256 colors?  You can't fit 16 bits of information into 8!

One of the solutions (the one we'll be covering in this article) uses
probably the most timing-dependant of all the tricks we'll be covering:
Page flipping.  Page flipping itself isn't time dependant, but when you have
to change the entire palette every page flip, you'll find that you are paying
very close attention to the state of VGA's vertical retrace.  :-)

Overview:

Crossfading 256 color pictures is done in a very brute-force way.  To
understand it, let's look at first how to display *both* pictures at the same
time:

	- Switch into ModeX
	- Load one picture onto the first video page
	- Load the second picture onto the second video page
	- Enter a loop:
		- Switch to the first video page
		- Load/Display the first picture's palette
		- Switch to the second video page
		- Load/Display the second picture's palette
	- End loop when key is pressed

This will display both pictures at the same time (although not very
nicely).  To crossfade, you can start the second picture's palette at
all black; then (while flipping pages) lower the first palette to black
and the second picture's palette from black to itself.  If your
programming skills are good and you have a fast machine, you can pull
this off without any assembler programming.  (To make this work on a
slow machine, we'll have to simulate a vertical-retrace interrupt, which
I'll define later.)

If you stopped reading this article right now and did what I just
described, what do you think you'd see?  Well, unless your monitor is a
piece of crap, you'd see a great deal of flickering.  This is because
your refresh rate in 320x200 mode, 70 Hz, is *halved* by trying to
display two pictures at the same time, bringing it down to 35 Hz (your
display is displaying a picture, then black, then a picture, then black,
etc.)  If we want to avoid inducing epileptic seizures, we'll have to do
something different.  For this particular method, we'll try the
crossfading with a raster.

Let's look at a pseudocode example:

1. Set the video mode to 320x400.

2. Load the first picture into video memory so that the pixels are set
   with raster... like this:

   x x x x
    x x x x
   x x x x
    x x x x

   So every other pixel in picture is "halved".
   Use video page 0.

3. Load the second picture into the opposite raster, like this:

    x x x x
   x x x x
    x x x x
   x x x x

   Use video page 1.

4. Set palette correctly for the first picture, and set page 0 as visual.
5. Wait for vertical retrace.
6. Set palette to totally black and page 1 as visual.
7. Wait for vertical retrace.

8. Repeat from number four until you want to start fading.

9. a=0
10. Set palette for first picture faded (100-a)% towards black, vis.page 0
11. Vertical retrace.
12. Palette for second picture faded a% towards the correct palette, vis.pg 1
13. Vertical retrace.
14. Increase a until it reaches 100.

15. Voila, you're done.

This method fools our persistance of vision (how our brain "fills in"
missing visual information) significantly enough to reduce the flicker
that we mentioned before, but still has one very bad drawback: the
picture's colors are dimmed to 25% from the original because half of the
time you're flipping pages, you're displaying a color pixel, then a
totally black one, then color, then black, etc.  With bright colors or
white, the flicker is extremely bad.  So, how to combat that?

Instead of swapping between a color and a black pixel, swap between a
color and a "shadow" pixel that tries to resemble the color one.
There's not enough palette entries to make a color "shadow" picture (it
would take anywhere from 48-64 palette entries, which steals away from
the 256 colors in the picture), but since our eyes are more sensitive to
light, we can create a 16-element grayscale picture and still have 240
colors left over for the picture.  Not a bad compromise.  (So, you can
see that I lied a bit--we're crossfading 240-color pictures, not
256-color pictures.)

HOWEVER, this adds a third problem:  When flipping between a color and a
gray pixel, the colors are now *lightened* by about 25%.  The brightness
of the colors (the "luminance") is back to normal, but it looks like all
the colors are "washed out".  So, to combat this, we pre-process all the
pictures in a batch image conversion program like Paint Shop Pro,
raising the color saturation (the color "strength") by about 75%.

Implement the above system and you might get an unpleasant surprise:
Your video card is too slow to switch video pages *and* update all 256
colors of the palette every frame.  This is seen as bad flickering.  If
there was only some way we could start our processing *right before* the
beam goes into vertical retrace... Well, older video cards (notably EGA)
used IRQ 2 as the vertical-retrace interrupt:  When IRQ 2 "fired", you
knew you were in vertical retrace, and you could attach any routine to
that interrupt to run some code.  This was convienent because you could
be doing other things (like normal game calculations) and you didn't
have to worry about missing the retrace, and subsequently, screwing up
your animation/palette/whatever.

Later video cards (like VGA), sadly, discontinued this interrupt.  In
order to do the same thing (have code executed automatically when
vertical retrace happens), we'll have to simulate that interrupt
ourself.  Provided in the code example (see below) is code to simulate a
vertical retrace interrupt, the use of which allows us to make our
crossfading technique work even on slow video cards and slow machines.
(The actual method of simulating a vertical-retrace interrupt will not
be covered here; it is beyond the scope of this article; and,
admittedly, beyond the scope of this programmer.  :-)

Code:

Code that acheives this effect is available on ftp.cdrom.com in the
directory /pub/demos/hornet/demonews/vgahard in the file vgahard2.zip.
To compile the code directly, you'll need Turbo Pascal 7.0 or later.
(The code can be compiled on eariler compilers as well, but some slight
modification might be necessary.)

Notes:

While the idea for crossfading 256-color pictures was mine, none of it
would have been possible without Jussi Lahdenniemi / Virtual Visions.
Without his ideas on how to fix the flickering and his vertical retrace
interrupt code, it would not have become a reality.  Thanks, Jussi!

Next time:

I think we've taken crossfading to it's maximum extent without using a
ton of real-time CPU calculation for the effect.  But we've discovered
something very interesting, haven't we?  By flipping between pages
quickly, persistence of vision (how our brain "fills in" missing visual
information) can be fooled into not seeing flicker--do you think it can
be tricked into seeing more colors as well?

Guess what: It can!  The next two installments in VGA Hardware Tricks
cover displaying pictures with much more than 256 colors--on a
*standard* VGA card.  Don't miss it!
