Today I'll cover how to fade the palette in and out, how to display text in
graphicmode, how to use precalculated lists and how to use a virtual screen.

I told you how to set the palette in part 1 of the demoschool, to fade the
palette is similar to setting the palette repeaditly with slightly different
values. A common trick is to set all the colors of the palette to black, 
then draw something to the screen and finally fade the palette in. That
way the whole picture will fade in simultainously no matter how much is
on the screen.

Like you remember, the palette is set through ports 3c8h and 3c9h.
The index of the color that shall be set first is written to port 3c8h.
Then the red, green and blue values are written to port 3c9h. After 3 bytes
have been written to port 3c9h the colorindex is automatically increased.
To set the entire palette to black, first write 0 to port 3c8h. Then write 
0 to port 3c9h 256*3 times.

Here's an example in C:

void blackpal(void)
{
int i;
outp(0x3c8,0);
for(i=0;i<256*3;i++) outp(0x3c9,0);
}

To fade the palette in, the palette is send as parameter to the function that 
will fade the palette, let's call it fade_in. That function should also have a
local array that will hold the temporary values of the palette during the fade.
First set all colors in the local palette to 0. Then enter a loop that will
set the local palette, increase the values of the local palette until they 
have reached their "right" values. That will be maximum 64 times since the
red green and blue values can be only 63 or less. Before setting the palette
you should call wtsync, that waits for the vertical retrace, to avoid snow
due to bad syncronisation with the electron beam.

Here's a fade_in funtion in C:

//will fade in the palette palett
void fade_in(unsigned char*palett)
{
int i,j;
unsigned char pal[256*3];       //local array

for(i=0;i<256*3;i++) pal[i]=0;  //set entire pal to 0
for(j=0;j<64;j++)               //fade in 64 steps
{
outp(0x3c8,0);          //Every step begins with setting color 0

wtsync();               //call wtsync to avoid snow
wtsync();               //call it another time to get a slower fade
//You could skip the second call to wtsync for a faster fade

        for(i=0;i<256*3;i++) //loop through all bytes in the palette
        {
                outp(0x3c9,pal[i]);             //send a byte to 3c9h
                if(pal[i]<palett[i]) pal[i]++;  //compare with final value
        }                                       //if it's less increase it
}
}

This function fades from black to the palette. Another variant is to fade
from the current palette to the palette that will be set. In that case set
pal to the current palette with getpal instead of black.
And add in the inner loop:        

        if(pal[i]<palett[i]) pal[i]++;
        if(pal[i]>palett[i]) pal[i]--;

In this case the color will go towards palette[i] even if it's greater.
the getpal function is in the source code.

Another fade would be to fade from the current palette to black and from the
current palette to white, this should be real simple if you understand the
functions above.



To write text to the screen in graphic mode is not as simple as in textmode.
You could use printf but please don't, it's so slooow.
Instead make an array where you store the characters you intend to use.
The easiest way is to let one byte represent one pixel. If one character is
8*8 pixels, that makes 8*8 = 64 bytes per character in the array.
In the source I've made a global array chars64 with the ascii-chars 32 . . 90.
That is Space to Z.
The question is how to get hold of the patterns of the characters. You could
draw them yourself in a paint program and store them on disk or you could 
read them from the BIOS dataarea where all the patterns are stored.
This time I'll read'em from BIOS. The problem is that every character is stored
with 1 bit per pixel, that is 8 bytes per character and we want them 64 bytes
per character. 

Ex : Letter A in the BIOS dataarea
Byte            Binrt                          Decimal
BYTE 0:         0 0 0 0 0 0 0 0         =       0
BYTE 1:         0 0 0 1 1 0 0 0         =       24
BYTE 2:         0 0 1 0 0 1 0 0         =       36
BYTE 3:         0 1 0 0 0 0 1 0         =       66
BYTE 4:         0 1 1 1 1 1 1 0         =       126
BYTE 5:         0 1 0 0 0 0 1 0         =       66
BYTE 6:         0 1 0 0 0 0 1 0         =       66
BYTE 7:         0 0 0 0 0 0 0 0         =       0

A 0 means the backgroundcolor and a 1 means the foregroundcolor. For every
bit in the pattern we want a byte. That's no problem, just shift the bits
one by one and if the shifted bit was a 0 set the respective byte in chars64
to 0 else set it to the foregroundcolor.
The foregroundcolor can be any of 256 possible colors. That means that the
pixels in the character does not have to be in the same color. I've chosen to
make the top row of every character bright and then I subtract 3 for every row
making the letters darker and darker for every row.

Data for BIOS chartable begins at address F000:FA6E
Every character is 8 bytes and they are in the same order as they appear in 
the ascii-table. The letter A has acii-value 65. 
The pattern for A is therefore at address F000:(FA6E + 65*8). 
This should be enough to understand the function getbioschars in the source.

To Display the characters I've made two functions. Showchar draws one single
character to the screen (the character should be defined in chars64 or
else only crap will be drawn to the screen). Show char draws all pixels
even the background color. Putcharonflag draws a character in the array flag.
It doesn't draw the pixel if it's 0 that makes the characters drawn with
putcharonflag transparent.



Lookup-tables are one of the most used and also most effective optimizing 
tricks in demo and game programming that require real-time prestanda. 
The idea is to calculate as much as possible in the initialization phase 
(beginning) of the program and save the results in arrays (lookup-tables). 
That way the program don't  have to make the calculations in the main-loop 
of the program, only lookup the results in the lookup-tables (that's where 
the name comes from).
The classical example of a lookuptable is a sinus-table like I used in the
example program. The program draws a flag on the screen and then moves it
in sine-waves in both x- and y-direction. All movements of the flag are
precalculated and put in the array sinlist. If the amplitude of the waves is
20 pixels up and down, then the calculation of the sinlist is done like this:

        for(i=0;i<xxx;i++) sinlist[i]=sin(K*i)*20;

This will make sinlist[i] vary between -20 and +20.
K and xxx are constants, xxx is the length of the list and K determines the
length of the waves (period of the wave).

At the same time as the flag moves in waves I draw two texts on the screen
and the texts also moves in waves (movements come from the same sinlist). 
Even the color of the flag changes in waves all from the same sinlist.
This way it looks like there's some major math going on but in reality it's
only one precalculated sin-table that does all the work.
The constants are #defined at the top of the code and it's easy to change 
them and see what happens.


This program also uses a virtual screen. A virtual screen is an array in 
memory that can be drawn to without anything beeing spotted on the visible 
screen. When the whole frame is ready-drawn just "flip" the virtual screen 
over to the visible screen and it all appears at once.
In this program the virtual screen is smaller than the visible screen but 
most times they have the same size. Before flipping it's a good idea to call 
wtsync, to avoid snow and flickering.

Some graphicmodes have more than one page, that means that it's possible to
draw to a invisible page and when you're ready make that page the visible
page. This is the same thing as using a virtual screen but you don't have to
allocate any memory for it and the flipping is faster. Multiple pages also
make scrolling a lot easier, but mode 13h doesn't normally support multiple 
pages. Although it is possible to screw with the port's of the graphic card 
to make it support multiple pages. This is known as unchained mode 13h or 
Mode X (resolution of real mode X is actually 320*240). 
I'll cove these modes later (maybe part 5 or 6).


Demo2.c contains the sourcecode for the flag and text.
onlyflag.c is shorter (only the flag) and perhaps easier to understand.


This part have been perhaps too complex for the beginner so if you don't
understand everything dont be sad, next part will be easier. It will cover
sprites and linking pure assembly routines to C.


PS      The program is still slow even though it uses precalculated tables.
        It would be faster with 386-specific instructions but my compiler
        won't allow it. If the assembly routines are written separatly
        and linked with the c-program you can use 386-specific instructions.
        I'll cover that next time.      DS


s-mail: Albert Veli
        spisringsg. 9
        724 76 Vsters

mail:   dat94avi@idt.mdh.se
